unwhack.c (3191B)
1 #include "stdinc.h" 2 #include "whack.h" 3 4 enum 5 { 6 DMaxFastLen = 7, 7 DBigLenCode = 0x3c, /* minimum code for large lenth encoding */ 8 DBigLenBits = 6, 9 DBigLenBase = 1 /* starting items to encode for big lens */ 10 }; 11 12 static uchar lenval[1 << (DBigLenBits - 1)] = 13 { 14 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 3, 3, 3, 3, 3, 3, 3, 3, 16 4, 4, 4, 4, 17 5, 18 6, 19 255, 20 255 21 }; 22 23 static uchar lenbits[] = 24 { 25 0, 0, 0, 26 2, 3, 5, 5, 27 }; 28 29 static uchar offbits[16] = 30 { 31 5, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 12, 13 32 }; 33 34 static ushort offbase[16] = 35 { 36 0, 0x20, 37 0x40, 0x60, 38 0x80, 0xc0, 39 0x100, 0x180, 40 0x200, 0x300, 41 0x400, 0x600, 42 0x800, 0xc00, 43 0x1000, 44 0x2000 45 }; 46 47 void 48 unwhackinit(Unwhack *uw) 49 { 50 uw->err[0] = '\0'; 51 } 52 53 int 54 unwhack(Unwhack *uw, uchar *dst, int ndst, uchar *src, int nsrc) 55 { 56 uchar *s, *d, *dmax, *smax, lit; 57 ulong uwbits, lithist; 58 int i, off, len, bits, use, code, uwnbits, overbits; 59 60 d = dst; 61 dmax = d + ndst; 62 63 smax = src + nsrc; 64 uwnbits = 0; 65 uwbits = 0; 66 overbits = 0; 67 lithist = ~0; 68 while(src < smax || uwnbits - overbits >= MinDecode){ 69 while(uwnbits <= 24){ 70 uwbits <<= 8; 71 if(src < smax) 72 uwbits |= *src++; 73 else 74 overbits += 8; 75 uwnbits += 8; 76 } 77 78 /* 79 * literal 80 */ 81 len = lenval[(uwbits >> (uwnbits - 5)) & 0x1f]; 82 if(len == 0){ 83 if(lithist & 0xf){ 84 uwnbits -= 9; 85 lit = (uwbits >> uwnbits) & 0xff; 86 lit &= 255; 87 }else{ 88 uwnbits -= 8; 89 lit = (uwbits >> uwnbits) & 0x7f; 90 if(lit < 32){ 91 if(lit < 24){ 92 uwnbits -= 2; 93 lit = (lit << 2) | ((uwbits >> uwnbits) & 3); 94 }else{ 95 uwnbits -= 3; 96 lit = (lit << 3) | ((uwbits >> uwnbits) & 7); 97 } 98 lit = (lit - 64) & 0xff; 99 } 100 } 101 if(d >= dmax){ 102 snprint(uw->err, WhackErrLen, "too much output"); 103 return -1; 104 } 105 *d++ = lit; 106 lithist = (lithist << 1) | (lit < 32) | (lit > 127); 107 continue; 108 } 109 110 /* 111 * length 112 */ 113 if(len < 255) 114 uwnbits -= lenbits[len]; 115 else{ 116 uwnbits -= DBigLenBits; 117 code = ((uwbits >> uwnbits) & ((1 << DBigLenBits) - 1)) - DBigLenCode; 118 len = DMaxFastLen; 119 use = DBigLenBase; 120 bits = (DBigLenBits & 1) ^ 1; 121 while(code >= use){ 122 len += use; 123 code -= use; 124 code <<= 1; 125 uwnbits--; 126 if(uwnbits < 0){ 127 snprint(uw->err, WhackErrLen, "len out of range"); 128 return -1; 129 } 130 code |= (uwbits >> uwnbits) & 1; 131 use <<= bits; 132 bits ^= 1; 133 } 134 len += code; 135 136 while(uwnbits <= 24){ 137 uwbits <<= 8; 138 if(src < smax) 139 uwbits |= *src++; 140 else 141 overbits += 8; 142 uwnbits += 8; 143 } 144 } 145 146 /* 147 * offset 148 */ 149 uwnbits -= 4; 150 bits = (uwbits >> uwnbits) & 0xf; 151 off = offbase[bits]; 152 bits = offbits[bits]; 153 154 uwnbits -= bits; 155 off |= (uwbits >> uwnbits) & ((1 << bits) - 1); 156 off++; 157 158 if(off > d - dst){ 159 snprint(uw->err, WhackErrLen, "offset out of range: off=%d d=%ld len=%d nbits=%d", off, d - dst, len, uwnbits); 160 return -1; 161 } 162 if(d + len > dmax){ 163 snprint(uw->err, WhackErrLen, "len out of range"); 164 return -1; 165 } 166 s = d - off; 167 for(i = 0; i < len; i++) 168 d[i] = s[i]; 169 d += len; 170 } 171 if(uwnbits < overbits){ 172 snprint(uw->err, WhackErrLen, "compressed data overrun"); 173 return -1; 174 } 175 176 len = d - dst; 177 178 return len; 179 }