db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Knut Anders Hatlen (JIRA)" <j...@apache.org>
Subject [jira] Updated: (DERBY-4088) DDMReader readBytes ArrayIndexOutOfBoundsException
Date Wed, 11 Mar 2009 16:58:50 GMT

     [ https://issues.apache.org/jira/browse/DERBY-4088?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel

Knut Anders Hatlen updated DERBY-4088:

    Attachment: derby-4088.diff

Here's a first attempt to fix the bug. I haven't investigated why the
client splits the value yet, but since the protocol seems to allow it,
it seems like we should fix it on the server anyway.

The important part of the patch is that it adds calls to
ensureALayerDataInBuffer() two places in compressBLayerData() to
ensure that we never try to access bytes that haven't been buffered
yet. compressBLayerData() takes multiple DSSs and concatenates them so
that they look like a single DSS for the caller. Since the new calls
to ensureALayerDataInBuffer() ensures that we have all the bytes for
the low-level DSSs in the buffer, it means that we also have all the
bytes needed to construct the concatenated "super DSS" created by
compressBLayerData(). This again ensures that when
ensureBLayerDataInBuffer() returns in readBytes(), we have the entire
byte string in the buffer, and System.arraycopy() won't go out of

(Some might find it a bit confusing that compressBLayerData() calls
ensureALayerDataInBuffer() and not ensureBLayerDataInBuffer(). The
explanation is that ensureBLayerDataInBuffer() uses
ensureALayerDataInBuffer() as a lower-level primitive to actually
fetch the physical bytes, whereas the Layer B method provides a
higher-level logical view of those bytes. Representing a sequence of
DSSs as a single DSS is one example of this. compressBLayerData() is
performing work for ensureBLayerDataInBuffer() to turn the physical
view of the bytes into the logical view, and therefore needs to use
the Layer A methods that give the physical view.)

Now, the use of ensureALayerDataInBuffer() in compressBLayerData()
made it necessary to make some more changes. compressBLayerData() has
a local variable called tempPos which specifies a position in the read
buffer. This position variable is used to access parts of the read
buffer without destructively skipping bytes up to the interesting
portion of the buffer. This is effectively the same as the position of
the first valid byte in the read buffer plus an offset, and it depends
on the position of the first valid byte being constant throughout the

However, ensureALayerDataInBuffer() may shift bytes to the left in
order to free up space at the end of the buffer. Then the position of
the first valid byte will change, and tempPos will need to be updated
accordingly. To compensate for this shift, I renamed the tempPos
variable to tempOffset and replaced all occurrences of tempPos with
(pos + tempOffset). This means that the local variable is just an
offset from the start of the valid region of the buffer, and it
doesn't change even if the valid region is shifted left or
right. Since pos is added to the offset each time it is used, we'll
automatically compensate for the shift.

I haven't run the full regression test suite yet, but I have added a
test case to derbynet/PrepareStatementTest that fails with an
ArrayIndexOutOfBoundsException without the fix and passes with the

> DDMReader readBytes ArrayIndexOutOfBoundsException
> --------------------------------------------------
>                 Key: DERBY-4088
>                 URL: https://issues.apache.org/jira/browse/DERBY-4088
>             Project: Derby
>          Issue Type: Bug
>          Components: Network Server
>    Affects Versions:
>         Environment: CentOS 5, java 1.6.0_11
>            Reporter: Urban Widmark
>            Assignee: Knut Anders Hatlen
>         Attachments: derby-4088.diff, derby-ddm.patch, DerbyBug.java
> DDMReader.readBytes(int length) checks the length vs DssConstants.MAX_DSS_LENGTH, but
ignores the fact that the buffer position "pos" might not be 0. If pos is non-zero then the
pos + length can be larger than the size of "buffer" causing an ArrayIndexOutOfBoundsException.
> For me this happened when sending a BLOB that was 32766 bytes long. The value of pos
was 2 in that method.

This message is automatically generated by JIRA.
You can reply to this email to add a comment to the issue online.

View raw message