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; }