diff --git a/src/libopensc/compression.c b/src/libopensc/compression.c index 3c8352d2..3dfd0ead 100644 --- a/src/libopensc/compression.c +++ b/src/libopensc/compression.c @@ -52,18 +52,28 @@ static int zerr_to_opensc(int err) { } static int detect_method(const u8* in, size_t inLen) { if (in != NULL && inLen > 1) { - if (inLen > 2 && in[0] == 0x1f && in[1] == 0x8b) + if (in[0] == 0x1f && in[1] == 0x8b) return COMPRESSION_GZIP; -#if 0 - if ((in[0] & 0x10) == Z_DEFLATED) - /* REALLY SIMPLE ZLIB TEST -- - * Check for the compression method to be set to 8... - * many things can spoof this, but this is ok for now - * */ + /* + * A zlib stream has the following structure: + * 0 1 + * +---+---+ + * |CMF|FLG| (more-->) + * +---+---+ + * + * FLG (FLaGs) + * This flag byte is divided as follows: + * + * bits 0 to 4 FCHECK (check bits for CMF and FLG) + * bit 5 FDICT (preset dictionary) + * bits 6 to 7 FLEVEL (compression level) + * + * The FCHECK value must be such that CMF and FLG, when viewed as + * a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), + * is a multiple of 31. + */ + if ((((uint16_t) in[0])*256 + in[1]) % 31 == 0) return COMPRESSION_ZLIB; -#else - return COMPRESSION_ZLIB; -#endif } return COMPRESSION_UNKNOWN; } @@ -105,8 +115,10 @@ static int sc_decompress_gzip(u8* out, size_t* outLen, const u8* in, size_t inLe gz.next_out = out; gz.avail_out = *outLen; + *outLen = 0; + err = inflateInit2(&gz, window_size); - if(err != Z_OK) return zerr_to_opensc(err); + if (err != Z_OK) return zerr_to_opensc(err); err = inflate(&gz, Z_FINISH); if(err != Z_STREAM_END) { inflateEnd(&gz); @@ -144,7 +156,8 @@ int sc_decompress(u8* out, size_t* outLen, const u8* in, size_t inLen, int metho if(method == COMPRESSION_AUTO) { method = detect_method(in, inLen); - if(method == COMPRESSION_UNKNOWN) { + if (method == COMPRESSION_UNKNOWN) { + *outLen = 0; return SC_ERROR_UNKNOWN_DATA_RECEIVED; } }