~ubuntu-branches/ubuntu/feisty/clamav/feisty-backports

« back to all changes in this revision

Viewing changes to libclamav/unrar/unrar20.c

  • Committer: Bazaar Package Importer
  • Author(s): SpecialK
  • Date: 2008-01-04 11:25:36 UTC
  • mfrom: (19.2.4 hardy)
  • Revision ID: james.westby@ubuntu.com-20080104112536-b23litkqiv48cm9o
Tags: 0.92~dfsg-2~feisty1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Extract RAR archives
3
 
 *
4
 
 *  Copyright (C) 2005 trog@uncon.org
5
 
 *
6
 
 *  This code is based on the work of Alexander L. Roshal
7
 
 *
8
 
 *  This program is free software; you can redistribute it and/or modify
9
 
 *  it under the terms of the GNU General Public License as published by
10
 
 *  the Free Software Foundation; either version 2 of the License, or
11
 
 *  (at your option) any later version.
12
 
 *
13
 
 *  This program is distributed in the hope that it will be useful,
14
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 *  GNU General Public License for more details.
17
 
 *
18
 
 *  You should have received a copy of the GNU General Public License
19
 
 *  along with this program; if not, write to the Free Software
20
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
 
 *  MA 02110-1301, USA.
22
 
 */
23
 
 
24
 
#include <string.h>
25
 
 
26
 
#include "others.h"
27
 
#include "unrar.h"
28
 
#include "unrar20.h"
29
 
 
30
 
#ifdef RAR_HIGH_DEBUG
31
 
#define rar_dbgmsg printf
32
 
#else
33
 
static void rar_dbgmsg(const char* fmt,...){}
34
 
#endif
35
 
 
36
 
void unpack_init_data20(int solid, unpack_data_t *unpack_data)
37
 
{
38
 
        if (!solid) {
39
 
                unpack_data->unp_channel_delta = 0;
40
 
                unpack_data->unp_cur_channel = 0;
41
 
                unpack_data->unp_channels = 1;
42
 
                memset(unpack_data->audv, 0, sizeof(unpack_data->audv));
43
 
                memset(unpack_data->unp_old_table20, 0, sizeof(unpack_data->unp_old_table20));
44
 
        }
45
 
}
46
 
 
47
 
static void copy_string20(unpack_data_t *unpack_data, unsigned int length, unsigned int distance)
48
 
{
49
 
        unsigned int dest_ptr;
50
 
        
51
 
        unpack_data->last_dist = unpack_data->old_dist[unpack_data->old_dist_ptr++ & 3] = distance;
52
 
        unpack_data->last_length = length;
53
 
        unpack_data->dest_unp_size -= length;
54
 
        
55
 
        dest_ptr = unpack_data->unp_ptr - distance;
56
 
        if (dest_ptr < MAXWINSIZE-300 && unpack_data->unp_ptr < MAXWINSIZE-300) {
57
 
                unpack_data->window[unpack_data->unp_ptr++] = unpack_data->window[dest_ptr++];
58
 
                unpack_data->window[unpack_data->unp_ptr++] = unpack_data->window[dest_ptr++];
59
 
                while (length > 2) {
60
 
                        length--;
61
 
                        unpack_data->window[unpack_data->unp_ptr++] = unpack_data->window[dest_ptr++];
62
 
                }
63
 
        } else while (length--) {
64
 
                unpack_data->window[unpack_data->unp_ptr] = unpack_data->window[dest_ptr++ & MAXWINMASK];
65
 
                unpack_data->unp_ptr = (unpack_data->unp_ptr+1) & MAXWINMASK;
66
 
        }
67
 
}
68
 
                        
69
 
static int read_tables20(int fd, unpack_data_t *unpack_data)
70
 
{
71
 
        unsigned char bit_length[BC20];
72
 
        unsigned char table[MC20 * 4];
73
 
        int table_size, n, i, number;
74
 
        unsigned int bit_field;
75
 
        
76
 
        rar_dbgmsg("in read_tables20\n");
77
 
        
78
 
        if (unpack_data->in_addr > unpack_data->read_top-25) {
79
 
                if (!unp_read_buf(fd, unpack_data)) {
80
 
                        return FALSE;
81
 
                }
82
 
        }
83
 
        bit_field = getbits(unpack_data);
84
 
        unpack_data->unp_audio_block = (bit_field & 0x8000);
85
 
        
86
 
        if (!(bit_field & 0x4000)) {
87
 
                memset(unpack_data->unp_old_table20, 0, sizeof(unpack_data->unp_old_table20));
88
 
        }
89
 
        addbits(unpack_data, 2);
90
 
        
91
 
        if (unpack_data->unp_audio_block) {
92
 
                unpack_data->unp_channels = ((bit_field>>12) & 3) + 1;
93
 
                if (unpack_data->unp_cur_channel >= unpack_data->unp_channels) {
94
 
                        unpack_data->unp_cur_channel = 0;
95
 
                }
96
 
                addbits(unpack_data, 2);
97
 
                table_size = MC20 * unpack_data->unp_channels;
98
 
        } else {
99
 
                table_size = NC20+DC20+RC20;
100
 
        }
101
 
        
102
 
        for (i=0 ; i < BC20 ; i++) {
103
 
                bit_length[i] = (unsigned char) (getbits(unpack_data) >> 12);
104
 
                addbits(unpack_data, 4);
105
 
        }
106
 
        make_decode_tables(bit_length, (struct Decode *)&unpack_data->BD, BC20);
107
 
        i=0;
108
 
        while (i < table_size) {
109
 
                if (unpack_data->in_addr > unpack_data->read_top-5) {
110
 
                        if (!unp_read_buf(fd, unpack_data)) {
111
 
                                return FALSE;
112
 
                        }
113
 
                }
114
 
                number = decode_number(unpack_data, (struct Decode *)&unpack_data->BD);
115
 
                if (number < 16) {
116
 
                        table[i] = (number + unpack_data->unp_old_table20[i]) & 0xf;
117
 
                        i++;
118
 
                } else if (number == 16) {
119
 
                        n = (getbits(unpack_data) >> 14) + 3;
120
 
                        addbits(unpack_data, 2);
121
 
                        while ((n-- > 0) && (i < table_size)) {
122
 
                                table[i] = table[i-1];
123
 
                                i++;
124
 
                        }
125
 
                } else {
126
 
                        if (number == 17) {
127
 
                                n = (getbits(unpack_data) >> 13) + 3;
128
 
                                addbits(unpack_data, 3);
129
 
                        } else {
130
 
                                n = (getbits(unpack_data) >> 9) + 11;
131
 
                                addbits(unpack_data, 7);
132
 
                        }
133
 
                        while ((n-- > 0) && (i < table_size)) {
134
 
                                table[i++] = 0;
135
 
                        }
136
 
                }
137
 
        }
138
 
        if (unpack_data->in_addr > unpack_data->read_top) {
139
 
                return TRUE;
140
 
        }
141
 
        if (unpack_data->unp_audio_block) {
142
 
                for (i=0 ; i < unpack_data->unp_channels ; i++) {
143
 
                        make_decode_tables(&table[i*MC20], (struct Decode *)&unpack_data->MD[i], MC20);
144
 
                }
145
 
        } else {
146
 
                make_decode_tables(&table[0], (struct Decode *)&unpack_data->LD, NC20);
147
 
                make_decode_tables(&table[NC20], (struct Decode *)&unpack_data->DD, DC20);
148
 
                make_decode_tables(&table[NC20+DC20], (struct Decode *)&unpack_data->RD, RC20);
149
 
        }
150
 
        memcpy(unpack_data->unp_old_table20, table, sizeof(unpack_data->unp_old_table20));
151
 
        return TRUE;
152
 
}
153
 
 
154
 
static void read_last_tables(int fd, unpack_data_t *unpack_data)
155
 
{
156
 
        if (unpack_data->read_top >= unpack_data->in_addr+5) {
157
 
                if (unpack_data->unp_audio_block) {
158
 
                        if (decode_number(unpack_data,
159
 
                                (struct Decode *)&unpack_data->MD[unpack_data->unp_cur_channel]) == 256) {
160
 
                                read_tables20(fd, unpack_data);
161
 
                        }
162
 
                } else if (decode_number(unpack_data, (struct Decode *)&unpack_data->LD) == 269) {
163
 
                        read_tables20(fd, unpack_data);
164
 
                }
165
 
        }
166
 
}
167
 
 
168
 
static unsigned char decode_audio(unpack_data_t *unpack_data, int delta)
169
 
{
170
 
        struct AudioVariables *v;
171
 
        int pch, d, i;
172
 
        unsigned int ch, mindif, num_min_dif;
173
 
        
174
 
        v = &unpack_data->audv[unpack_data->unp_cur_channel];
175
 
        v->byte_count++;
176
 
        v->D4 = v->D3;
177
 
        v->D3 = v->D2;
178
 
        v->D2 = v->last_delta - v->D1;
179
 
        v->D1 = v->last_delta;
180
 
        
181
 
        pch = 8 * v->last_char + v->K1 * v->D1 + v->K2 * v->D2 + v->K3 *
182
 
                v->D3 + v->K4 * v->D4 + v->K5 * unpack_data->unp_channel_delta;
183
 
        pch = (pch >> 3) & 0xff;
184
 
        
185
 
        ch = pch - delta;
186
 
        
187
 
        d = ((signed char) delta) << 3;
188
 
        
189
 
        v->dif[0] += abs(d);
190
 
        v->dif[1] += abs(d - v->D1);
191
 
        v->dif[2] += abs(d + v->D1);
192
 
        v->dif[3] += abs(d - v->D2);
193
 
        v->dif[4] += abs(d + v->D2);
194
 
        v->dif[5] += abs(d - v->D3);
195
 
        v->dif[6] += abs(d + v->D3);
196
 
        v->dif[7] += abs(d - v->D4);
197
 
        v->dif[8] += abs(d + v->D4);
198
 
        v->dif[9] += abs(d - unpack_data->unp_channel_delta);
199
 
        v->dif[10] += abs(d + unpack_data->unp_channel_delta);
200
 
 
201
 
        unpack_data->unp_channel_delta = v->last_delta = (signed char) (ch - v->last_char);
202
 
        v->last_char = ch;
203
 
        
204
 
        if ((v->byte_count & 0x1f) == 0) {
205
 
                mindif = v->dif[0];
206
 
                num_min_dif = 0;
207
 
                v->dif[0] = 0;
208
 
                for (i = 1 ; i < 11 ; i++) {
209
 
                        if (v->dif[i] < mindif) {
210
 
                                mindif = v->dif[i];
211
 
                                num_min_dif = i;
212
 
                        }
213
 
                        v->dif[i]=0; /* ?????? looks wrong to me */
214
 
                }
215
 
                switch(num_min_dif) {
216
 
                        case 1:
217
 
                                if (v->K1 >= -16) {
218
 
                                        v->K1--;
219
 
                                }
220
 
                                break;
221
 
                        case 2:
222
 
                                if (v->K1 < 16) {
223
 
                                        v->K1++;
224
 
                                }
225
 
                                break;
226
 
                        case 3:
227
 
                                if (v->K2 >= -16) {
228
 
                                        v->K2--;
229
 
                                }
230
 
                                break;
231
 
                        case 4:
232
 
                                if (v->K2 < 16) {
233
 
                                        v->K2++;
234
 
                                }
235
 
                                break;
236
 
                        case 5:
237
 
                                if (v->K3 >= -16) {
238
 
                                        v->K3--;
239
 
                                }
240
 
                                break;
241
 
                        case 6:
242
 
                                if (v->K3 < 16) {
243
 
                                        v->K3++;
244
 
                                }
245
 
                                break;
246
 
                        case 7:
247
 
                                if (v->K4 >= -16) {
248
 
                                        v->K4--;
249
 
                                }
250
 
                                break;
251
 
                        case 8:
252
 
                                if (v->K4 < 16) {
253
 
                                        v->K4++;
254
 
                                }
255
 
                                break;
256
 
                        case 9:
257
 
                                if (v->K5 >= -16) {
258
 
                                        v->K5--;
259
 
                                }
260
 
                                break;
261
 
                        case 10:
262
 
                                if (v->K5 < 16) {
263
 
                                        v->K5++;
264
 
                                }
265
 
                                break;
266
 
                }
267
 
        }
268
 
        return ((unsigned char) ch);
269
 
}
270
 
 
271
 
int rar_unpack20(int fd, int solid, unpack_data_t *unpack_data)
272
 
{
273
 
        unsigned char ldecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,
274
 
                        32,40,48,56,64,80,96,112,128,160,192,224};
275
 
        unsigned char lbits[]={0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5};
276
 
        int ddecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,
277
 
                        768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,
278
 
                        32768U,49152U,65536,98304,131072,196608,262144,327680,393216,
279
 
                        458752,524288,589824,655360,720896,786432,851968,917504,983040};
280
 
        unsigned char dbits[]={0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,
281
 
                        12,12,13,13,14,14,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16};
282
 
        unsigned char sddecode[]={0,4,8,16,32,64,128,192};
283
 
        unsigned char sdbits[]={2,2,3,4,5,6,6,6};
284
 
        unsigned int bits, distance;
285
 
        int retval=TRUE, audio_number, number, length, dist_number, length_number;
286
 
        
287
 
        rar_dbgmsg("in rar_unpack20\n");
288
 
 
289
 
        unpack_init_data(solid, unpack_data);
290
 
        if (!unp_read_buf(fd, unpack_data)) {
291
 
                cli_dbgmsg("unp_read_buf 1 failed\n");
292
 
                return FALSE;
293
 
        }
294
 
        if (!solid) {
295
 
                if (!read_tables20(fd, unpack_data)) {
296
 
                        cli_dbgmsg("read_tables20 failed\n");
297
 
                        return FALSE;
298
 
                }
299
 
        }
300
 
        --unpack_data->dest_unp_size;
301
 
        
302
 
        while (unpack_data->dest_unp_size >= 0) {
303
 
                rar_dbgmsg("dest_unp_size = %ld\n", unpack_data->dest_unp_size);
304
 
                unpack_data->unp_ptr &= MAXWINMASK;
305
 
                
306
 
                if (unpack_data->in_addr > unpack_data->read_top-30) {
307
 
                        if (!unp_read_buf(fd, unpack_data)) {
308
 
                                cli_dbgmsg("unp_read_buf 2 failed\n");
309
 
                                break;
310
 
                        }
311
 
                }
312
 
                if (((unpack_data->wr_ptr - unpack_data->unp_ptr) & MAXWINMASK) < 270 &&
313
 
                                (unpack_data->wr_ptr != unpack_data->unp_ptr)) {
314
 
                        unp_write_buf_old(unpack_data);
315
 
                }
316
 
                if (unpack_data->unp_audio_block) {
317
 
                        audio_number = decode_number(unpack_data,
318
 
                                (struct Decode *)&unpack_data->MD[unpack_data->unp_cur_channel]);
319
 
                        if (audio_number == 256) {
320
 
                                if (!read_tables20(fd, unpack_data)) {
321
 
                                        retval = FALSE;
322
 
                                        break;
323
 
                                }
324
 
                                continue;
325
 
                        }
326
 
                        unpack_data->window[unpack_data->unp_ptr++] =
327
 
                                        decode_audio(unpack_data, audio_number);
328
 
                        if (++unpack_data->unp_cur_channel == unpack_data->unp_channels) {
329
 
                                unpack_data->unp_cur_channel = 0;
330
 
                        }
331
 
                        --unpack_data->dest_unp_size;
332
 
                        continue;
333
 
                }
334
 
                
335
 
                number = decode_number(unpack_data, (struct Decode *)&unpack_data->LD);
336
 
                if (number < 256) {
337
 
                        unpack_data->window[unpack_data->unp_ptr++] = (unsigned char) number;
338
 
                        --unpack_data->dest_unp_size;
339
 
                        continue;
340
 
                }
341
 
                if (number > 269) {
342
 
                        length = ldecode[number-=270]+3;
343
 
                        if ((bits = lbits[number]) > 0) {
344
 
                                length += getbits(unpack_data) >> (16-bits);
345
 
                                addbits(unpack_data, bits);
346
 
                        }
347
 
                        
348
 
                        dist_number = decode_number(unpack_data, (struct Decode *)&unpack_data->DD);
349
 
                        distance = ddecode[dist_number] + 1;
350
 
                        if ((bits = dbits[dist_number]) > 0) {
351
 
                                distance += getbits(unpack_data)>>(16-bits);
352
 
                                addbits(unpack_data, bits);
353
 
                        }
354
 
                        
355
 
                        if (distance >= 0x2000) {
356
 
                                length++;
357
 
                                if (distance >= 0x40000L) {
358
 
                                        length++;
359
 
                                }
360
 
                        }
361
 
                        
362
 
                        copy_string20(unpack_data, length, distance);
363
 
                        continue;
364
 
                }
365
 
                if (number == 269) {
366
 
                        if (!read_tables20(fd, unpack_data)) {
367
 
                                retval = FALSE;
368
 
                                break;
369
 
                        }
370
 
                        continue;
371
 
                }
372
 
                if (number == 256) {
373
 
                        copy_string20(unpack_data, unpack_data->last_length, unpack_data->last_dist);
374
 
                        continue;
375
 
                }
376
 
                if (number < 261) {
377
 
                        distance = unpack_data->old_dist[(unpack_data->old_dist_ptr-(number-256)) & 3];
378
 
                        length_number = decode_number(unpack_data, (struct Decode *)&unpack_data->RD);
379
 
                        length = ldecode[length_number]+2;
380
 
                        if ((bits = lbits[length_number]) > 0) {
381
 
                                length += getbits(unpack_data) >> (16-bits);
382
 
                                addbits(unpack_data, bits);
383
 
                        }
384
 
                        if (distance >= 0x101) {
385
 
                                length++;
386
 
                                if (distance >= 0x2000) {
387
 
                                        length++;
388
 
                                        if (distance >= 0x40000) {
389
 
                                                length++;
390
 
                                        }
391
 
                                }
392
 
                        }
393
 
                        copy_string20(unpack_data, length, distance);
394
 
                        continue;
395
 
                }
396
 
                if (number < 270) {
397
 
                        distance = sddecode[number-=261]+1;
398
 
                        if ((bits=sdbits[number]) > 0) {
399
 
                                distance += getbits(unpack_data) >> (16-bits);
400
 
                                addbits(unpack_data, bits);
401
 
                        }
402
 
                        copy_string20(unpack_data, 2, distance);
403
 
                        continue;
404
 
                }
405
 
        }
406
 
        if (retval) {
407
 
                read_last_tables(fd, unpack_data);
408
 
                unp_write_buf_old(unpack_data);
409
 
        }
410
 
        return retval;
411
 
}