void deflate_parse_htrees(bitstream_t *bitstream, htree_t **htree_lit, htree_t **htree_dist) { int hlit = read_bits(bitstream, 5) + 257; int hdist = read_bits(bitstream, 5) + 1; int hclen = read_bits(bitstream, 4) + 4; int cl_order[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; int cl_lengths[19] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; for (int i = 0; i < hclen; i++) { cl_lengths[cl_order[i]] = read_bits(bitstream, 3); } htree_t *ht_cl = huffman_create_tree(19, cl_lengths); int tot = hlit + hdist; int *lengths = calloc(tot, sizeof(int)); int cur_len = 0; while (cur_len < tot) { htree_t *cur_cl = huffman_get_symbol(ht_cl, bitstream); int symbol = 0, repeats = 1; if (cur_cl->symbol == 16) { /* Symbol 16: Copy previous length 3-6 times. */ symbol = lengths[cur_len - 1]; repeats = read_bits(bitstream, 2) + 3; } else if (cur_cl->symbol == 17) { /* Symbol 17: Repeat 0 for 3-10 times. */ repeats = read_bits(bitstream, 3) + 3; } else if (cur_cl->symbol == 18) { /* Symbol 18: Repeat 0 for 11-138 times. */ repeats = read_bits(bitstream, 7) + 11; } else { /* Otherwise: Emit length. */ symbol = cur_cl->symbol; } for (int i = 0; i < repeats; i++) { lengths[cur_len++] = symbol; } } if (cur_len > tot) { printf("Error: Code tree lengths defined too far\n"); } /* We don't need the code length Huffman tree anymore. */ huffman_free_tree(ht_cl); int *lit_lengths = &lengths[0]; int *dist_lengths = &lengths[hlit]; *htree_lit = huffman_create_tree(hlit, lit_lengths); *htree_dist = huffman_create_tree(hdist, dist_lengths); /* Free the data arrays used to create the Huffman trees. */ free(lengths); }
void deflate_get_fixed_htrees(htree_t **htree_lit, htree_t **htree_dist) { int lengths[288]; for (int i = 0; i < 288; i++) { if (i < 144) { lengths[i] = 8; } else if (i < 256) { lengths[i] = 9; } else if (i < 280) { lengths[i] = 7; } else { lengths[i] = 8; } } *htree_lit = huffman_create_tree(288, lengths); for (int i = 0; i < 32; i++) { lengths[i] = 5; } *htree_dist = huffman_create_tree(32, lengths); }
unsigned int alpng_inflate(struct input_data* data, unsigned char* unpacked_data, unsigned int unpacked_length, char** error_msg) { int bfinal, btype; /* as defined by the deflate spec */ int code, length, distance, i; unsigned int unpacked_index = 0; struct huffman_tree* main_tree = huffman_create_tree(); struct huffman_tree* distances_tree = huffman_create_tree(); struct huffman_tree* helper_tree = huffman_create_tree(); /* for codelengths */ *error_msg = "OK"; data->i = 2; /* ignore zlib header */ do { bfinal = input_read_bit(data); if (data->error) { *error_msg = "Data shorter than one bit!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } btype = input_read_bits(data, 2); if (data->error) { *error_msg = "Data shorter than one byte!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } switch (btype) { case 0: length = input_read_bytes(data, 2); if (data->error) { *error_msg = "Cannot read length of uncompressed block!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } i = input_read_bytes(data, 2); if (data->error) { *error_msg = "Cannot read length of uncompressed block!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } if (length != (i ^ 0xFFFF)) { *error_msg = "Uncompressed block corruption detected!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } for (i = 0; i < length; i++) { code = input_read_byte(data); if (data->error) { *error_msg = "Uncompressed block incomplete!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } if (unpacked_index >= unpacked_length) { *error_msg = "Too much data!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } else { unpacked_data[unpacked_index++] = code; } } break; case 1: if (!load_fixed_tree(main_tree, distances_tree)) { *error_msg = "Cannot load fixed Huffman tree!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } break; case 2: if (!load_dynamic_tree(main_tree, distances_tree, helper_tree, data)) { *error_msg = "Cannot load dynamic Huffman tree!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; } break; case 3: *error_msg = "Unsupported (non-existing) type of compression!"; huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return 0; break; } if (btype > 0) { code = huffman_read_next_code(main_tree, data); if (code == -1) { huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); *error_msg = "Invalid data!"; return 0; } while (code != 256) { if (code < 256) { if (unpacked_index >= unpacked_length) { huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); *error_msg = "Too much data!"; return 0; } unpacked_data[unpacked_index++] = code; } else { length = 0; distance = 0; if (code >= 257 && code <= 264) { length = code - 257 + 3; } else if (code >= 265 && code <= 268) { length = (code - 265) * 2 + 11 + input_read_bit(data); } else if (code >= 269 && code <= 272) { length = (code - 269) * 4 + 19 + input_read_bits(data, 2); } else if (code >= 273 && code <= 276) { length = (code - 273) * 8 + 35 + input_read_bits(data, 3); } else if (code >= 277 && code <= 280) { length = (code - 277) * 16 + 67 + input_read_bits(data, 4); } else if (code >= 281 && code <= 284) { length = (code - 281) * 32 + 131 + input_read_bits(data, 5); } else if (code == 285) { length = 258; } else { huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); *error_msg = "Algorithm error: unknown length!"; return 0; } if (data->error) { huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); *error_msg = "Cannot read length!"; return 0; } distance = get_distance(distances_tree, data); if (distance == -1) { huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); *error_msg = "Algorithm error: bad distance!"; return 0; } for (i = 0; i < length; i++) { code = unpacked_data[unpacked_index - distance]; if (unpacked_index >= unpacked_length) { huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); *error_msg = "Too much data!"; return 0; } unpacked_data[unpacked_index++] = code; } } code = huffman_read_next_code(main_tree, data); if (code == -1) { huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); *error_msg = "Invalid data!"; return 0; } } } } while (bfinal == 0); huffman_destroy_tree(main_tree); huffman_destroy_tree(distances_tree); huffman_destroy_tree(helper_tree); return unpacked_index; }