Skip to content
Snippets Groups Projects
Commit dcf958cd authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Merge branch 'lzh-refactor' into 'master'

Overhaul LZH code

See merge request !489
parents 868b7d82 5cfffef8
No related branches found
No related tags found
1 merge request!489Overhaul LZH code
Pipeline #7609 passed
...@@ -20,4 +20,4 @@ endif ...@@ -20,4 +20,4 @@ endif
# Test build # Test build
lzh${EXEFILE}: lzh.c lzh${EXEFILE}: lzh.c
$(QUIET)$(CC) -std=c11 $(CFLAGS) -DLZH_TEST $(CCFLAGS) -o $@ $< $(QUIET)$(CC) -std=c11 $(CFLAGS) -Wall -pedantic -DLZH_TEST $(CCFLAGS) -o $@ $<
...@@ -20,183 +20,166 @@ ...@@ -20,183 +20,166 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
   
/* FreeBSD's malloc.h is deprecated, it drops a warning and */ #include "xpendian.h"
/* #includes <stdlib.h>, which is already here. */
#if !defined(__unix__)
#include <malloc.h>
#endif
#include "lzh.h" #include "lzh.h"
   
#define REALLOC realloc
#define LMALLOC malloc
#define MALLOC malloc
#define LFREE free
#define FREE free
/* LZSS Parameters */ /* LZSS Parameters */
   
#define LZH_N 4096 /* Size of string buffer */ #define LZH_STRBUF_SZ 4096 /* Size of string buffer */
#define LZH_F 60 /* Size of look-ahead buffer */ #define LZH_LOOKAHD_SZ 60 /* Size of look-ahead buffer */
#define LZH_THRESHOLD 2 #define LZH_THRESHOLD 2
#define LZH_NIL LZH_N /* End of tree's node */ #define LZH_NIL LZH_STRBUF_SZ /* End of tree's node */
   
/* Huffman coding parameters */ /* Huffman coding parameters */
   
#define LZH_N_CHAR (256 - LZH_THRESHOLD + LZH_F) #define LZH_N_CHAR (256 - LZH_THRESHOLD + LZH_LOOKAHD_SZ)
/* character code (= 0..LZH_N_CHAR-1) */ /* character code (= 0..LZH_N_CHAR-1) */
#define LZH_T (LZH_N_CHAR * 2 - 1) /* Size of table */ #define LZH_TABLE_SZ (LZH_N_CHAR * 2 - 1) /* Size of table */
#define LZH_R (LZH_T - 1) /* root position */ #define LZH_ROOT (LZH_TABLE_SZ - 1) /* root position */
#define MAX_FREQ 0x8000 #define MAX_FREQ 0x8000
/* update when cumulative frequency */ /* update when cumulative frequency */
/* reaches to this value */ /* reaches to this value */
   
/* Converted from global variables to struct Apr-21-2003 */ // Shared struct
typedef struct { typedef struct {
   
#ifdef LZH_DYNAMIC_BUF uint16_t freq[LZH_TABLE_SZ + 1]; /* cumulative freq table */
uint16_t parent[LZH_TABLE_SZ + LZH_N_CHAR];
uint16_t child[LZH_TABLE_SZ + 1]; /* bug fixed by Digital Dynamics */
   
unsigned char* text_buf; } huffman_t;
short int match_position, match_length,
*lson, *rson, *dad;
   
unsigned short* freq; /* cumulative freq table */ /* Converted from global variables to struct Apr-21-2003 */
typedef struct {
/*
* pointing parent nodes.
* area [LZH_T..(LZH_T + LZH_N_CHAR - 1)] are pointers for leaves
*/
short int* prnt;
/* pointing children nodes (son[], son[] + 1)*/
short int* son;
#else /* STATIC */
   
unsigned char text_buf[LZH_N + LZH_F - 1]; huffman_t huff;
short int match_position, match_length, uint16_t getbuf; /* Was just "unsigned" fixed 04/12/95 */
lson[LZH_N + 1], rson[LZH_N + 257], dad[LZH_N + 1]; uint8_t text_buf[LZH_STRBUF_SZ];
uint8_t getlen;
size_t outsz;
   
unsigned short freq[LZH_T + 1]; /* cumulative freq table */ } lzh_decode_t;
short int prnt[LZH_T + LZH_N_CHAR];
short int son[LZH_T + 1]; /* bug fixed by Digital Dynamics */
   
#endif typedef struct {
   
unsigned short getbuf; /* Was just "unsigned" fixed 04/12/95 */ uint32_t putbuf;
uint8_t getlen; huffman_t huff;
unsigned putbuf; uint16_t lchild[LZH_STRBUF_SZ + 1];
uint16_t rchild[LZH_STRBUF_SZ + 257];
uint16_t eparent[LZH_STRBUF_SZ + 1];
uint16_t match_position;
uint16_t match_length;
uint8_t text_buf[LZH_STRBUF_SZ + LZH_LOOKAHD_SZ - 1];
uint8_t putlen; uint8_t putlen;
size_t outsz;
   
unsigned short code, len; } lzh_encode_t;
} lzh_t;
   
static void lzh_init_tree(lzh_t* lzh) /* Initializing tree */ static void lzh_init_tree(lzh_encode_t* lzh) /* Initializing tree */
{ {
short int i; unsigned i;
   
for (i = LZH_N + 1; i <= LZH_N + 256; i++) for (i = LZH_STRBUF_SZ + 1; i <= LZH_STRBUF_SZ + 256; i++)
lzh->rson[i] = LZH_NIL; /* root */ lzh->rchild[i] = LZH_NIL; /* root */
for (i = 0; i < LZH_N; i++) for (i = 0; i < LZH_STRBUF_SZ; i++)
lzh->dad[i] = LZH_NIL; /* node */ lzh->eparent[i] = LZH_NIL; /* node */
} }
   
/******************************/ /******************************/
/* Inserting node to the tree */ /* Inserting node to the tree */
/* Only used during encoding */ /* Only used during encoding */
/******************************/ /******************************/
static void lzh_insert_node(lzh_t* lzh, short int r) static void lzh_insert_node(lzh_encode_t* lzh, uint16_t r)
{ {
short int i, p, cmp; unsigned i;
unsigned char *key;
unsigned c; unsigned c;
int cmp;
uint16_t p;
uint8_t *key;
   
cmp = 1; cmp = 1;
key = lzh->text_buf+r; key = lzh->text_buf+r;
p = LZH_N + 1 + key[0]; p = LZH_STRBUF_SZ + 1 + key[0];
lzh->rson[r] = lzh->lson[r] = LZH_NIL; lzh->rchild[r] = lzh->lchild[r] = LZH_NIL;
lzh->match_length = 0; lzh->match_length = 0;
for ( ; ; ) { for ( ; ; ) {
if (cmp >= 0) { if (cmp >= 0) {
if (lzh->rson[p] != LZH_NIL) if (lzh->rchild[p] != LZH_NIL)
p = lzh->rson[p]; p = lzh->rchild[p];
else { else {
lzh->rson[p] = r; lzh->rchild[p] = r;
lzh->dad[r] = p; lzh->eparent[r] = p;
return; return;
} }
} else { } else {
if (lzh->lson[p] != LZH_NIL) if (lzh->lchild[p] != LZH_NIL)
p = lzh->lson[p]; p = lzh->lchild[p];
else { else {
lzh->lson[p] = r; lzh->lchild[p] = r;
lzh->dad[r] = p; lzh->eparent[r] = p;
return; return;
} }
} }
for (i = 1; i < LZH_F; i++) for (i = 1; i < LZH_LOOKAHD_SZ; i++)
if ((cmp = key[i] - lzh->text_buf[p + i]) != 0) if ((cmp = key[i] - lzh->text_buf[p + i]) != 0)
break; break;
if (i > LZH_THRESHOLD) { if (i > LZH_THRESHOLD) {
if (i > lzh->match_length) { if (i > lzh->match_length) {
lzh->match_position = ((r - p) & (LZH_N - 1)) - 1; lzh->match_position = ((r - p) & (LZH_STRBUF_SZ - 1)) - 1;
if ((lzh->match_length = i) >= LZH_F) if ((lzh->match_length = i) >= LZH_LOOKAHD_SZ)
break; break;
} }
if (i == lzh->match_length) { if (i == lzh->match_length) {
if ((c = ((r - p) & (LZH_N - 1)) - 1) if ((c = ((r - p) & (LZH_STRBUF_SZ - 1)) - 1)
< (unsigned)lzh->match_position) { < lzh->match_position) {
lzh->match_position = c; lzh->match_position = c;
} }
} }
} }
} }
lzh->dad[r] = lzh->dad[p]; lzh->eparent[r] = lzh->eparent[p];
lzh->lson[r] = lzh->lson[p]; lzh->lchild[r] = lzh->lchild[p];
lzh->rson[r] = lzh->rson[p]; lzh->rchild[r] = lzh->rchild[p];
lzh->dad[lzh->lson[p]] = r; lzh->eparent[lzh->lchild[p]] = r;
lzh->dad[lzh->rson[p]] = r; lzh->eparent[lzh->rchild[p]] = r;
if (lzh->rson[lzh->dad[p]] == p) if (lzh->rchild[lzh->eparent[p]] == p)
lzh->rson[lzh->dad[p]] = r; lzh->rchild[lzh->eparent[p]] = r;
else else
lzh->lson[lzh->dad[p]] = r; lzh->lchild[lzh->eparent[p]] = r;
lzh->dad[p] = LZH_NIL; /* remove p */ lzh->eparent[p] = LZH_NIL; /* remove p */
} }
   
static void lzh_delete_node(lzh_t* lzh, short int p) /* Deleting node from the tree */ static void lzh_delete_node(lzh_encode_t* lzh, uint16_t p) /* Deleting node from the tree */
{ {
short int q; uint16_t q;
   
if (lzh->dad[p] == LZH_NIL) if (lzh->eparent[p] == LZH_NIL)
return; /* unregistered */ return; /* unregistered */
if (lzh->rson[p] == LZH_NIL) if (lzh->rchild[p] == LZH_NIL)
q = lzh->lson[p]; q = lzh->lchild[p];
else else
if (lzh->lson[p] == LZH_NIL) if (lzh->lchild[p] == LZH_NIL)
q = lzh->rson[p]; q = lzh->rchild[p];
else { else {
q = lzh->lson[p]; q = lzh->lchild[p];
if (lzh->rson[q] != LZH_NIL) { if (lzh->rchild[q] != LZH_NIL) {
do { do {
q = lzh->rson[q]; q = lzh->rchild[q];
} while (lzh->rson[q] != LZH_NIL); } while (lzh->rchild[q] != LZH_NIL);
lzh->rson[lzh->dad[q]] = lzh->lson[q]; lzh->rchild[lzh->eparent[q]] = lzh->lchild[q];
lzh->dad[lzh->lson[q]] = lzh->dad[q]; lzh->eparent[lzh->lchild[q]] = lzh->eparent[q];
lzh->lson[q] = lzh->lson[p]; lzh->lchild[q] = lzh->lchild[p];
lzh->dad[lzh->lson[p]] = q; lzh->eparent[lzh->lchild[p]] = q;
} }
lzh->rson[q] = lzh->rson[p]; lzh->rchild[q] = lzh->rchild[p];
lzh->dad[lzh->rson[p]] = q; lzh->eparent[lzh->rchild[p]] = q;
} }
lzh->dad[q] = lzh->dad[p]; lzh->eparent[q] = lzh->eparent[p];
if (lzh->rson[lzh->dad[p]] == p) if (lzh->rchild[lzh->eparent[p]] == p)
lzh->rson[lzh->dad[p]] = q; lzh->rchild[lzh->eparent[p]] = q;
else else
lzh->lson[lzh->dad[p]] = q; lzh->lchild[lzh->eparent[p]] = q;
lzh->dad[p] = LZH_NIL; lzh->eparent[p] = LZH_NIL;
} }
   
/* /*
...@@ -298,50 +281,56 @@ static uint8_t lzh_d_len[256] = { ...@@ -298,50 +281,56 @@ static uint8_t lzh_d_len[256] = {
}; };
   
   
static int lzh_getbit(lzh_t* lzh, uint8_t *inbuf, int32_t *incnt, long inlen) /* get one bit */ static bool lzh_getbit(lzh_decode_t* lzh, const uint8_t *inbuf, uint32_t *incnt, uint32_t inlen) /* get one bit */
{ {
short int i; bool ret;
uint8_t ch;
   
while (lzh->getlen <= 8) { while (lzh->getlen <= 8) {
if ((*incnt) >= inlen) if ((*incnt) >= inlen)
i=0; ch = 0;
else else
i=inbuf[(*incnt)++]; ch = inbuf[(*incnt)++];
lzh->getbuf |= i << (8 - lzh->getlen); lzh->getbuf |= ch << (8 - lzh->getlen);
lzh->getlen += 8; lzh->getlen += 8;
} }
i = lzh->getbuf; ret = !!(lzh->getbuf & 0x8000);
lzh->getbuf <<= 1; lzh->getbuf <<= 1;
lzh->getlen--; lzh->getlen--;
return (i < 0); return (ret);
} }
   
static short int lzh_getbyte(lzh_t* lzh, uint8_t *inbuf, int32_t *incnt, long inlen) /* get a byte */ static uint8_t lzh_getbyte(lzh_decode_t* lzh, const uint8_t *inbuf, uint32_t *incnt, uint32_t inlen) /* get a byte */
{ {
unsigned short i; uint8_t ret;
uint8_t ch;
   
while (lzh->getlen <= 8) { while (lzh->getlen <= 8) {
if((*incnt)>=inlen) if((*incnt)>=inlen)
i=0; ch = 0;
else else
i=inbuf[(*incnt)++]; ch = inbuf[(*incnt)++];
lzh->getbuf |= i << (8 - lzh->getlen); lzh->getbuf |= ch << (8 - lzh->getlen);
lzh->getlen += 8; lzh->getlen += 8;
} }
i = lzh->getbuf; ret = lzh->getbuf >> 8;
lzh->getbuf <<= 8; lzh->getbuf <<= 8;
lzh->getlen -= 8; lzh->getlen -= 8;
return i >> 8; return ret;
} }
   
   
/* output c bits */ /* output c bits */
static void lzh_putcode(lzh_t* lzh, short int l, unsigned short c, uint8_t *outbuf, int32_t *outlen) static bool lzh_putcode(lzh_encode_t* lzh, uint16_t l, uint16_t c, uint8_t *outbuf, uint32_t *outlen)
{ {
lzh->putbuf |= c >> lzh->putlen; lzh->putbuf |= c >> lzh->putlen;
if ((lzh->putlen += l) >= 8) { if ((lzh->putlen += l) >= 8) {
if (*outlen >= lzh->outsz || *outlen == UINT32_MAX)
return false;
outbuf[(*outlen)++]=(lzh->putbuf >> 8); outbuf[(*outlen)++]=(lzh->putbuf >> 8);
if ((lzh->putlen -= 8) >= 8) { if ((lzh->putlen -= 8) >= 8) {
if (*outlen >= lzh->outsz || *outlen == UINT32_MAX)
return false;
outbuf[(*outlen)++]=lzh->putbuf; outbuf[(*outlen)++]=lzh->putbuf;
lzh->putlen -= 8; lzh->putlen -= 8;
lzh->putbuf = c << (l - lzh->putlen); lzh->putbuf = c << (l - lzh->putlen);
...@@ -349,121 +338,144 @@ static void lzh_putcode(lzh_t* lzh, short int l, unsigned short c, uint8_t *outb ...@@ -349,121 +338,144 @@ static void lzh_putcode(lzh_t* lzh, short int l, unsigned short c, uint8_t *outb
lzh->putbuf <<= 8; lzh->putbuf <<= 8;
} }
} }
return true;
} }
   
   
/* initialize freq tree */ /* initialize freq tree */
   
static void lzh_start_huff(lzh_t* lzh) static void lzh_start_huff(huffman_t* huff)
{ {
short int i, j; unsigned i;
unsigned j;
   
for (i = 0; i < LZH_N_CHAR; i++) { for (i = 0; i < LZH_N_CHAR; i++) {
lzh->freq[i] = 1; huff->freq[i] = 1;
lzh->son[i] = i + LZH_T; huff->child[i] = i + LZH_TABLE_SZ;
lzh->prnt[i + LZH_T] = i; huff->parent[i + LZH_TABLE_SZ] = i;
} }
i = 0; j = LZH_N_CHAR; i = 0; j = LZH_N_CHAR;
while (j <= LZH_R) { while (j <= LZH_ROOT) {
lzh->freq[j] = lzh->freq[i] + lzh->freq[i + 1]; huff->freq[j] = huff->freq[i] + huff->freq[i + 1];
lzh->son[j] = i; huff->child[j] = i;
lzh->prnt[i] = lzh->prnt[i + 1] = j; huff->parent[i] = huff->parent[i + 1] = j;
i += 2; j++; i += 2; j++;
} }
lzh->freq[LZH_T] = 0xffff; huff->freq[LZH_TABLE_SZ] = 0xffff;
lzh->prnt[LZH_R] = 0; huff->parent[LZH_ROOT] = 0;
} }
   
   
/* reconstruct freq tree */ /* reconstruct freq tree */
   
static void lzh_reconst(lzh_t* lzh) static void lzh_reconst(huffman_t* huff)
{ {
short int i, j, k; unsigned i;
unsigned short f, l; unsigned j;
unsigned k;
uint16_t f;
uint16_t l;
   
/* halven cumulative freq for leaf nodes */ /* halven cumulative freq for leaf nodes */
j = 0; j = 0;
for (i = 0; i < LZH_T; i++) { for (i = 0; i < LZH_TABLE_SZ; i++) {
if (lzh->son[i] >= LZH_T) { if (huff->child[i] >= LZH_TABLE_SZ) {
lzh->freq[j] = (lzh->freq[i] + 1) / 2; huff->freq[j] = (huff->freq[i] + 1) / 2;
lzh->son[j] = lzh->son[i]; huff->child[j] = huff->child[i];
j++; j++;
} }
} }
/* make a tree : first, connect children nodes */ /* make a tree : first, connect children nodes */
for (i = 0, j = LZH_N_CHAR; j < LZH_T; i += 2, j++) { for (i = 0, j = LZH_N_CHAR; j < LZH_TABLE_SZ; i += 2, j++) {
k = i + 1; k = i + 1;
f = lzh->freq[j] = lzh->freq[i] + lzh->freq[k]; f = huff->freq[j] = huff->freq[i] + huff->freq[k];
for (k = j - 1; f < lzh->freq[k]; k--); for (k = j - 1; f < huff->freq[k]; k--);
k++; k++;
l = (j - k) * 2; l = (j - k) * 2;
/* movmem() is Turbo-C dependent /* movmem() is Turbo-C dependent
rewritten to memmove() by Kenji */ rewritten to memmove() by Kenji */
/* movmem(&lzh->freq[k], &lzh->freq[k + 1], l); */ /* movmem(&huff->freq[k], &huff->freq[k + 1], l); */
(void)memmove(lzh->freq+k+1,lzh->freq+k, l); (void)memmove(huff->freq+k+1,huff->freq+k, l);
lzh->freq[k] = f; huff->freq[k] = f;
/* movmem(&lzh->son[k], &lzh->son[k + 1], l); */ /* movmem(&huff->child[k], &huff->child[k + 1], l); */
(void)memmove(lzh->son+k+1,lzh->son+k, l); (void)memmove(huff->child+k+1,huff->child+k, l);
lzh->son[k] = i; huff->child[k] = i;
} }
/* connect parent nodes */ /* connect parent nodes */
for (i = 0; i < LZH_T; i++) { for (i = 0; i < LZH_TABLE_SZ; i++) {
if ((k = lzh->son[i]) >= LZH_T) { if ((k = huff->child[i]) >= LZH_TABLE_SZ) {
lzh->prnt[k] = i; huff->parent[k] = i;
} else { } else {
lzh->prnt[k] = lzh->prnt[k + 1] = i; huff->parent[k] = huff->parent[k + 1] = i;
} }
} }
} }
   
/* update freq tree */ /* update freq tree */
   
static void lzh_update(lzh_t* lzh, short int c) static void lzh_update(huffman_t* huff, uint16_t c)
{ {
short int i, j, k, l; uint16_t l;
uint16_t tmp;
uint16_t tmp2;
   
if (lzh->freq[LZH_R] == MAX_FREQ) { // If freq is already max, halve all of them
lzh_reconst(lzh); if (huff->freq[LZH_ROOT] == MAX_FREQ) {
lzh_reconst(huff);
} }
c = lzh->prnt[c + LZH_T]; c = huff->parent[c + LZH_TABLE_SZ];
do { do {
k = ++lzh->freq[c]; tmp = ++huff->freq[c];
   
/* swap nodes to keep the tree freq-ordered */ /*
if (((unsigned)k) > ((unsigned)lzh->freq[l = c + 1])) { * If we now have a greater freq than the next node...
while (l < LZH_T && k > lzh->freq[++l]) * and are not already the last node
*/
if (c < LZH_TABLE_SZ && tmp > huff->freq[c + 1]) {
/*
* Find the last node after the current one
* that has a lower frequency than our new one
*/
for (l = c + 1; l <= LZH_TABLE_SZ && tmp > huff->freq[l]; l++)
; ;
// If we exited before the end of table, decrement l
if (tmp <= huff->freq[l])
l--; l--;
lzh->freq[c] = lzh->freq[l];
lzh->freq[l] = k;
   
i = lzh->son[c]; // Now swap nodes
lzh->prnt[i] = l; huff->freq[c] = huff->freq[l];
if (i < LZH_T) lzh->prnt[i + 1] = l; huff->freq[l] = tmp;
tmp = huff->child[c];
huff->parent[tmp] = l;
if (tmp < LZH_TABLE_SZ)
huff->parent[tmp + 1] = l;
   
j = lzh->son[l]; tmp2 = huff->child[l];
lzh->son[l] = i; huff->child[l] = tmp;
   
lzh->prnt[j] = c; huff->parent[tmp2] = c;
if (j < LZH_T) lzh->prnt[j + 1] = c; if (tmp2 < LZH_TABLE_SZ)
lzh->son[c] = j; huff->parent[tmp2 + 1] = c;
huff->child[c] = tmp2;
   
c = l; c = l;
} }
} while (((c = lzh->prnt[c]) != 0) && c < ((sizeof(lzh->son)/sizeof(lzh->son[0]))-1)); /* do it until reaching the root */ } while (((c = huff->parent[c]) != 0) && c < ((sizeof(huff->child)/sizeof(huff->child[0]))-1)); /* do it until reaching the root */
} }
   
static void lzh_encode_char(lzh_t* lzh, unsigned short c, uint8_t *outbuf, int32_t *outlen) static bool lzh_encode_char(lzh_encode_t* lzh, uint16_t c, uint8_t *outbuf, uint32_t *outlen)
{ {
unsigned short i; uint16_t k;
short int j, k; uint16_t j;
uint16_t i;
   
i = 0; i = 0;
j = 0; j = 0;
k = lzh->prnt[c + LZH_T]; k = lzh->huff.parent[c + LZH_TABLE_SZ];
   
/* search connections from leaf node to the root */ /* search connections from leaf node to the root */
do { do {
...@@ -473,68 +485,76 @@ static void lzh_encode_char(lzh_t* lzh, unsigned short c, uint8_t *outbuf, int32 ...@@ -473,68 +485,76 @@ static void lzh_encode_char(lzh_t* lzh, unsigned short c, uint8_t *outbuf, int32
if node's address is odd, output 1 if node's address is odd, output 1
else output 0 else output 0
*/ */
if (k & 1) i += 0x8000; if (k & 1)
i |= 0x8000;
   
j++; j++;
} while ((k = lzh->prnt[k]) != LZH_R); } while ((k = lzh->huff.parent[k]) != LZH_ROOT);
lzh_putcode(lzh, j, i, outbuf, outlen); if (!lzh_putcode(lzh, j, i, outbuf, outlen))
lzh->code = i; return false;
lzh->len = j; lzh_update(&lzh->huff,c);
lzh_update(lzh,c); return true;
} }
   
static void lzh_encode_position(lzh_t* lzh, unsigned short c, uint8_t *outbuf, int32_t *outlen) static bool lzh_encode_position(lzh_encode_t* lzh, uint16_t c, uint8_t *outbuf, uint32_t *outlen)
{ {
unsigned short i; unsigned i;
   
/* output upper 6 bits with encoding */ /* output upper 6 bits with encoding */
i = c >> 6; i = c >> 6;
lzh_putcode(lzh, lzh_p_len[i], (unsigned short)(lzh_p_code[i] << 8), outbuf, outlen); if (!lzh_putcode(lzh, lzh_p_len[i], (lzh_p_code[i] << 8), outbuf, outlen))
return false;
   
/* output lower 6 bits directly */ /* output lower 6 bits directly */
lzh_putcode(lzh, 6, (unsigned short)((c & 0x3f) << 10), outbuf, outlen); return lzh_putcode(lzh, 6, (c & 0x3f) << 10, outbuf, outlen);
} }
   
static void lzh_encode_end(lzh_t* lzh, uint8_t *outbuf, int32_t *outlen) static bool lzh_encode_end(lzh_encode_t* lzh, uint8_t *outbuf, uint32_t *outlen)
{ {
if (lzh->putlen) { if (lzh->putlen) {
if (*outlen >= lzh->outsz || *outlen == UINT32_MAX)
return false;
outbuf[(*outlen)++]=(lzh->putbuf >> 8); outbuf[(*outlen)++]=(lzh->putbuf >> 8);
} }
return true;
} }
   
static short int lzh_decode_char(lzh_t* lzh, uint8_t *inbuf, int32_t *incnt, long inlen) static uint16_t lzh_decode_char(lzh_decode_t* lzh, const uint8_t *inbuf, uint32_t *incnt, uint32_t inlen)
{ {
unsigned short c; uint16_t c;
   
c = lzh->son[LZH_R]; c = lzh->huff.child[LZH_ROOT];
   
/* /*
* start searching tree from the root to leaves. * start searching tree from the root to leaves.
* choose node #(lzh.son[]) if input bit == 0 * choose node #(lzh.child[]) if input bit == 0
* else choose #(lzh.son[]+1) (input bit == 1) * else choose #(lzh.child[]+1) (input bit == 1)
*/ */
while (c < LZH_T) { while (c < LZH_TABLE_SZ) {
c += lzh_getbit(lzh,inbuf,incnt,inlen); c += lzh_getbit(lzh,inbuf,incnt,inlen);
c = lzh->son[c]; c = lzh->huff.child[c];
} }
c -= LZH_T; c -= LZH_TABLE_SZ;
lzh_update(lzh,c); lzh_update(&lzh->huff,c);
return c; return c;
} }
   
static short int lzh_decode_position(lzh_t* lzh, uint8_t *inbuf, int32_t *incnt, long inlen) static uint16_t lzh_decode_position(lzh_decode_t* lzh, const uint8_t *inbuf, uint32_t *incnt, uint32_t inlen)
{ {
unsigned short i, j, c; unsigned i;
unsigned j;
uint16_t c;
   
/* decode upper 6 bits from given table */ /* decode upper 6 bits from given table */
i = lzh_getbyte(lzh,inbuf,incnt,inlen); i = lzh_getbyte(lzh,inbuf,incnt,inlen);
c = (unsigned)lzh_d_code[i] << 6; c = lzh_d_code[i];
c <<= 6;
j = lzh_d_len[i]; j = lzh_d_len[i];
   
/* input lower 6 bits directly */ /* input lower 6 bits directly */
j -= 2; j -= 2;
while (j--) { while (j--) {
i = (i << 1) + lzh_getbit(lzh,inbuf,incnt,inlen); i = (i << 1) | lzh_getbit(lzh,inbuf,incnt,inlen);
} }
return c | (i & 0x3f); return c | (i & 0x3f);
} }
...@@ -543,76 +563,31 @@ static short int lzh_decode_position(lzh_t* lzh, uint8_t *inbuf, int32_t *incnt, ...@@ -543,76 +563,31 @@ static short int lzh_decode_position(lzh_t* lzh, uint8_t *inbuf, int32_t *incnt,
   
/* Encoding/Compressing */ /* Encoding/Compressing */
/* Returns length of outbuf */ /* Returns length of outbuf */
int32_t lzh_encode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf) uint32_t lzh_encode(const uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, size_t outsz)
{ {
short int i, c, len, r, s, last_match_length; uint16_t i, c, len, r, s, last_match_length;
int32_t incnt,outlen; /* textsize=0; */ uint32_t incnt,outlen;
lzh_t lzh; lzh_encode_t lzh;
memset(&lzh,0,sizeof(lzh)); memset(&lzh,0,sizeof(lzh));
lzh.outsz = outsz;
#ifdef LZH_DYNAMIC_BUF
if((lzh.text_buf=(uint8_t *)malloc(LZH_N + LZH_F - 1))==NULL)
return(-1);
if((lzh.freq=(unsigned short*)malloc((LZH_T + 1)*sizeof(unsigned short)))==NULL) {
free(lzh.text_buf);
return(-1); }
if((lzh.prnt=(short *)malloc((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
free(lzh.text_buf);
free(lzh.freq);
return(-1); }
if((lzh.son=(short *)malloc((LZH_T + 1) * sizeof(short)))==NULL) {
free(lzh.text_buf);
free(lzh.prnt);
free(lzh.freq);
return(-1); }
if((lzh.lson=(short *)malloc((LZH_N + 1)*sizeof(short)))==NULL) {
free(lzh.text_buf);
free(lzh.prnt);
free(lzh.freq);
free(lzh.son);
return(-1); }
if((lzh.rson=(short *)malloc((LZH_N + 257)*sizeof(short)))==NULL) {
free(lzh.text_buf);
free(lzh.prnt);
free(lzh.freq);
free(lzh.son);
free(lzh.lson);
return(-1); }
if((lzh.dad=(short *)malloc((LZH_N + 1)*sizeof(short)))==NULL) {
free(lzh.text_buf);
free(lzh.prnt);
free(lzh.freq);
free(lzh.son);
free(lzh.lson);
free(lzh.rson);
return(-1); }
#endif
   
incnt=0; incnt=0;
inlen = LE_INT32(inlen);
memcpy(outbuf,&inlen,sizeof(inlen)); memcpy(outbuf,&inlen,sizeof(inlen));
inlen = LE_INT32(inlen);
outlen=sizeof(inlen); outlen=sizeof(inlen);
if(!inlen) { if(!inlen)
#ifdef LZH_DYNAMIC_BUF return(0);
free(lzh.text_buf); lzh_start_huff(&lzh.huff);
free(lzh.prnt);
free(lzh.freq);
free(lzh.son);
free(lzh.lson);
free(lzh.rson);
free(lzh.dad);
#endif
return(outlen); }
lzh_start_huff(&lzh);
lzh_init_tree(&lzh); lzh_init_tree(&lzh);
s = 0; s = 0;
r = LZH_N - LZH_F; r = LZH_STRBUF_SZ - LZH_LOOKAHD_SZ;
for (i = s; i < r; i++) for (i = s; i < r; i++)
lzh.text_buf[i] = ' '; lzh.text_buf[i] = ' ';
for (len = 0; len < LZH_F && incnt<inlen; len++) for (len = 0; len < LZH_LOOKAHD_SZ && incnt<inlen; len++)
lzh.text_buf[r + len] = inbuf[incnt++]; lzh.text_buf[r + len] = inbuf[incnt++];
/* textsize = len; */ /* textsize = len; */
for (i = 1; i <= LZH_F; i++) for (i = 1; i <= LZH_LOOKAHD_SZ; i++)
lzh_insert_node(&lzh,(short)(r - i)); lzh_insert_node(&lzh,(short)(r - i));
lzh_insert_node(&lzh,r); lzh_insert_node(&lzh,r);
do { do {
...@@ -620,131 +595,95 @@ int32_t lzh_encode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf) ...@@ -620,131 +595,95 @@ int32_t lzh_encode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf)
lzh.match_length = len; lzh.match_length = len;
if (lzh.match_length <= LZH_THRESHOLD) { if (lzh.match_length <= LZH_THRESHOLD) {
lzh.match_length = 1; lzh.match_length = 1;
lzh_encode_char(&lzh,lzh.text_buf[r],outbuf,&outlen); if (!lzh_encode_char(&lzh,lzh.text_buf[r],outbuf,&outlen))
return 0;
} else { } else {
lzh_encode_char(&lzh,(unsigned short)(255 - LZH_THRESHOLD + lzh.match_length) if (!lzh_encode_char(&lzh,(255 - LZH_THRESHOLD + lzh.match_length) ,outbuf,&outlen))
,outbuf,&outlen); return 0;
lzh_encode_position(&lzh,lzh.match_position if (!lzh_encode_position(&lzh,lzh.match_position,outbuf,&outlen))
,outbuf,&outlen); return 0;
} }
last_match_length = lzh.match_length; last_match_length = lzh.match_length;
for (i = 0; i < last_match_length && incnt<inlen; i++) { for (i = 0; i < last_match_length && incnt<inlen; i++) {
lzh_delete_node(&lzh,s); lzh_delete_node(&lzh,s);
c=inbuf[incnt++]; c=inbuf[incnt++];
lzh.text_buf[s] = (uint8_t)c; lzh.text_buf[s] = (uint8_t)c;
if (s < LZH_F - 1) if (s < LZH_LOOKAHD_SZ - 1)
lzh.text_buf[s + LZH_N] = (uint8_t)c; lzh.text_buf[s + LZH_STRBUF_SZ] = (uint8_t)c;
s = (s + 1) & (LZH_N - 1); s = (s + 1) & (LZH_STRBUF_SZ - 1);
r = (r + 1) & (LZH_N - 1); r = (r + 1) & (LZH_STRBUF_SZ - 1);
lzh_insert_node(&lzh,r); lzh_insert_node(&lzh,r);
} }
/***
if ((textsize += i) > printcount) {
printf("%12ld\r", textsize);
printcount += 1024;
}
***/
while (i++ < last_match_length) { while (i++ < last_match_length) {
lzh_delete_node(&lzh,s); lzh_delete_node(&lzh,s);
s = (s + 1) & (LZH_N - 1); s = (s + 1) & (LZH_STRBUF_SZ - 1);
r = (r + 1) & (LZH_N - 1); r = (r + 1) & (LZH_STRBUF_SZ - 1);
if (--len) lzh_insert_node(&lzh,r); if (--len) lzh_insert_node(&lzh,r);
} }
} while (len > 0); } while (len > 0);
lzh_encode_end(&lzh,outbuf,&outlen); if (!lzh_encode_end(&lzh,outbuf,&outlen))
return 0;
/* /*
printf("input: %ld (%ld) bytes\n", inlen,textsize); printf("input: %" PRId32 " bytes\n", inlen);
printf("output: %ld bytes\n", outlen); printf("output: %" PRId32 " bytes\n", outlen);
printf("output/input: %.3f\n", (double)outlen / inlen); printf("output/input: %.3f\n", (double)outlen / inlen);
*/ */
   
#ifdef LZH_DYNAMIC_BUF
free(lzh.text_buf);
free(lzh.prnt);
free(lzh.freq);
free(lzh.son);
free(lzh.lson);
free(lzh.rson);
free(lzh.dad);
#endif
return(outlen); return(outlen);
} }
   
/* Decoding/Uncompressing */ /* Decoding/Uncompressing */
/* Returns length of outbuf */ /* Returns length of outbuf */
int32_t lzh_decode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf) uint32_t lzh_decode(const uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, size_t outlen)
{ {
short int i, j, k, r, c; uint16_t i, j, k, r, c;
uint32_t count; uint32_t count;
int32_t incnt,textsize;
lzh_t lzh;
   
memset(&lzh,0,sizeof(lzh)); uint32_t incnt;
#ifdef LZH_DYNAMIC_BUF uint32_t textsize;
lzh_decode_t lzh;
if((lzh.text_buf=(uint8_t *)malloc((LZH_N + LZH_F - 1)*2))==NULL)
return(-1);
if((lzh.freq=(unsigned short *)malloc((LZH_T + 1)*sizeof(unsigned short)))
==NULL) {
free(lzh.text_buf);
return(-1); }
if((lzh.prnt=(short *)malloc((LZH_T + LZH_N_CHAR)*sizeof(short)))==NULL) {
free(lzh.text_buf);
free(lzh.freq);
return(-1); }
if((lzh.son=(short *)malloc((LZH_T + 1) * sizeof(short)))==NULL) {
free(lzh.text_buf);
free(lzh.prnt);
free(lzh.freq);
return(-1); }
   
#endif memset(&lzh,0,sizeof(lzh));
lzh.outsz = outlen;
   
incnt=0; incnt=0;
memcpy(&textsize,inbuf,sizeof(textsize)); memcpy(&textsize,inbuf,sizeof(textsize));
textsize = LE_INT32(textsize);
if (textsize > outlen)
return 0;
incnt+=sizeof(textsize); incnt+=sizeof(textsize);
if (textsize == 0) { if (textsize == 0)
#ifdef LZH_DYNAMIC_BUF return(textsize);
free(lzh.text_buf); lzh_start_huff(&lzh.huff);
free(lzh.prnt); for (i = 0; i < LZH_STRBUF_SZ - LZH_LOOKAHD_SZ; i++)
free(lzh.freq);
free(lzh.son);
#endif
return(textsize); }
lzh_start_huff(&lzh);
for (i = 0; i < LZH_N - LZH_F; i++)
*(lzh.text_buf+i) = ' '; *(lzh.text_buf+i) = ' ';
r = LZH_N - LZH_F; r = LZH_STRBUF_SZ - LZH_LOOKAHD_SZ;
for (count = 0; count < (unsigned long)textsize; ) { for (count = 0; count < textsize; ) {
c = lzh_decode_char(&lzh,inbuf,&incnt,inlen); c = lzh_decode_char(&lzh,inbuf,&incnt,inlen);
if (c < 256) { if (c < 256) {
if (count >= outlen || count == UINT32_MAX)
return 0;
outbuf[count]=(uint8_t)c; outbuf[count]=(uint8_t)c;
#if 0 if (r >= LZH_STRBUF_SZ)
if(r>(LZH_N + LZH_F - 1) || r<0) { return 0;
printf("Overflow! (%d)\n",r);
getch();
exit(-1); }
#endif
*(lzh.text_buf+r) = (uint8_t)c; *(lzh.text_buf+r) = (uint8_t)c;
r++; r++;
r &= (LZH_N - 1); r &= (LZH_STRBUF_SZ - 1);
count++; count++;
} else { } else {
i = (r - lzh_decode_position(&lzh,inbuf,&incnt,inlen) - 1) i = (r - lzh_decode_position(&lzh,inbuf,&incnt,inlen) - 1)
& (LZH_N - 1); & (LZH_STRBUF_SZ - 1);
j = c - 255 + LZH_THRESHOLD; j = c - 255 + LZH_THRESHOLD;
for (k = 0; k < j && count<(unsigned long)textsize; k++) { for (k = 0; k < j && count<textsize; k++) {
c = lzh.text_buf[(i + k) & (LZH_N - 1)]; c = lzh.text_buf[(i + k) & (LZH_STRBUF_SZ - 1)];
if (count >= outlen || count == UINT32_MAX)
return 0;
outbuf[count]=(uint8_t)c; outbuf[count]=(uint8_t)c;
#if 0 if (r >= LZH_STRBUF_SZ)
if(r>(LZH_N + LZH_F - 1) || r<0) { return 0;
printf("Overflow! (%d)\n",r);
exit(-1); }
#endif
*(lzh.text_buf+r) = (uint8_t)c; *(lzh.text_buf+r) = (uint8_t)c;
r++; r++;
r &= (LZH_N - 1); r &= (LZH_STRBUF_SZ - 1);
count++; count++;
} }
} }
...@@ -753,13 +692,6 @@ int32_t lzh_decode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf) ...@@ -753,13 +692,6 @@ int32_t lzh_decode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf)
printf("%12ld\n", count); printf("%12ld\n", count);
***/ ***/
   
#ifdef LZH_DYNAMIC_BUF
free(lzh.text_buf);
free(lzh.prnt);
free(lzh.freq);
free(lzh.son);
#endif
return(count); return(count);
} }
   
...@@ -18323,7 +18255,7 @@ int main(void) ...@@ -18323,7 +18255,7 @@ int main(void)
{ {
uint32_t lzh_len; uint32_t lzh_len;
   
lzh_len = lzh_encode(plaintext, strlen((char*)plaintext), tmp); lzh_len = lzh_encode(plaintext, strlen((char*)plaintext), tmp, sizeof(tmp));
printf("Compressed Len: %" PRId32 "\n", lzh_len); printf("Compressed Len: %" PRId32 "\n", lzh_len);
if (lzh_len != sizeof(compressed)) if (lzh_len != sizeof(compressed))
printf(" Expected Len: %zu\n", sizeof(compressed)); printf(" Expected Len: %zu\n", sizeof(compressed));
...@@ -18331,7 +18263,7 @@ int main(void) ...@@ -18331,7 +18263,7 @@ int main(void)
if (memcmp(tmp, compressed, lzh_len)) if (memcmp(tmp, compressed, lzh_len))
printf(" Bytes different\n"); printf(" Bytes different\n");
   
lzh_len = lzh_decode(compressed, sizeof(compressed), tmp); lzh_len = lzh_decode(compressed, sizeof(compressed), tmp, sizeof(tmp));
printf("Uncompressed Size: %" PRId32 "\n", lzh_len); printf("Uncompressed Size: %" PRId32 "\n", lzh_len);
if (lzh_len != strlen((char*)plaintext)) if (lzh_len != strlen((char*)plaintext))
printf(" Expected Len: %zu\n", strlen((char*)plaintext)); printf(" Expected Len: %zu\n", strlen((char*)plaintext));
...@@ -18339,7 +18271,7 @@ int main(void) ...@@ -18339,7 +18271,7 @@ int main(void)
if (memcmp(tmp, plaintext, lzh_len)) if (memcmp(tmp, plaintext, lzh_len))
printf(" Bytes different\n"); printf(" Bytes different\n");
   
lzh_len = lzh_encode(plaintext2, sizeof(plaintext2), tmp); lzh_len = lzh_encode(plaintext2, sizeof(plaintext2), tmp, sizeof(tmp));
printf("Compressed Len: %" PRId32 "\n", lzh_len); printf("Compressed Len: %" PRId32 "\n", lzh_len);
if (lzh_len != sizeof(compressed2)) if (lzh_len != sizeof(compressed2))
printf(" Expected Len: %zu\n", sizeof(compressed2)); printf(" Expected Len: %zu\n", sizeof(compressed2));
...@@ -18347,7 +18279,7 @@ int main(void) ...@@ -18347,7 +18279,7 @@ int main(void)
if (memcmp(tmp, compressed2, lzh_len)) if (memcmp(tmp, compressed2, lzh_len))
printf(" Bytes different\n"); printf(" Bytes different\n");
   
lzh_len = lzh_decode(compressed2, sizeof(compressed2), tmp); lzh_len = lzh_decode(compressed2, sizeof(compressed2), tmp, sizeof(tmp));
printf("Uncompressed Size: %" PRId32 "\n", lzh_len); printf("Uncompressed Size: %" PRId32 "\n", lzh_len);
if (lzh_len != sizeof(plaintext2)) if (lzh_len != sizeof(plaintext2))
printf(" Expected Len: %zu\n", sizeof(plaintext2)); printf(" Expected Len: %zu\n", sizeof(plaintext2));
...@@ -18355,7 +18287,7 @@ int main(void) ...@@ -18355,7 +18287,7 @@ int main(void)
if (memcmp(tmp, plaintext2, lzh_len)) if (memcmp(tmp, plaintext2, lzh_len))
printf(" Bytes different\n"); printf(" Bytes different\n");
   
lzh_len = lzh_encode(ooii_snd_cackle, sizeof(ooii_snd_cackle), tmp); lzh_len = lzh_encode(ooii_snd_cackle, sizeof(ooii_snd_cackle), tmp, sizeof(tmp));
printf("Compressed Len: %" PRId32 "\n", lzh_len); printf("Compressed Len: %" PRId32 "\n", lzh_len);
if (lzh_len != sizeof(ooii_snd_cackle_compressed)) if (lzh_len != sizeof(ooii_snd_cackle_compressed))
printf(" Expected Len: %zu\n", sizeof(ooii_snd_cackle_compressed)); printf(" Expected Len: %zu\n", sizeof(ooii_snd_cackle_compressed));
...@@ -18363,7 +18295,7 @@ int main(void) ...@@ -18363,7 +18295,7 @@ int main(void)
if (memcmp(tmp, ooii_snd_cackle_compressed, lzh_len)) if (memcmp(tmp, ooii_snd_cackle_compressed, lzh_len))
printf(" Bytes different\n"); printf(" Bytes different\n");
   
lzh_len = lzh_decode(ooii_snd_cackle_compressed, sizeof(ooii_snd_cackle_compressed), tmp); lzh_len = lzh_decode(ooii_snd_cackle_compressed, sizeof(ooii_snd_cackle_compressed), tmp, sizeof(tmp));
printf("Uncompressed Size: %" PRId32 "\n", lzh_len); printf("Uncompressed Size: %" PRId32 "\n", lzh_len);
if (lzh_len != sizeof(ooii_snd_cackle)) if (lzh_len != sizeof(ooii_snd_cackle))
printf(" Expected Len: %zu\n", sizeof(ooii_snd_cackle)); printf(" Expected Len: %zu\n", sizeof(ooii_snd_cackle));
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
LZHEXPORT int32_t lzh_encode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf); LZHEXPORT uint32_t lzh_encode(const uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, size_t outlen);
LZHEXPORT int32_t lzh_decode(uint8_t *inbuf, int32_t inlen, uint8_t *outbuf); LZHEXPORT uint32_t lzh_decode(const uint8_t *inbuf, uint32_t inlen, uint8_t *outbuf, size_t outlen);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -34,7 +34,7 @@ int smb_addmsg(smb_t* smb, smbmsg_t* msg, int storage, int dupechk_hashes ...@@ -34,7 +34,7 @@ int smb_addmsg(smb_t* smb, smbmsg_t* msg, int storage, int dupechk_hashes
,uint16_t xlat, const uchar* body, const uchar* tail) ,uint16_t xlat, const uchar* body, const uchar* tail)
{ {
uchar* lzhbuf=NULL; uchar* lzhbuf=NULL;
int lzhlen; uint32_t lzhlen;
int retval; int retval;
size_t n; size_t n;
off_t l; off_t l;
...@@ -113,7 +113,7 @@ int smb_addmsg(smb_t* smb, smbmsg_t* msg, int storage, int dupechk_hashes ...@@ -113,7 +113,7 @@ int smb_addmsg(smb_t* smb, smbmsg_t* msg, int storage, int dupechk_hashes
/* LZH compress? */ /* LZH compress? */
if(xlat==XLAT_LZH && bodylen+taillen>=SDT_BLOCK_LEN if(xlat==XLAT_LZH && bodylen+taillen>=SDT_BLOCK_LEN
&& (lzhbuf=(uchar *)malloc(bodylen*2))!=NULL) { && (lzhbuf=(uchar *)malloc(bodylen*2))!=NULL) {
lzhlen=lzh_encode((uchar*)body,bodylen-sizeof(xlat),lzhbuf); lzhlen=lzh_encode((uchar*)body,bodylen-sizeof(xlat),lzhbuf,bodylen*2);
if(lzhlen>1 if(lzhlen>1
&& smb_datblocks(lzhlen+(sizeof(xlat)*2)+taillen) && smb_datblocks(lzhlen+(sizeof(xlat)*2)+taillen)
< smb_datblocks(bodylen+taillen)) { < smb_datblocks(bodylen+taillen)) {
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include <stdlib.h> /* malloc/realloc/free */ #include <stdlib.h> /* malloc/realloc/free */
#include <string.h> /* strlen */ #include <string.h> /* strlen */
/* XPDev */
#include "xpendian.h"
/* SMB-specific */ /* SMB-specific */
#include "smblib.h" #include "smblib.h"
#include "base64.h" #include "base64.h"
...@@ -38,7 +41,9 @@ char* smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, uint mode) ...@@ -38,7 +41,9 @@ char* smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, uint mode)
uint16_t xlat; uint16_t xlat;
uint i; uint i;
int lzh; /* bool */ int lzh; /* bool */
int l=0,lzhlen,length; uint32_t lzhlen;
uint32_t lzh_decoded;
int l=0,length;
if((buf=(char*)malloc(sizeof(char)))==NULL) { if((buf=(char*)malloc(sizeof(char)))==NULL) {
safe_snprintf(smb->last_error, sizeof(smb->last_error) safe_snprintf(smb->last_error, sizeof(smb->last_error)
...@@ -146,7 +151,8 @@ char* smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, uint mode) ...@@ -146,7 +151,8 @@ char* smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, uint mode)
free(preamble); free(preamble);
return(NULL); return(NULL);
} }
lzhlen=*(int32_t*)lzhbuf; memcpy(&lzhlen, lzhbuf, sizeof(lzhlen));
lzhlen = LE_INT32(lzhlen);
if((p=(char*)realloc(buf,l+lzhlen+3L))==NULL) { if((p=(char*)realloc(buf,l+lzhlen+3L))==NULL) {
safe_snprintf(smb->last_error, sizeof(smb->last_error) safe_snprintf(smb->last_error, sizeof(smb->last_error)
,"%s realloc failure of %d bytes for text buffer" ,"%s realloc failure of %d bytes for text buffer"
...@@ -157,7 +163,16 @@ char* smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, uint mode) ...@@ -157,7 +163,16 @@ char* smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, uint mode)
return(NULL); return(NULL);
} }
buf=p; buf=p;
lzh_decode((uint8_t *)lzhbuf,length,(uint8_t *)buf+l); lzh_decoded = lzh_decode((uint8_t *)lzhbuf,length,(uint8_t *)buf+l,l+lzhlen+3);
if (lzh_decoded < lzhlen) {
safe_snprintf(smb->last_error, sizeof(smb->last_error)
,"%s lzh_decode failure got %" PRIu32 " of %" PRIu32 " bytes for text buffer"
, __FUNCTION__, lzh_decoded, lzhlen);
free(lzhbuf);
free(buf);
free(preamble);
return(NULL);
}
free(lzhbuf); free(lzhbuf);
l+=lzhlen; l+=lzhlen;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment