db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r752813 - in /db/derby/code/trunk/java: drda/org/apache/derby/impl/drda/DDMReader.java testing/org/apache/derbyTesting/functionTests/tests/derbynet/PrepareStatementTest.java
Date Thu, 12 Mar 2009 09:33:55 GMT
Author: kahatlen
Date: Thu Mar 12 09:33:47 2009
New Revision: 752813

URL: http://svn.apache.org/viewvc?rev=752813&view=rev
Log:
DERBY-4088: DDMReader readBytes ArrayIndexOutOfBoundsException

When ensureBLayerDataInBuffer() calls compressBLayerData() the number
of bytes in the buffer is reduced (header bytes are stripped out) and
there might be too little data in the buffer when it returns. This
patch fixes the problem by ensuring that compressBLayerData() fills
the buffer with enough extra bytes to compensate for the removal of
the header bytes.

Modified:
    db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/PrepareStatementTest.java

Modified: db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java?rev=752813&r1=752812&r2=752813&view=diff
==============================================================================
--- db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java (original)
+++ db/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java Thu Mar 12 09:33:47
2009
@@ -1695,21 +1695,23 @@
 		throws DRDAProtocolException
 	{
 
-		
+        // Offset from the start of the valid region of the byte buffer,
+        // pointing to the start of the DSS we're looking at.
+        int tempOffset = 0;
+
 		// jump to the last continuation header.
-		int tempPos = 0;
 		for (int i = 0; i < continueDssHeaderCount; i++) 
 		{
 			// the first may be less than the size of a full DSS
 			if (i == 0) 
 			{
 				// only jump by the number of bytes remaining in the current DSS
-				tempPos = pos + dssLength;
+				tempOffset = dssLength;
 			}
 			else 
 			{
 				// all other jumps are for a full continued DSS
-				tempPos += DssConstants.MAX_DSS_LENGTH;
+				tempOffset += DssConstants.MAX_DSS_LENGTH;
 			}
 		}
 
@@ -1725,8 +1727,13 @@
 
 		for (int i = 0; i < continueDssHeaderCount; i++) 
 		{
-			continueHeaderLength = ((buffer[tempPos] & 0xff) << 8) +
-				((buffer[tempPos + 1] & 0xff) << 0);
+            // Get the length of the DSS. Make sure that we have enough data
+            // in the buffer to actually see the length (may not have enough
+            // bytes if this is not the first DSS).
+            ensureALayerDataInBuffer(tempOffset + 1);
+            continueHeaderLength =
+                    ((buffer[pos + tempOffset] & 0xff) << 8) +
+                    (buffer[pos + tempOffset + 1] & 0xff);
 
 			if (i == 0) 
 			{
@@ -1746,6 +1753,13 @@
 				}
 				// the very first shift size is 2
 				shiftSize = 2;
+
+                // Make sure we have all of the last DSS in the buffer
+                // (DERBY-4088). Since we look at the last DSS first,
+                // we don't need to do this for the other DSSs, as they
+                // will also be fetched into the buffer when we fetch the
+                // last one.
+                ensureALayerDataInBuffer(tempOffset + continueHeaderLength);
 			}
 			else 
 			{
@@ -1784,12 +1798,12 @@
 			else
 				bytesToShift = dssLength;
 
-			tempPos -= (bytesToShift - 2);
-			System.arraycopy(buffer, tempPos - shiftSize, buffer, tempPos,
-							 bytesToShift);
+			tempOffset -= (bytesToShift - 2);
+			System.arraycopy(buffer, pos + tempOffset - shiftSize,
+                             buffer, pos + tempOffset, bytesToShift);
 		}
 		// reposition the start of the data after the final DSS shift.
-		pos = tempPos;
+		pos += tempOffset;
 		dssLength += newdssLength;
 	}
 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/PrepareStatementTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/PrepareStatementTest.java?rev=752813&r1=752812&r2=752813&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/PrepareStatementTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/PrepareStatementTest.java
Thu Mar 12 09:33:47 2009
@@ -32,11 +32,14 @@
 
 import java.math.BigDecimal;
 import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.Arrays;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
+import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetStream;
 import org.apache.derbyTesting.junit.BaseJDBCTestCase;
 import org.apache.derbyTesting.junit.TestConfiguration;
 import org.apache.derbyTesting.junit.JDBC;
@@ -1296,4 +1299,31 @@
         for (int i = 0; i < length; ++i) buf.append("X");
         return buf.toString();
     }
+
+    /**
+     * Test fix for DERBY-4088 where an ArrayIndexOutOfBoundsException was
+     * thrown by DDMReader.readBytes() when reading a BLOB value whose length
+     * was close to the maximum length of a DSS.
+     */
+    public void testReadBlobCloseToMaxDssLength() throws Exception {
+        final int length = 32766; // max DSS length is 32767
+
+        // Create test data with the requested length
+        DataInputStream stream1 =
+                new DataInputStream(new LoopingAlphabetStream(length));
+        byte[] bytes = new byte[length];
+        stream1.readFully(bytes);
+
+        // See if the test data can be sent to the server and back with
+        // no errors.
+        PreparedStatement ps = prepareStatement("values cast(? as blob)");
+        ps.setBytes(1, bytes);
+        ResultSet rs = ps.executeQuery();
+        assertTrue("empty result set", rs.next());
+        InputStream stream2 = rs.getBinaryStream(1);
+        assertEquals(new LoopingAlphabetStream(length), stream2);
+        assertFalse("too many rows", rs.next());
+        rs.close();
+    }
+
 }



Mime
View raw message