This patch fix the Bub #22941.

ChangeLog:
2008-01-24  Ito Kazumitsu  <[EMAIL PROTECTED]>

        Fixes bug #22941
        * java/io/DataInputStream.java(readUTFLong): New method.
        (readUTF): New private method.
        * java/io/DataOutputStream.java(getUTFlength): Made package-private,
        Return type changed to long.
        (writeUTF): Use the new method writeUTFShort.
        (writeUTFShort): New package-private method.
        (writeUTFLong): New package-private method.
        (writeUTFBytes): New private method.
        * java/io/ObjectInputStream.java(parseContent): Separate the
        handling of TC_LONGSTRING from TC_STRING.
        * java/io/ObjectOutputStream.java(writeObject): When to write a
        String, use writeUTFShort or writeUTFLong depending on the byte length.

Index: classpath/java/io/DataInputStream.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/DataInputStream.java,v
retrieving revision 1.31
diff -u -r1.31 DataInputStream.java
--- classpath/java/io/DataInputStream.java      2 Jul 2005 20:32:37 -0000       
1.31
+++ classpath/java/io/DataInputStream.java      24 Jan 2008 15:03:47 -0000
@@ -590,13 +590,56 @@
   public static final String readUTF(DataInput in) throws IOException
   {
     final int UTFlen = in.readUnsignedShort ();
-    byte[] buf = new byte [UTFlen];
+    
+    return readUTF(in, UTFlen);
+  }
+
+  /**
+   * This method is similar to <code>readUTF</code>, but the
+   * UTF-8 byte length is in 64 bits.
+   * This method is not public. It is used by <code>ObjectInputStream</code>.
+   * 
+   * @return The <code>String</code> read
+   *
+   * @exception EOFException If end of file is reached before reading
+   * the String
+   * @exception UTFDataFormatException If the data is not in UTF-8 format
+   * @exception IOException If any other error occurs
+   *
+   * @see DataOutput#writeUTFLong
+   */
+  final String readUTFLong () throws IOException
+  {
+    long l = readLong ();
+    if (l > Integer.MAX_VALUE)
+      throw new IOException("The string length > Integer.MAX_VALUE");
+    final int UTFlen = (int)l;
+    return readUTF (this, UTFlen);
+  }
+
+  /**
+   * This method performs the main task of <code>readUTF</code> and
+   * <code>readUTFLong</code>.
+   *
+   * @param in The <code>DataInput</code> source to read from
+   *
+   * @param len The UTF-8 byte length of the String to be read
+   *
+   * @return The String read from the source
+   *
+   * @exception IOException If an error occurs
+   *
+   * @see DataInput#readUTF
+   */
+  private static final String readUTF(DataInput in, int len) throws IOException
+  {
+    byte[] buf = new byte [len];
 
     // This blocks until the entire string is available rather than
     // doing partial processing on the bytes that are available and then
     // blocking.  An advantage of the latter is that Exceptions
     // could be thrown earlier.  The former is a bit cleaner.
-    in.readFully (buf, 0, UTFlen);
+    in.readFully (buf, 0, len);
 
     return convertFromUTF (buf);
   }
Index: classpath/java/io/DataOutputStream.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/DataOutputStream.java,v
retrieving revision 1.23
diff -u -r1.23 DataOutputStream.java
--- classpath/java/io/DataOutputStream.java     12 Apr 2006 16:19:02 -0000      
1.23
+++ classpath/java/io/DataOutputStream.java     24 Jan 2008 15:03:47 -0000
@@ -379,19 +379,20 @@
 
   /**
    *  Calculate the length, in bytes, of a <code>String</code> in Utf8 format.
+   *  This method is package-private so that <code>ObjectOutputStream</code>
+   *  may use it.  The return type is long so that a long string whose
+   *  Utf8 byte count is 64 bit long may be handled.
    *
    *  @param value The <code>String</code> to measure
    *  @param start String index at which to begin count
    *  @param sum Starting Utf8 byte count
    *
-   *  @throws UTFDataFormatException if result would exceed 65535
    */
-  private int getUTFlength(String value, int start, int sum)
-    throws IOException
+  long getUTFlength(String value, int start, long sum)
   {
     int len = value.length();
 
-    for (int i = start; i < len && sum <= 65535; ++i)
+    for (int i = start; i < len; ++i)
       {
        char c = value.charAt(i);
        if (c >= '\u0001' && c <= '\u007f')
@@ -402,9 +403,6 @@
          sum += 3;
       }
 
-    if (sum > 65535)
-      throw new UTFDataFormatException ();
-
     return sum;
   }
   
@@ -442,10 +440,70 @@
    */
   public final synchronized void writeUTF(String value) throws IOException
   {
+    long l = getUTFlength(value, 0, 0);
+    if (l > 65535)
+      throw new UTFDataFormatException ();
+    writeUTFShort(value, (int)l);
+  }
+
+  /**
+   * This method performs the main task of <code>writeUTF</code>.
+   * This method is package-private because ObjectOutputStream uses it.
+   *
+   * @param value The <code>String</code> to write to the output in UTF format
+   *
+   * @param bytelen The UTF-8 byte length of the <code>String</code>. When
+   * this method is called, the expected byte length must have been calculated
+   * by <code>getUTFlength</code>.
+   *
+   * @exception IOException If an error occurs
+   *
+   * @see DataInput#readUTF
+   */
+  final synchronized void writeUTFShort(String value, int bytelen)
+    throws IOException
+  {
+    writeShort(bytelen);
+    writeUTFBytes(value);
+  }
+
+  /**
+   * This method is similar to <code>writeUTF</code>, but it writes the
+   * UTF-8 byte length in 64 bits.
+   * This method is not public but <code>ObjectOutputStream</code> uses it.
+   *
+   * @param value The <code>String</code> to write to the output in UTF format
+   *
+   * @param bytelen The UTF-8 byte length of the <code>String</code>. When
+   * this method is called, the expected byte length must have been calculated
+   * by <code>getUTFlength</code>.
+   *
+   * @exception IOException If an error occurs
+   *
+   */
+  final synchronized void writeUTFLong(String value, long bytelen)
+    throws IOException
+  {
+    writeLong(bytelen);
+    writeUTFBytes(value);
+  }
+
+  /**
+   * This method performes the main task of <code>writeUTF</code> and
+   * <code>WriteUTFLong</code>, which is to write the UTF-8 byte
+   * sequence to the output.
+   *
+   * @param value The <code>String</code> to write to the output in UTF format
+   *
+   * @exception IOException If an error occurs
+   *
+   */
+  private final synchronized void writeUTFBytes(String value)
+    throws IOException
+  {
     int len = value.length();
     int i = 0;
     int pos = 0;
-    boolean lengthWritten = false;
 
     if (buf == null)
       buf = new byte[512];
@@ -472,14 +530,6 @@
                buf[pos++] = (byte) (0x80 | (0x3f & c));
              }
          }
-       if (! lengthWritten)
-         {
-           if (i == len)
-             writeShort(pos);
-           else
-             writeShort(getUTFlength(value, i, pos));
-           lengthWritten = true;
-         }
        write(buf, 0, pos);
        pos = 0;
      }
Index: classpath/java/io/ObjectInputStream.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/ObjectInputStream.java,v
retrieving revision 1.83
diff -u -r1.83 ObjectInputStream.java
--- classpath/java/io/ObjectInputStream.java    9 Jan 2008 20:42:40 -0000       
1.83
+++ classpath/java/io/ObjectInputStream.java    24 Jan 2008 15:03:48 -0000
@@ -356,7 +356,6 @@
        }
        
        case TC_STRING:
-       case TC_LONGSTRING:
        {
          if(dump) dumpElement("STRING=");
          String s = this.realInputStream.readUTF();
@@ -366,6 +365,16 @@
          break;
        }
  
+       case TC_LONGSTRING:
+       {
+         if(dump) dumpElement("STRING=");
+         String s = this.realInputStream.readUTFLong();
+         if(dump) dumpElementln(s);
+         ret_val = processResolution(null, s, assignNewHandle(s,shared),
+                                     shared);
+         break;
+       }
+
        case TC_ARRAY:
        {
          if(dump) dumpElementln("ARRAY");
Index: classpath/java/io/ObjectOutputStream.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/io/ObjectOutputStream.java,v
retrieving revision 1.72
diff -u -r1.72 ObjectOutputStream.java
--- classpath/java/io/ObjectOutputStream.java   16 Apr 2007 15:39:10 -0000      
1.72
+++ classpath/java/io/ObjectOutputStream.java   24 Jan 2008 15:03:48 -0000
@@ -363,10 +363,22 @@
 
            if (obj instanceof String)
              {
-               realOutput.writeByte(TC_STRING);
-               if (shared)
-                 assignNewHandle(obj);
-               realOutput.writeUTF((String)obj);
+                String s = (String)obj;
+                long l = realOutput.getUTFlength(s, 0, 0);
+                if (l <= 65535)
+                  {
+                   realOutput.writeByte(TC_STRING);
+                   if (shared)
+                     assignNewHandle(obj);
+                   realOutput.writeUTFShort(s, (int)l);
+                  }
+                else
+                  {
+                   realOutput.writeByte(TC_LONGSTRING);
+                   if (shared)
+                     assignNewHandle(obj);
+                   realOutput.writeUTFLong(s, l);
+                  }
                break;
              }
 

Reply via email to