/* Lempel-Ziv-Tyr ;-) */ long CcffLoader::cff_unpacker::unpack(unsigned char *ibuf, unsigned char *obuf) { if (memcmp(ibuf,"YsComp""\x07""CUD1997""\x1A\x04",16)) return 0; input = ibuf + 16; output = obuf; output_length = 0; heap = (unsigned char *)malloc(0x10000); dictionary = (unsigned char **)malloc(sizeof(unsigned char *)*0x8000); memset(heap,0,0x10000); memset(dictionary,0,0x8000); cleanup(); if(!startup()) goto out; // LZW while (1) { new_code = get_code(); // 0x00: end of data if (new_code == 0) break; // 0x01: end of block if (new_code == 1) { cleanup(); if(!startup()) goto out; continue; } // 0x02: expand code length if (new_code == 2) { code_length++; continue; } // 0x03: RLE if (new_code == 3) { unsigned char old_code_length = code_length; code_length = 2; unsigned char repeat_length = get_code() + 1; code_length = 4 << get_code(); unsigned long repeat_counter = get_code(); if(output_length + repeat_counter * repeat_length > 0x10000) { output_length = 0; goto out; } for (unsigned int i=0;i<repeat_counter*repeat_length;i++) output[output_length++] = output[output_length - repeat_length]; code_length = old_code_length; if(!startup()) goto out; continue; } if (new_code >= (0x104 + dictionary_length)) { // dictionary <- old.code.string + old.code.char the_string[++the_string[0]] = the_string[1]; } else { // dictionary <- old.code.string + new.code.char unsigned char temp_string[256]; translate_code(new_code,temp_string); the_string[++the_string[0]] = temp_string[1]; } expand_dictionary(the_string); // output <- new.code.string translate_code(new_code,the_string); if(output_length + the_string[0] > 0x10000) { output_length = 0; goto out; } for (int i=0;i<the_string[0];i++) output[output_length++] = the_string[i+1]; old_code = new_code; } out: free(heap); free(dictionary); return output_length; }
/* Lempel-Ziv-Tyr ;-) */ void CffPlayer::cff_unpacker::unpack(const std::vector<uint8_t>& ibuf, std::vector<uint8_t>& obuf) { obuf.clear(); if(memcmp(ibuf.data(), "YsComp" "\x07" "CUD1997" "\x1A\x04", 16)) return; auto it = std::next(ibuf.begin(), 16); std::vector<std::vector<uint8_t>> dictionary; cleanup(); if(!startup(dictionary, obuf, it)) return; // LZW while(auto newCode = get_code(it)) { // 0x01: end of block if(newCode == 1) { cleanup(); dictionary.clear(); if(!startup(dictionary, obuf, it)) return; continue; } // 0x02: expand code length if(newCode == 2) { m_codeLength++; continue; } // 0x03: RLE if(newCode == 3) { uint8_t old_code_length = m_codeLength; m_codeLength = 2; uint8_t repeat_length = get_code(it) + 1; m_codeLength = 4 << get_code(it); unsigned long repeat_counter = get_code(it); if(obuf.size() + repeat_counter * repeat_length) { obuf.clear(); return; } for(auto i = 0; i < repeat_counter * repeat_length; i++) { obuf.emplace_back(obuf[obuf.size() - repeat_length]); } m_codeLength = old_code_length; if(!startup(dictionary, obuf, it)) return; continue; } if(newCode >= (0x104 + dictionary.size())) { // dictionary <- old.code.string + old.code.char m_theString[++m_theString[0]] = m_theString[1]; } else { // dictionary <- old.code.string + new.code.char uint8_t temp_string[256]; translate_code(newCode, temp_string, dictionary); m_theString[++m_theString[0]] = temp_string[1]; } expand_dictionary(m_theString, dictionary); // output <- new.code.string translate_code(newCode, m_theString, dictionary); for(int i = 0; i < m_theString[0]; i++) obuf.emplace_back(m_theString[i + 1]); } }