1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.    Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.    See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "jni.h"
  27 #include "imageDecompressor.hpp"
  28 #include "endian.hpp"
  29 #ifdef WIN32
  30 #include <windows.h>
  31 #else
  32 #include <dlfcn.h>
  33 #endif
  34 
  35 typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen,
  36                                               void *outBuf, jlong outLen, char **pmsg);
  37 static ZipInflateFully_t ZipInflateFully        = NULL;
  38 
  39 #ifndef WIN32
  40     #define JNI_LIB_PREFIX "lib"
  41     #ifdef __APPLE__
  42         #define JNI_LIB_SUFFIX ".dylib"
  43     #else
  44         #define JNI_LIB_SUFFIX ".so"
  45     #endif
  46 #endif
  47 
  48 /**
  49  * Return the address of the entry point named in the zip shared library.
  50  * @param name - the name of the entry point
  51  * @return the address of the entry point or NULL
  52  */
  53 static void* findEntry(const char* name) {
  54     void *addr = NULL;
  55 #ifdef WIN32
  56     HMODULE handle = GetModuleHandle("zip.dll");
  57     if (handle == NULL) {
  58         return NULL;
  59     }
  60     addr = (void*) GetProcAddress(handle, name);
  61     return addr;
  62 #else
  63     addr = dlopen(JNI_LIB_PREFIX "zip" JNI_LIB_SUFFIX, RTLD_GLOBAL|RTLD_LAZY);
  64     if (addr == NULL) {
  65         return NULL;
  66     }
  67     addr = dlsym(addr, name);
  68     return addr;
  69 #endif
  70 }
  71 
  72 /*
  73  * Initialize the array of decompressors.
  74  */
  75 int ImageDecompressor::_decompressors_num = 0;
  76 ImageDecompressor** ImageDecompressor::_decompressors = NULL;
  77 void ImageDecompressor::image_decompressor_init() {
  78     if (_decompressors == NULL) {
  79         ZipInflateFully = (ZipInflateFully_t) findEntry("ZIP_InflateFully");
  80      assert(ZipInflateFully != NULL && "ZIP decompressor not found.");
  81         _decompressors_num = 2;
  82         _decompressors = new ImageDecompressor*[_decompressors_num];
  83         _decompressors[0] = new ZipDecompressor("zip");
  84         _decompressors[1] = new SharedStringDecompressor("compact-cp");
  85     }
  86 }
  87 
  88 void ImageDecompressor::image_decompressor_close() {
  89     delete[] _decompressors;
  90 }
  91 
  92 /*
  93  * Locate decompressor.
  94  */
  95 ImageDecompressor* ImageDecompressor::get_decompressor(const char * decompressor_name) {
  96     image_decompressor_init();
  97     for (int i = 0; i < _decompressors_num; i++) {
  98         ImageDecompressor* decompressor = _decompressors[i];
  99         assert(decompressor != NULL && "Decompressors not initialized.");
 100         if (strcmp(decompressor->get_name(), decompressor_name) == 0) {
 101             return decompressor;
 102         }
 103     }
 104     assert(false && "No decompressor found.");
 105     return NULL;
 106 }
 107 
 108 /*
 109  * Decompression entry point. Called from ImageFileReader::get_resource.
 110  */
 111 void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
 112                 u4 uncompressed_size, const ImageStrings* strings) {
 113     bool has_header = false;
 114     u1* decompressed_resource = compressed;
 115     u1* compressed_resource = compressed;
 116 
 117     // Resource could have been transformed by a stack of decompressors.
 118     // Iterate and decompress resources until there is no more header.
 119     do {
 120         ResourceHeader _header;
 121         memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
 122         has_header = _header._magic == ResourceHeader::resource_header_magic;
 123         if (has_header) {
 124             // decompressed_resource array contains the result of decompression
 125             decompressed_resource = new u1[_header._uncompressed_size];
 126             // Retrieve the decompressor name
 127             const char* decompressor_name = strings->get(_header._decompressor_name_offset);
 128             assert(decompressor_name && "image decompressor not found");
 129             // Retrieve the decompressor instance
 130             ImageDecompressor* decompressor = get_decompressor(decompressor_name);
 131             assert(decompressor && "image decompressor not found");
 132             u1* compressed_resource_base = compressed_resource;
 133             compressed_resource += ResourceHeader::resource_header_length;
 134             // Ask the decompressor to decompress the compressed content
 135             decompressor->decompress_resource(compressed_resource, decompressed_resource,
 136                 &_header, strings);
 137             if (compressed_resource_base != compressed) {
 138                 delete[] compressed_resource_base;
 139             }
 140             compressed_resource = decompressed_resource;
 141         }
 142     } while (has_header);
 143     memcpy(uncompressed, decompressed_resource, uncompressed_size);
 144     delete[] decompressed_resource;
 145 }
 146 
 147 // Zip decompressor
 148 
 149 void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed,
 150                 ResourceHeader* header, const ImageStrings* strings) {
 151     char* msg = NULL;
 152     jboolean res = ZipDecompressor::decompress(data, header->_size, uncompressed,
 153                     header->_uncompressed_size, &msg);
 154     assert(res && "decompression failed");
 155 }
 156 
 157 jboolean ZipDecompressor::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) {
 158     return (*ZipInflateFully)(in, inSize, out, outSize, pmsg);
 159 }
 160 
 161 // END Zip Decompressor
 162 
 163 // Shared String decompressor
 164 
 165 // array index is the constant pool tag. value is size.
 166 // eg: array[5]  = 8; means size of long is 8 bytes.
 167 const u1 SharedStringDecompressor::sizes[] = {
 168     0, 0, 0, 4, 4, 8, 8, 2, 2, 4, 4, 4, 4, 0, 0, 3, 2, 0, 4
 169 };
 170 /**
 171  * Recreate the class by reconstructing the constant pool.
 172  */
 173 void SharedStringDecompressor::decompress_resource(u1* data,
 174                 u1* uncompressed_resource,
 175                 ResourceHeader* header, const ImageStrings* strings) {
 176     u1* uncompressed_base = uncompressed_resource;
 177     u1* data_base = data;
 178     int header_size = 8; // magic + major + minor
 179     memcpy(uncompressed_resource, data, header_size + 2); //+ cp count
 180     uncompressed_resource += header_size + 2;
 181     data += header_size;
 182     u2 cp_count = Endian::get_java(data);
 183     data += 2;
 184     for (int i = 1; i < cp_count; i++) {
 185         u1 tag = *data;
 186         data += 1;
 187         switch (tag) {
 188 
 189             case externalized_string:
 190             { // String in Strings table
 191                 *uncompressed_resource = 1;
 192                 uncompressed_resource += 1;
 193                 int k = decompress_int(data);
 194                 const char * string = strings->get(k);
 195                 int str_length = (int) strlen(string);
 196                 Endian::set_java(uncompressed_resource, str_length);
 197                 uncompressed_resource += 2;
 198                 memcpy(uncompressed_resource, string, str_length);
 199                 uncompressed_resource += str_length;
 200                 break;
 201             }
 202             // Descriptor String has been split and types added to Strings table
 203             case externalized_string_descriptor:
 204             {
 205                 *uncompressed_resource = 1;
 206                 uncompressed_resource += 1;
 207                 int descriptor_index = decompress_int(data);
 208                 int indexes_length = decompress_int(data);
 209                 u1* length_address = uncompressed_resource;
 210                 uncompressed_resource += 2;
 211                 int desc_length = 0;
 212                 const char * desc_string = strings->get(descriptor_index);
 213                 if (indexes_length > 0) {
 214                     u1* indexes_base = data;
 215                     data += indexes_length;
 216                     char c = *desc_string;
 217                     do {
 218                         *uncompressed_resource = c;
 219                         uncompressed_resource++;
 220                         desc_length += 1;
 221                         /*
 222                          * Every L character is the marker we are looking at in order
 223                          * to reconstruct the descriptor. Each time an L is found, then
 224                          * we retrieve the couple token/token at the current index and
 225                          * add it to the descriptor.
 226                          * "(L;I)V" and "java/lang","String" couple of tokens,
 227                          * this becomes "(Ljava/lang/String;I)V"
 228                          */
 229                         if (c == 'L') {
 230                             int index = decompress_int(indexes_base);
 231                             const char * pkg = strings->get(index);
 232                             int str_length = (int) strlen(pkg);
 233                             // the case where we have a package.
 234                             // reconstruct the type full name
 235                             if (str_length > 0) {
 236                                 int len = str_length + 1;
 237                                 char* fullpkg = new char[len];
 238                                 char* pkg_base = fullpkg;
 239                                 memcpy(fullpkg, pkg, str_length);
 240                                 fullpkg += str_length;
 241                                 *fullpkg = '/';
 242                                 memcpy(uncompressed_resource, pkg_base, len);
 243                                 uncompressed_resource += len;
 244                                 delete[] pkg_base;
 245                                 desc_length += len;
 246                             } else { // Empty package
 247                                 // Nothing to do.
 248                             }
 249                             int classIndex = decompress_int(indexes_base);
 250                             const char * clazz = strings->get(classIndex);
 251                             int clazz_length = (int) strlen(clazz);
 252                             memcpy(uncompressed_resource, clazz, clazz_length);
 253                             uncompressed_resource += clazz_length;
 254                             desc_length += clazz_length;
 255                         }
 256                         desc_string += 1;
 257                         c = *desc_string;
 258                     } while (c != '\0');
 259                 } else {
 260                         desc_length = (int) strlen(desc_string);
 261                         memcpy(uncompressed_resource, desc_string, desc_length);
 262                         uncompressed_resource += desc_length;
 263                 }
 264                 Endian::set_java(length_address, desc_length);
 265                 break;
 266             }
 267 
 268             case constant_utf8:
 269             { // UTF-8
 270                 *uncompressed_resource = tag;
 271                 uncompressed_resource += 1;
 272                 u2 str_length = Endian::get_java(data);
 273                 int len = str_length + 2;
 274                 memcpy(uncompressed_resource, data, len);
 275                 uncompressed_resource += len;
 276                 data += len;
 277                 break;
 278             }
 279 
 280             case constant_long:
 281             case constant_double:
 282             {
 283                 i++;
 284             }
 285             default:
 286             {
 287                 *uncompressed_resource = tag;
 288                 uncompressed_resource += 1;
 289                 int size = sizes[tag];
 290                 memcpy(uncompressed_resource, data, size);
 291                 uncompressed_resource += size;
 292                 data += size;
 293             }
 294         }
 295     }
 296     u4 remain = header->_size - (int)(data - data_base);
 297     u4 computed = (u4)(uncompressed_resource - uncompressed_base) + remain;
 298     if (header->_uncompressed_size != computed)
 299         printf("Failure, expecting %d but getting %d\n", header->_uncompressed_size,
 300                 computed);
 301     assert(header->_uncompressed_size == computed &&
 302                 "Constant Pool reconstruction failed");
 303     memcpy(uncompressed_resource, data, remain);
 304 }
 305 
 306 /*
 307  * Decompress integers. Compressed integers are negative.
 308  * If positive, the integer is not decompressed.
 309  * If negative, length extracted from the first byte, then reconstruct the integer
 310  * from the following bytes.
 311  * Example of compression: 1 is compressed on 1 byte: 10100001
 312  */
 313 int SharedStringDecompressor::decompress_int(unsigned char*& value) {
 314     int len = 4;
 315     int res = 0;
 316     char b1 = *value;
 317     if (is_compressed((signed char)b1)) { // compressed
 318         len = get_compressed_length(b1);
 319         char clearedValue = b1 &= 0x1F;
 320         if (len == 1) {
 321             res = clearedValue;
 322         } else {
 323             res = (clearedValue & 0xFF) << 8 * (len - 1);
 324             for (int i = 1; i < len; i++) {
 325                 res |= (value[i]&0xFF) << 8 * (len - i - 1);
 326             }
 327         }
 328     } else {
 329         res = (value[0] & 0xFF) << 24 | (value[1]&0xFF) << 16 |
 330                     (value[2]&0xFF) << 8 | (value[3]&0xFF);
 331     }
 332     value += len;
 333     return res;
 334 }
 335 // END Shared String decompressor