This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: FYI: fix PR libgcj/27271


I'm checking this in to Classpath and GCC svn trunk.  This is the PR
27271 fix, changed to work with the newer-than-4.1 PartialInputStream.

I'm copying in the text from my previous email for the benefit of
Classpath hackers.

This fixes PR 27271.  My patch for PR 24461 revealed a latent bug
which affects some programs, notably RSSOwl.  The problem is that
Inflater requires an extra dummy byte when created with the "no
header" flag.  This patch arranges to pass in this byte when reading
from a zip file.

I looked at other creations of Inflater and, apparently, this
treatment is not required there.  (Meaning, I could not write a
failing test case for those cases.)

I think this is an interesting example of how an API mistake (the
extra byte oddity originates in zlib) can propagate outward, making
more and more things uglier and harder to maintain.


Additional note for Classpath: the Classpath Inflater does not
actually require the extra input byte.  libgcj does because it uses
the native zlib instead of Classpath's pure java implementation.  This
patch doesn't hurt Classpath according to my tests -- the Classpath
Inflater still has to support getting the extra byte due to
compatibility.

Tom

Index: ChangeLog.gcj
from  Tom Tromey  <tromey@redhat.com>

	PR libgcj/27271:
	* java/util/zip/ZipFile.java (getInputStream): Call addDummyByte
	on PartialInputStream.
	(PartialInputStream.dummyByteCount): New field.
	(PartialInputStream.fillBuffer): Handle dummy byte.
	(PartialInputStream.read): Likewise.
	(PartialInputStream.addDummyByte): New method.

Index: java/util/zip/ZipFile.java
===================================================================
--- java/util/zip/ZipFile.java	(revision 115038)
+++ java/util/zip/ZipFile.java	(working copy)
@@ -445,6 +445,7 @@
       case ZipOutputStream.STORED:
 	return inp;
       case ZipOutputStream.DEFLATED:
+        inp.addDummyByte();
         final Inflater inf = new Inflater(true);
         final int sz = (int) entry.getSize();
         return new InflaterInputStream(inp, inf)
@@ -520,6 +521,11 @@
     private long bufferOffset;
     private int pos;
     private long end;
+    // We may need to supply an extra dummy byte to our reader.
+    // See Inflater.  We use a count here to simplify the logic
+    // elsewhere in this class.  Note that we ignore the dummy
+    // byte in methods where we know it is not needed.
+    private int dummyByteCount;
 
     public PartialInputStream(RandomAccessFile raf, int bufferSize)
       throws IOException
@@ -540,8 +546,17 @@
     {
       synchronized (raf)
         {
-          raf.seek(bufferOffset);
-          raf.readFully(buffer, 0, (int) Math.min(buffer.length, end - bufferOffset));
+          long len = end - bufferOffset;
+          if (len == 0 && dummyByteCount > 0)
+            {
+              buffer[0] = 0;
+              dummyByteCount = 0;
+            }
+          else
+            {
+              raf.seek(bufferOffset);
+              raf.readFully(buffer, 0, (int) Math.min(buffer.length, len));
+            }
         }
     }
     
@@ -555,7 +570,7 @@
     
     public int read() throws IOException
     {
-      if (bufferOffset + pos >= end)
+      if (bufferOffset + pos >= end + dummyByteCount)
 	return -1;
       if (pos == buffer.length)
         {
@@ -569,9 +584,9 @@
 
     public int read(byte[] b, int off, int len) throws IOException
     {
-      if (len > end - (bufferOffset + pos))
+      if (len > end + dummyByteCount - (bufferOffset + pos))
 	{
-	  len = (int) (end - (bufferOffset + pos));
+	  len = (int) (end + dummyByteCount - (bufferOffset + pos));
 	  if (len == 0)
 	    return -1;
 	}
@@ -681,5 +696,10 @@
           throw new AssertionError(uee);
         }
     }
+
+    public void addDummyByte()
+    {
+      dummyByteCount = 1;
+    }
   }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]