Targeted backport of a java.util.Inflater fix.
This has been causing trouble for Gmail. The original fix cleaned up large
parts of the java.util.zip code; this just contains the active ingredient.
(I've excluded the error-handling change to this same function because
that hasn't been tested in the real world yet.)
Bug: 3220923
Change-Id: Ib4bc585a45061ef55c29f09f2bd650c772aab64d
diff --git a/luni/src/main/native/java_util_zip_Inflater.cpp b/luni/src/main/native/java_util_zip_Inflater.cpp
index 8dd9e87..aa53240 100644
--- a/luni/src/main/native/java_util_zip_Inflater.cpp
+++ b/luni/src/main/native/java_util_zip_Inflater.cpp
@@ -95,46 +95,39 @@
}
static jint Inflater_inflateImpl(JNIEnv* env, jobject recv, jbyteArray buf, int off, int len, jlong handle) {
- jfieldID fid2 = 0;
-
- /* We need to get the number of bytes already read */
- jfieldID fid = gCachedFields.inRead;
- jint inBytes = env->GetIntField(recv, fid);
-
NativeZipStream* stream = toNativeZipStream(handle);
- stream->stream.avail_out = len;
- jint sin = stream->stream.total_in;
- jint sout = stream->stream.total_out;
ScopedByteArrayRW out(env, buf);
if (out.get() == NULL) {
return -1;
}
stream->stream.next_out = reinterpret_cast<Bytef*>(out.get() + off);
+ stream->stream.avail_out = len;
+
+ Bytef* initialNextIn = stream->stream.next_in;
+ Bytef* initialNextOut = stream->stream.next_out;
+
int err = inflate(&stream->stream, Z_SYNC_FLUSH);
if (err != Z_OK) {
if (err == Z_STREAM_ERROR) {
return 0;
}
- if (err == Z_STREAM_END || err == Z_NEED_DICT) {
- env->SetIntField(recv, fid, (jint) stream->stream.total_in - sin + inBytes);
- if (err == Z_STREAM_END) {
- fid2 = gCachedFields.finished;
- } else {
- fid2 = gCachedFields.needsDictionary;
- }
- env->SetBooleanField(recv, fid2, JNI_TRUE);
- return stream->stream.total_out - sout;
+ if (err == Z_STREAM_END) {
+ env->SetBooleanField(recv, gCachedFields.finished, JNI_TRUE);
+ } else if (err == Z_NEED_DICT) {
+ env->SetBooleanField(recv, gCachedFields.needsDictionary, JNI_TRUE);
} else {
throwExceptionForZlibError(env, "java/util/zip/DataFormatException", err);
return -1;
}
}
- /* Need to update the number of input bytes read. Is there a better way
- * (Maybe global the fid then delete when end is called)?
- */
- env->SetIntField(recv, fid, (jint) stream->stream.total_in - sin + inBytes);
- return stream->stream.total_out - sout;
+ jint bytesRead = stream->stream.next_in - initialNextIn;
+ jint bytesWritten = stream->stream.next_out - initialNextOut;
+
+ jint inReadValue = env->GetIntField(recv, gCachedFields.inRead);
+ inReadValue += bytesRead;
+ env->SetIntField(recv, gCachedFields.inRead, inReadValue);
+ return bytesWritten;
}
static jint Inflater_getAdlerImpl(JNIEnv*, jobject, jlong handle) {