You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2010/06/29 13:46:17 UTC

svn commit: r958939 - /db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java

Author: kristwaa
Date: Tue Jun 29 11:46:16 2010
New Revision: 958939

URL: http://svn.apache.org/viewvc?rev=958939&view=rev
Log:
DERBY-1595: Network server fails with DRDAProtocolException if a BLOB with size 2147483647 is streamed from client 

Switched from int to long when dealing with scalar streams, which can be longer
than Integer.MAX_VALUE and cause arithmetic overflow.
Introduced 'nullIndicatorSize' to duplicate less code.

Patch file: derby-1595-2a-client_int_overflow.diff


Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java?rev=958939&r1=958938&r2=958939&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/Request.java Tue Jun 29 11:46:16 2010
@@ -21,18 +21,19 @@
 package org.apache.derby.client.net;
 
 import org.apache.derby.client.am.DateTime;
+import org.apache.derby.client.am.DateTimeValue;
 import org.apache.derby.client.am.DisconnectException;
 import org.apache.derby.client.am.ClientMessageId;
 import org.apache.derby.client.am.SqlException;
 import org.apache.derby.shared.common.reference.SQLState;
+import org.apache.derby.shared.common.sanity.SanityManager;
 import org.apache.derby.iapi.reference.DRDAConstants;
 
 import java.io.BufferedInputStream;
+import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.io.UnsupportedEncodingException;
 
-import java.io.IOException;
-import org.apache.derby.client.am.DateTimeValue;
 
 public class Request {
 
@@ -245,11 +246,11 @@ public class Request {
 	final void writeScalarStream(boolean chained,
                                  boolean chainedWithSameCorrelator,
                                  int codePoint,
-                                 int length,
+                                 long length,
                                  java.io.InputStream in,
                                  boolean writeNullByte,
                                  int parameterIndex) throws DisconnectException, SqlException {
-		
+
 		if (netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRIDDTA ||
 			netAgent_.netConnection_.getSecurityMechanism() == NetConfiguration.SECMEC_EUSRPWDDTA) {
             // DERBY-4706
@@ -297,7 +298,7 @@ public class Request {
 	final private void writePlainScalarStream(boolean chained,
                                               boolean chainedWithSameCorrelator,
                                               int codePoint,
-                                              int length,
+                                              long length,
                                               java.io.InputStream in,
                                               boolean writeNullByte,
                                               int parameterIndex) throws DisconnectException, SqlException {
@@ -309,19 +310,16 @@ public class Request {
 
         // If the Derby specific status byte is sent, the number of bytes to
         // send differs from the number of bytes to read (off by one byte).
-		int leftToRead = length;
-        int bytesToSend = writeEXTDTAStatusByte ? leftToRead + 1 : leftToRead;
+        long leftToRead = length;
+        long bytesToSend = writeEXTDTAStatusByte ? leftToRead + 1 : leftToRead;
 		int extendedLengthByteCount = prepScalarStream(chained,
 													   chainedWithSameCorrelator,
 													   writeNullByte,
                                                        bytesToSend);
-		int bytesToRead;
-				
-		if (writeNullByte) {
-            bytesToRead = Math.min(bytesToSend, DssConstants.MAX_DSS_LEN - 6 - 4 - 1 - extendedLengthByteCount);
-		} else {
-            bytesToRead = Math.min(bytesToSend, DssConstants.MAX_DSS_LEN - 6 - 4 - extendedLengthByteCount);
-		}
+        int nullIndicatorSize = writeNullByte ? 1 : 0;
+        int dssMaxDataLength = DssConstants.MAX_DSS_LEN - 6 - 4 -
+                nullIndicatorSize - extendedLengthByteCount;
+        int bytesToRead = (int)Math.min(bytesToSend, dssMaxDataLength);
 
         // If we are sending the status byte and we can send the user value as
         // one DSS, correct for the status byte (otherwise we read one byte too
@@ -519,11 +517,11 @@ public class Request {
                                  boolean writeNullByte,
                                  int parameterIndex) throws DisconnectException, 
                                                             SqlException{
-        
+
         writeScalarStream(chained,
                           chainedWithSameCorrelator,
                           codePoint,
-                          length * 2,
+                          length * 2L,
                           EncodedInputStream.createUTF16BEStream(r),
                           writeNullByte,
                           parameterIndex);
@@ -553,21 +551,15 @@ public class Request {
     protected final int prepScalarStream(boolean chained,
                                          boolean chainedWithSameCorrelator,
                                          boolean writeNullByte,
-                                         int leftToRead) throws DisconnectException {
-        int extendedLengthByteCount;
-
-        int nullIndicatorSize = 0;
-        if (writeNullByte) {
-            // leftToRead is cast to (long) on the off chance that +4+1 pushes it outside the range of int
-            extendedLengthByteCount = calculateExtendedLengthByteCount((long) leftToRead + 4 + 1);
-            nullIndicatorSize = 1;
-        } else {
-            extendedLengthByteCount = calculateExtendedLengthByteCount(leftToRead + 4);
-        }
+                                         long leftToRead)
+            throws DisconnectException {
+        int nullIndicatorSize = writeNullByte ? 1 : 0;
+        int extendedLengthByteCount = calculateExtendedLengthByteCount(
+                    leftToRead + 4 + nullIndicatorSize);
 
         // flush the existing DSS segment if this stream will not fit in the send buffer
-        // leftToRead is cast to (long) on the off chance that +4+1 pushes it outside the range of int
-        if (10 + extendedLengthByteCount + nullIndicatorSize + (long) leftToRead + offset_ > DssConstants.MAX_DSS_LEN) {
+        if ((10 + extendedLengthByteCount + nullIndicatorSize +
+                leftToRead + offset_) > DssConstants.MAX_DSS_LEN) {
             try {
                 if (simpleDssFinalize) {
                     finalizeDssLength();
@@ -621,7 +613,7 @@ public class Request {
 
     // Writes out a scalar stream DSS segment, along with DSS continuation headers,
     // if necessary.
-    protected final int flushScalarStreamSegment(int leftToRead,
+    protected final int flushScalarStreamSegment(long leftToRead,
                                                  int bytesToRead) throws DisconnectException {
         int newBytesToRead = bytesToRead;
 
@@ -638,7 +630,7 @@ public class Request {
             dssLengthLocation_ = offset_;
             bytes_[offset_++] = (byte) (0xff);
             bytes_[offset_++] = (byte) (0xff);
-            newBytesToRead = Math.min(leftToRead, 32765);
+            newBytesToRead = (int)Math.min(leftToRead, 32765L);
         }
 
         return newBytesToRead;
@@ -675,7 +667,7 @@ public class Request {
      *      {@code writeStatus} is {@code false}
      * @throws DisconnectException if flushing the buffer fails
      */
-    protected final void padScalarStreamForError(int leftToRead,
+    protected final void padScalarStreamForError(long leftToRead,
                                                  int bytesToRead,
                                                  boolean writeStatus,
                                                  byte status)
@@ -1577,24 +1569,22 @@ public class Request {
     }
 
     private void buildLengthAndCodePointForLob(int codePoint,
-                                               int leftToRead,
+                                               long leftToRead,
                                                boolean writeNullByte,
                                                int extendedLengthByteCount) throws DisconnectException {
+        int nullIndicatorSize = writeNullByte ? 1 : 0;
         if (extendedLengthByteCount > 0) {
             // method should never ensure length
             writeLengthCodePoint(0x8004 + extendedLengthByteCount, codePoint);
-
-            if (writeNullByte) {
-                writeExtendedLengthBytes(extendedLengthByteCount, leftToRead + 1);
-            } else {
-                writeExtendedLengthBytes(extendedLengthByteCount, leftToRead);
-            }
+            writeExtendedLengthBytes(
+                    extendedLengthByteCount, leftToRead + nullIndicatorSize);
         } else {
-            if (writeNullByte) {
-                writeLengthCodePoint(leftToRead + 4 + 1, codePoint);
-            } else {
-                writeLengthCodePoint(leftToRead + 4, codePoint);
+            if (SanityManager.DEBUG) {
+                SanityManager.ASSERT(leftToRead +4 + nullIndicatorSize <=
+                        DssConstants.MAX_DSS_LEN);
             }
+            writeLengthCodePoint((int)(leftToRead + 4 + nullIndicatorSize),
+                    codePoint);
         }
 
         // write the null byte, if necessary