From 1745554bbb5117a3bb9fbe3d90db73b112aa5ca4 Mon Sep 17 00:00:00 2001 From: Ito Kazumitsu Date: Tue, 29 Jan 2008 22:30:42 +0000 Subject: 2008-01-29 Ito Kazumitsu 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. --- ChangeLog | 16 ++++++++ java/io/DataInputStream.java | 50 ++++++++++++++++++++++-- java/io/DataOutputStream.java | 84 ++++++++++++++++++++++++++++++++--------- java/io/ObjectInputStream.java | 13 ++++++- java/io/ObjectOutputStream.java | 22 ++++++++--- 5 files changed, 158 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index da1c640ab..f625f84b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2008-01-29 Ito Kazumitsu + + 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. + 2008-01-27 Bernhard Fischer * java/util/SimpleTimeZone.java (SimpleTimeZone): Fix typo in comment. diff --git a/java/io/DataInputStream.java b/java/io/DataInputStream.java index d2604b51f..8b223ea84 100644 --- a/java/io/DataInputStream.java +++ b/java/io/DataInputStream.java @@ -1,5 +1,6 @@ /* DataInputStream.java -- FilteredInputStream that implements DataInput - Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation + Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2008 + Free Software Foundation This file is part of GNU Classpath. @@ -590,13 +591,56 @@ public class DataInputStream extends FilterInputStream implements DataInput 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 readUTF, but the + * UTF-8 byte length is in 64 bits. + * This method is not public. It is used by ObjectInputStream. + * + * @return The String 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 readUTF and + * readUTFLong. + * + * @param in The DataInput 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); } diff --git a/java/io/DataOutputStream.java b/java/io/DataOutputStream.java index 6670c2dba..435ff76d1 100644 --- a/java/io/DataOutputStream.java +++ b/java/io/DataOutputStream.java @@ -1,5 +1,5 @@ /* DataOutputStream.java -- Writes primitive Java datatypes to streams - Copyright (C) 1998, 2001, 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 1998, 2001, 2003, 2005, 2008 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -379,19 +379,20 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput /** * Calculate the length, in bytes, of a String in Utf8 format. + * This method is package-private so that ObjectOutputStream + * 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 String 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 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput sum += 3; } - if (sum > 65535) - throw new UTFDataFormatException (); - return sum; } @@ -441,11 +439,71 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput * @see DataInput#readUTF */ 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 writeUTF. + * This method is package-private because ObjectOutputStream uses it. + * + * @param value The String to write to the output in UTF format + * + * @param bytelen The UTF-8 byte length of the String. When + * this method is called, the expected byte length must have been calculated + * by getUTFlength. + * + * @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 writeUTF, but it writes the + * UTF-8 byte length in 64 bits. + * This method is not public but ObjectOutputStream uses it. + * + * @param value The String to write to the output in UTF format + * + * @param bytelen The UTF-8 byte length of the String. When + * this method is called, the expected byte length must have been calculated + * by getUTFlength. + * + * @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 writeUTF and + * WriteUTFLong, which is to write the UTF-8 byte + * sequence to the output. + * + * @param value The String 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 @@ public class DataOutputStream extends FilterOutputStream implements DataOutput 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; } diff --git a/java/io/ObjectInputStream.java b/java/io/ObjectInputStream.java index ea3ffde61..36e70d6a4 100644 --- a/java/io/ObjectInputStream.java +++ b/java/io/ObjectInputStream.java @@ -1,5 +1,5 @@ /* ObjectInputStream.java -- Class used to read serialized objects - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -356,7 +356,6 @@ public class ObjectInputStream extends InputStream } case TC_STRING: - case TC_LONGSTRING: { if(dump) dumpElement("STRING="); String s = this.realInputStream.readUTF(); @@ -366,6 +365,16 @@ public class ObjectInputStream extends InputStream 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"); diff --git a/java/io/ObjectOutputStream.java b/java/io/ObjectOutputStream.java index 5cb2a73f9..c09487536 100644 --- a/java/io/ObjectOutputStream.java +++ b/java/io/ObjectOutputStream.java @@ -1,5 +1,5 @@ /* ObjectOutputStream.java -- Class used to write serialized objects - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -363,10 +363,22 @@ public class ObjectOutputStream extends OutputStream 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; } -- cgit v1.2.1