|
|
unsigned char pt_len[NPT]; | unsigned char pt_len[NPT]; |
unsigned char sub_bit_buf; | unsigned char sub_bit_buf; |
uint16_t pt_table[PTABLESIZE]; | uint16_t pt_table[PTABLESIZE]; |
|
int status; |
} arj_decode_t; | } arj_decode_t; |
| |
static int fill_buf(arj_decode_t *decode_data, int n) | static int fill_buf(arj_decode_t *decode_data, int n) |
|
|
if (decode_data->comp_size != 0) { | if (decode_data->comp_size != 0) { |
decode_data->comp_size--; | decode_data->comp_size--; |
if (cli_readn(decode_data->fd, &decode_data->sub_bit_buf, 1) != 1) { | if (cli_readn(decode_data->fd, &decode_data->sub_bit_buf, 1) != 1) { |
|
decode_data->status = CL_EIO; |
return CL_EIO; | return CL_EIO; |
} | } |
} else { | } else { |
|
|
for (i = 0; (int)i < nchar; i++) { | for (i = 0; (int)i < nchar; i++) { |
if (bitlen[i] >= 17) { | if (bitlen[i] >= 17) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
count[bitlen[i]]++; | count[bitlen[i]]++; |
|
|
start[i+1] = start[i] + (count[i] << (16 - i)); | start[i+1] = start[i] + (count[i] << (16 - i)); |
} | } |
if (start[17] != (unsigned short) (1 << 16)) { | if (start[17] != (unsigned short) (1 << 16)) { |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
| |
jutbits = 16 - tablebits; | jutbits = 16 - tablebits; |
if (tablebits >= 17) { | if (tablebits >= 17) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
for (i = 1; (int)i <= tablebits; i++) { | for (i = 1; (int)i <= tablebits; i++) { |
|
|
while (i != k) { | while (i != k) { |
if (i >= tablesize) { | if (i >= tablesize) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
table[i++] = 0; | table[i++] = 0; |
|
|
} | } |
if (len >= 17) { | if (len >= 17) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
k = start[len]; | k = start[len]; |
nextcode = k + weight[len]; | nextcode = k + weight[len]; |
if ((int)len <= tablebits) { | if ((int)len <= tablebits) { |
if (nextcode > (unsigned int) tablesize) { | if (nextcode > (unsigned int) tablesize) { |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
for (i = start[len]; i < nextcode; i++) { | for (i = start[len]; i < nextcode; i++) { |
|
|
if (*p == 0) { | if (*p == 0) { |
if (avail >= (2 * NC - 1)) { | if (avail >= (2 * NC - 1)) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
decode_data->right[avail] = decode_data->left[avail] = 0; | decode_data->right[avail] = decode_data->left[avail] = 0; |
|
|
} | } |
if (*p >= (2 * NC - 1)) { | if (*p >= (2 * NC - 1)) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
if (k & mask) { | if (k & mask) { |
|
|
return CL_SUCCESS; | return CL_SUCCESS; |
} | } |
| |
static void read_pt_len(arj_decode_t *decode_data, int nn, int nbit, int i_special) |
static int read_pt_len(arj_decode_t *decode_data, int nn, int nbit, int i_special) |
{ | { |
int i, n; | int i, n; |
short c; | short c; |
|
|
if (n == 0) { | if (n == 0) { |
if (nn > NPT) { | if (nn > NPT) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
return; |
decode_data->status = CL_EARJ; |
|
return CL_EARJ; |
} | } |
c = arj_getbits(decode_data, nbit); | c = arj_getbits(decode_data, nbit); |
for (i = 0; i < nn; i++) { | for (i = 0; i < nn; i++) { |
|
|
} | } |
} | } |
fill_buf(decode_data, (c < 7) ? 3 : (int)(c - 3)); | fill_buf(decode_data, (c < 7) ? 3 : (int)(c - 3)); |
|
if (decode_data->status != CL_SUCCESS) { |
|
return decode_data->status; |
|
} |
decode_data->pt_len[i++] = (unsigned char) c; | decode_data->pt_len[i++] = (unsigned char) c; |
if (i == i_special) { | if (i == i_special) { |
c = arj_getbits(decode_data, 2); | c = arj_getbits(decode_data, 2); |
|
if (decode_data->status != CL_SUCCESS) { |
|
return decode_data->status; |
|
} |
while ((--c >= 0) && (i < NPT)) { | while ((--c >= 0) && (i < NPT)) { |
decode_data->pt_len[i++] = 0; | decode_data->pt_len[i++] = 0; |
} | } |
|
|
while ((i < nn) && (i < NPT)) { | while ((i < nn) && (i < NPT)) { |
decode_data->pt_len[i++] = 0; | decode_data->pt_len[i++] = 0; |
} | } |
make_table(decode_data, nn, decode_data->pt_len, 8, decode_data->pt_table, PTABLESIZE); |
if (make_table(decode_data, nn, decode_data->pt_len, 8, decode_data->pt_table, PTABLESIZE) != CL_SUCCESS) { |
|
return CL_EARJ; |
|
} |
} | } |
|
return CL_SUCCESS; |
} | } |
| |
static int read_c_len(arj_decode_t *decode_data) | static int read_c_len(arj_decode_t *decode_data) |
|
|
unsigned short mask; | unsigned short mask; |
| |
n = arj_getbits(decode_data, CBIT); | n = arj_getbits(decode_data, CBIT); |
|
if (decode_data->status != CL_SUCCESS) { |
|
return decode_data->status; |
|
} |
if (n == 0) { | if (n == 0) { |
c = arj_getbits(decode_data, CBIT); | c = arj_getbits(decode_data, CBIT); |
|
if (decode_data->status != CL_SUCCESS) { |
|
return decode_data->status; |
|
} |
for (i = 0; i < NC; i++) { | for (i = 0; i < NC; i++) { |
decode_data->c_len[i] = 0; | decode_data->c_len[i] = 0; |
} | } |
|
|
do { | do { |
if (c >= (2 * NC - 1)) { | if (c >= (2 * NC - 1)) { |
cli_warnmsg("ERROR: bounds exceeded\n"); | cli_warnmsg("ERROR: bounds exceeded\n"); |
|
decode_data->status = CL_EFORMAT; |
return CL_EFORMAT; | return CL_EFORMAT; |
} | } |
if (decode_data->bit_buf & mask) { | if (decode_data->bit_buf & mask) { |
|
|
} | } |
if (c >= 19) { | if (c >= 19) { |
cli_dbgmsg("UNARJ: bounds exceeded\n"); | cli_dbgmsg("UNARJ: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return CL_EARJ; | return CL_EARJ; |
} | } |
fill_buf(decode_data, (int)(decode_data->pt_len[c])); | fill_buf(decode_data, (int)(decode_data->pt_len[c])); |
|
if (decode_data->status != CL_SUCCESS) { |
|
return decode_data->status; |
|
} |
if (c <= 2) { | if (c <= 2) { |
if (c == 0) { | if (c == 0) { |
c = 1; | c = 1; |
|
|
} else { | } else { |
c = arj_getbits(decode_data, CBIT) + 20; | c = arj_getbits(decode_data, CBIT) + 20; |
} | } |
|
if (decode_data->status != CL_SUCCESS) { |
|
return decode_data->status; |
|
} |
while (--c >= 0) { | while (--c >= 0) { |
if (i >= NC) { | if (i >= NC) { |
cli_warnmsg("ERROR: bounds exceeded\n"); | cli_warnmsg("ERROR: bounds exceeded\n"); |
|
decode_data->status = CL_EFORMAT; |
return CL_EFORMAT; | return CL_EFORMAT; |
} | } |
decode_data->c_len[i++] = 0; | decode_data->c_len[i++] = 0; |
|
|
} else { | } else { |
if (i >= NC) { | if (i >= NC) { |
cli_warnmsg("ERROR: bounds exceeded\n"); | cli_warnmsg("ERROR: bounds exceeded\n"); |
|
decode_data->status = CL_EFORMAT; |
return CL_EFORMAT; | return CL_EFORMAT; |
} | } |
decode_data->c_len[i++] = (unsigned char) (c - 2); | decode_data->c_len[i++] = (unsigned char) (c - 2); |
|
|
while (i < NC) { | while (i < NC) { |
decode_data->c_len[i++] = 0; | decode_data->c_len[i++] = 0; |
} | } |
make_table(decode_data, NC, decode_data->c_len, 12, decode_data->c_table, CTABLESIZE); |
if (make_table(decode_data, NC, decode_data->c_len, 12, decode_data->c_table, CTABLESIZE) != CL_SUCCESS) { |
|
return CL_EARJ; |
|
} |
} | } |
return CL_SUCCESS; | return CL_SUCCESS; |
} | } |
|
|
do { | do { |
if (j >= (2 * NC - 1)) { | if (j >= (2 * NC - 1)) { |
cli_warnmsg("ERROR: bounds exceeded\n"); | cli_warnmsg("ERROR: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return 0; | return 0; |
} | } |
if (decode_data->bit_buf & mask) { | if (decode_data->bit_buf & mask) { |
|
|
do { | do { |
if (j >= (2 * NC - 1)) { | if (j >= (2 * NC - 1)) { |
cli_warnmsg("ERROR: bounds exceeded\n"); | cli_warnmsg("ERROR: bounds exceeded\n"); |
|
decode_data->status = CL_EARJ; |
return 0; | return 0; |
} | } |
if (decode_data->bit_buf & mask) { | if (decode_data->bit_buf & mask) { |
|
|
decode_data.comp_size = metadata->comp_size; | decode_data.comp_size = metadata->comp_size; |
ret = decode_start(&decode_data); | ret = decode_start(&decode_data); |
if (ret != CL_SUCCESS) { | if (ret != CL_SUCCESS) { |
|
free(decode_data.text); |
return ret; | return ret; |
} | } |
|
decode_data.status = CL_SUCCESS; |
| |
while (count < metadata->orig_size) { | while (count < metadata->orig_size) { |
if ((chr = decode_c(&decode_data)) <= UCHAR_MAX) { | if ((chr = decode_c(&decode_data)) <= UCHAR_MAX) { |
|
|
count++; | count++; |
if (++out_ptr >= DDICSIZ) { | if (++out_ptr >= DDICSIZ) { |
out_ptr = 0; | out_ptr = 0; |
write_text(metadata->ofd, decode_data.text, DDICSIZ); |
if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return CL_EIO; |
|
} |
} | } |
} else { | } else { |
j = chr - (UCHAR_MAX + 1 - THRESHOLD); | j = chr - (UCHAR_MAX + 1 - THRESHOLD); |
|
|
decode_data.text[out_ptr] = decode_data.text[i]; | decode_data.text[out_ptr] = decode_data.text[i]; |
if (++out_ptr >= DDICSIZ) { | if (++out_ptr >= DDICSIZ) { |
out_ptr = 0; | out_ptr = 0; |
write_text(metadata->ofd, decode_data.text, DDICSIZ); |
if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return CL_EIO; |
|
} |
} | } |
if (++i >= DDICSIZ) { | if (++i >= DDICSIZ) { |
i = 0; | i = 0; |
|
|
} | } |
} | } |
} | } |
|
if (decode_data.status != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return decode_data.status; |
|
} |
} | } |
if (out_ptr != 0) { | if (out_ptr != 0) { |
write_text(metadata->ofd, decode_data.text, out_ptr); | write_text(metadata->ofd, decode_data.text, out_ptr); |
|
|
return ret; | return ret; |
} | } |
decode_data.getlen = decode_data.getbuf = 0; | decode_data.getlen = decode_data.getbuf = 0; |
|
decode_data.status = CL_SUCCESS; |
|
|
while (count < metadata->orig_size) { | while (count < metadata->orig_size) { |
chr = decode_len(&decode_data); | chr = decode_len(&decode_data); |
|
if (decode_data.status != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return decode_data.status; |
|
} |
if (chr == 0) { | if (chr == 0) { |
ARJ_GETBITS(dd, chr, CHAR_BIT); | ARJ_GETBITS(dd, chr, CHAR_BIT); |
|
if (decode_data.status != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return decode_data.status; |
|
} |
decode_data.text[out_ptr] = (unsigned char) chr; | decode_data.text[out_ptr] = (unsigned char) chr; |
count++; | count++; |
if (++out_ptr >= DDICSIZ) { | if (++out_ptr >= DDICSIZ) { |
out_ptr = 0; | out_ptr = 0; |
write_text(metadata->ofd, decode_data.text, DDICSIZ); |
if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return CL_EIO; |
|
} |
} | } |
} else { | } else { |
j = chr - 1 + THRESHOLD; | j = chr - 1 + THRESHOLD; |
count += j; | count += j; |
pos = decode_ptr(&decode_data); | pos = decode_ptr(&decode_data); |
|
if (decode_data.status != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return decode_data.status; |
|
} |
if ((i = out_ptr - pos - 1) < 0) { | if ((i = out_ptr - pos - 1) < 0) { |
i += DDICSIZ; | i += DDICSIZ; |
} | } |
|
|
decode_data.text[out_ptr] = decode_data.text[i]; | decode_data.text[out_ptr] = decode_data.text[i]; |
if (++out_ptr >= DDICSIZ) { | if (++out_ptr >= DDICSIZ) { |
out_ptr = 0; | out_ptr = 0; |
write_text(metadata->ofd, decode_data.text, DDICSIZ); |
if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) { |
|
free(decode_data.text); |
|
return CL_EIO; |
|
} |
} | } |
if (++i >= DDICSIZ) { | if (++i >= DDICSIZ) { |
i = 0; | i = 0; |
|
|
case 1: | case 1: |
case 2: | case 2: |
case 3: | case 3: |
decode(fd, metadata); |
ret = decode(fd, metadata); |
break; | break; |
case 4: | case 4: |
decode_f(fd, metadata); |
ret = decode_f(fd, metadata); |
break; | break; |
default: | default: |
ret = CL_EFORMAT; | ret = CL_EFORMAT; |