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

« back to all changes in this revision

Viewing changes to libclamav/unrar/unrar20.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

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
}