Path: blob/master/src/java.base/share/native/libzip/Inflater.c
41149 views
/*1* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* Native method support for java.util.zip.Inflater27*/2829#include <stddef.h>30#include <stdio.h>31#include <stdlib.h>32#include <errno.h>33#include <string.h>34#include "jlong.h"35#include "jni.h"36#include "jvm.h"37#include "jni_util.h"38#include <zlib.h>39#include "java_util_zip_Inflater.h"4041#define ThrowDataFormatException(env, msg) \42JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg)4344static jfieldID inputConsumedID;45static jfieldID outputConsumedID;4647JNIEXPORT void JNICALL48Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls)49{50inputConsumedID = (*env)->GetFieldID(env, cls, "inputConsumed", "I");51outputConsumedID = (*env)->GetFieldID(env, cls, "outputConsumed", "I");52CHECK_NULL(inputConsumedID);53CHECK_NULL(outputConsumedID);54}5556JNIEXPORT jlong JNICALL57Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap)58{59z_stream *strm = calloc(1, sizeof(z_stream));6061if (strm == NULL) {62JNU_ThrowOutOfMemoryError(env, 0);63return jlong_zero;64} else {65const char *msg;66int ret = inflateInit2(strm, nowrap ? -MAX_WBITS : MAX_WBITS);67switch (ret) {68case Z_OK:69return ptr_to_jlong(strm);70case Z_MEM_ERROR:71free(strm);72JNU_ThrowOutOfMemoryError(env, 0);73return jlong_zero;74default:75msg = ((strm->msg != NULL) ? strm->msg :76(ret == Z_VERSION_ERROR) ?77"zlib returned Z_VERSION_ERROR: "78"compile time and runtime zlib implementations differ" :79(ret == Z_STREAM_ERROR) ?80"inflateInit2 returned Z_STREAM_ERROR" :81"unknown error initializing zlib library");82free(strm);83JNU_ThrowInternalError(env, msg);84return jlong_zero;85}86}87}8889static void checkSetDictionaryResult(JNIEnv *env, jlong addr, int res)90{91switch (res) {92case Z_OK:93break;94case Z_STREAM_ERROR:95case Z_DATA_ERROR:96JNU_ThrowIllegalArgumentException(env, ((z_stream *)jlong_to_ptr(addr))->msg);97break;98default:99JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg);100break;101}102}103104JNIEXPORT void JNICALL105Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,106jbyteArray b, jint off, jint len)107{108jint res;109Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);110if (buf == NULL) /* out of memory */111return;112res = inflateSetDictionary(jlong_to_ptr(addr), buf + off, len);113(*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);114checkSetDictionaryResult(env, addr, res);115}116117JNIEXPORT void JNICALL118Java_java_util_zip_Inflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr,119jlong bufferAddr, jint len)120{121jint res;122Bytef *buf = jlong_to_ptr(bufferAddr);123res = inflateSetDictionary(jlong_to_ptr(addr), buf, len);124checkSetDictionaryResult(env, addr, res);125}126127static jint doInflate(jlong addr,128jbyte *input, jint inputLen,129jbyte *output, jint outputLen)130{131jint ret;132z_stream *strm = jlong_to_ptr(addr);133134strm->next_in = (Bytef *) input;135strm->next_out = (Bytef *) output;136strm->avail_in = inputLen;137strm->avail_out = outputLen;138139ret = inflate(strm, Z_PARTIAL_FLUSH);140return ret;141}142143static jlong checkInflateStatus(JNIEnv *env, jobject this, jlong addr,144jint inputLen, jint outputLen, jint ret )145{146z_stream *strm = jlong_to_ptr(addr);147jint inputUsed = 0, outputUsed = 0;148int finished = 0;149int needDict = 0;150151switch (ret) {152case Z_STREAM_END:153finished = 1;154/* fall through */155case Z_OK:156inputUsed = inputLen - strm->avail_in;157outputUsed = outputLen - strm->avail_out;158break;159case Z_NEED_DICT:160needDict = 1;161/* Might have consumed some input here! */162inputUsed = inputLen - strm->avail_in;163/* zlib is unclear about whether output may be produced */164outputUsed = outputLen - strm->avail_out;165break;166case Z_BUF_ERROR:167break;168case Z_DATA_ERROR:169inputUsed = inputLen - strm->avail_in;170(*env)->SetIntField(env, this, inputConsumedID, inputUsed);171outputUsed = outputLen - strm->avail_out;172(*env)->SetIntField(env, this, outputConsumedID, outputUsed);173ThrowDataFormatException(env, strm->msg);174break;175case Z_MEM_ERROR:176JNU_ThrowOutOfMemoryError(env, 0);177break;178default:179JNU_ThrowInternalError(env, strm->msg);180break;181}182return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)needDict) << 63);183}184185JNIEXPORT jlong JNICALL186Java_java_util_zip_Inflater_inflateBytesBytes(JNIEnv *env, jobject this, jlong addr,187jbyteArray inputArray, jint inputOff, jint inputLen,188jbyteArray outputArray, jint outputOff, jint outputLen)189{190jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);191jbyte *output;192jint ret;193jlong retVal;194195if (input == NULL) {196if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)197JNU_ThrowOutOfMemoryError(env, 0);198return 0L;199}200output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);201if (output == NULL) {202(*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);203if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)204JNU_ThrowOutOfMemoryError(env, 0);205return 0L;206}207208ret = doInflate(addr, input + inputOff, inputLen, output + outputOff,209outputLen);210211(*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);212(*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);213214retVal = checkInflateStatus(env, this, addr, inputLen, outputLen, ret );215return retVal;216}217218JNIEXPORT jlong JNICALL219Java_java_util_zip_Inflater_inflateBytesBuffer(JNIEnv *env, jobject this, jlong addr,220jbyteArray inputArray, jint inputOff, jint inputLen,221jlong outputBuffer, jint outputLen)222{223jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);224jbyte *output;225jint ret;226jlong retVal;227228if (input == NULL) {229if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)230JNU_ThrowOutOfMemoryError(env, 0);231return 0L;232}233output = jlong_to_ptr(outputBuffer);234235ret = doInflate(addr, input + inputOff, inputLen, output, outputLen);236237(*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);238retVal = checkInflateStatus(env, this, addr, inputLen, outputLen, ret );239240return retVal;241}242243JNIEXPORT jlong JNICALL244Java_java_util_zip_Inflater_inflateBufferBytes(JNIEnv *env, jobject this, jlong addr,245jlong inputBuffer, jint inputLen,246jbyteArray outputArray, jint outputOff, jint outputLen)247{248jbyte *input = jlong_to_ptr(inputBuffer);249jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);250jint ret;251jlong retVal;252253if (output == NULL) {254if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)255JNU_ThrowOutOfMemoryError(env, 0);256return 0L;257}258259ret = doInflate(addr, input, inputLen, output + outputOff, outputLen);260261(*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);262retVal = checkInflateStatus(env, this, addr, inputLen, outputLen, ret );263264return retVal;265}266267JNIEXPORT jlong JNICALL268Java_java_util_zip_Inflater_inflateBufferBuffer(JNIEnv *env, jobject this, jlong addr,269jlong inputBuffer, jint inputLen,270jlong outputBuffer, jint outputLen)271{272jbyte *input = jlong_to_ptr(inputBuffer);273jbyte *output = jlong_to_ptr(outputBuffer);274jint ret;275jlong retVal;276277ret = doInflate(addr, input, inputLen, output, outputLen);278retVal = checkInflateStatus(env, this, addr, inputLen, outputLen, ret);279return retVal;280}281282JNIEXPORT jint JNICALL283Java_java_util_zip_Inflater_getAdler(JNIEnv *env, jclass cls, jlong addr)284{285return ((z_stream *)jlong_to_ptr(addr))->adler;286}287288JNIEXPORT void JNICALL289Java_java_util_zip_Inflater_reset(JNIEnv *env, jclass cls, jlong addr)290{291if (inflateReset(jlong_to_ptr(addr)) != Z_OK) {292JNU_ThrowInternalError(env, 0);293}294}295296JNIEXPORT void JNICALL297Java_java_util_zip_Inflater_end(JNIEnv *env, jclass cls, jlong addr)298{299if (inflateEnd(jlong_to_ptr(addr)) == Z_STREAM_ERROR) {300JNU_ThrowInternalError(env, 0);301} else {302free(jlong_to_ptr(addr));303}304}305306307