Skip to content

java.lang.ArrayIndexOutOfBoundsException at CBORGenerator.java:548 #62

@mlmitch

Description

@mlmitch

I am encountering index out of bound exceptions at CBORGenerator.java:548 when performing serialization with a new ObjectMapper(new CBORFactory()) instance. I haven't done a full investigation of the cause since calls to CBORGenerator::writeStartObject are very stateful. Here is the offending function.

@Override
// since 2.8
public final void writeStartObject(Object forValue) throws IOException {
    _verifyValueWrite("start an object");
    JsonWriteContext ctxt = _writeContext.createChildObjectContext();
    _writeContext = ctxt;
    if (forValue != null) {
        ctxt.setCurrentValue(forValue);
    }
    if (_elementCountsPtr > 0) {
        _elementCounts[_elementCountsPtr++] = _currentRemainingElements;
    }
    _currentRemainingElements = INDEFINITE_LENGTH;
    _writeByte(BYTE_OBJECT_INDEFINITE);
}

An example error producing call has _elementCountsPtr = 11 and _elementCounts.length = 10. My guess at a solution and my current workaround is to add a safety check like in CBORGenerator::writeStartArray. Here is that function.

@Override
public void writeStartArray(int elementsToWrite) throws IOException {
    _verifyValueWrite("start an array");
    _writeContext = _writeContext.createChildArrayContext();
    if (_elementCounts.length == _elementCountsPtr) { // initially, as well as if full
        _elementCounts = Arrays.copyOf(_elementCounts, _elementCounts.length+10);
    }
    _elementCounts[_elementCountsPtr++] = _currentRemainingElements;
    _currentRemainingElements = elementsToWrite;
    _writeLengthMarker(PREFIX_TYPE_ARRAY, elementsToWrite);
}

As you can see, the function resizes the _elementCounts array when required. I don't know what kind of coding styles you want to employ, but I would change the offending section in every writeStartArray and writeStartObject overload to read:

    if (_elementCounts.length <= _elementCountsPtr) { // less than or equal to catch more bad cases
        //use _elementCountsPtr for new size to guarantee the array is big enough for this call
        _elementCounts = Arrays.copyOf(_elementCounts, _elementCountsPtr+10); 
    }
    if (_elementCountsPtr > 0) { //guard for negative indexes
        _elementCounts[_elementCountsPtr++] = _currentRemainingElements;
    }
    

Sorry I couldn't be more helpful with regard to why it is happening. Though I'd be happy to make a pull request with my described solution. Let me know what you think.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions