unwhack.c 3.1 KB

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