Coverage Report

Created: 2023-12-08 06:48

/src/clamav/libclamav/unarj.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Extract component parts of ARJ archives.
3
 *
4
 *  Copyright (C) 2013-2023 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
5
 *  Copyright (C) 2007-2013 Sourcefire, Inc.
6
 *
7
 *  Authors: Trog
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License version 2 as
11
 *  published by the Free Software Foundation.
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
#if HAVE_CONFIG_H
25
#include "clamav-config.h"
26
#endif
27
28
#include <stdio.h>
29
#include <string.h>
30
#include <stdlib.h>
31
#ifdef HAVE_UNISTD_H
32
#include <unistd.h>
33
#endif
34
#include <sys/types.h>
35
#include <sys/stat.h>
36
#include <fcntl.h>
37
#include <ctype.h>
38
39
#include "clamav.h"
40
#include "str.h"
41
#include "others.h"
42
#include "unarj.h"
43
#include "textnorm.h"
44
45
3.82M
#define FIRST_HDR_SIZE 30
46
3.82M
#define COMMENT_MAX 2048
47
3.82M
#define FNAME_MAX 512
48
3.82M
#define HEADERSIZE_MAX (FIRST_HDR_SIZE + 10 + FNAME_MAX + COMMENT_MAX)
49
15.0M
#define MAXDICBIT 16
50
4.30G
#define DDICSIZ 26624
51
1.01G
#define THRESHOLD 3
52
#ifndef UCHAR_MAX
53
#define UCHAR_MAX (255)
54
#endif
55
#ifndef CHAR_BIT
56
#define CHAR_BIT (8)
57
#endif
58
991M
#define MAXMATCH 256
59
#ifndef FALSE
60
#define FALSE (0)
61
#define TRUE (1)
62
#endif
63
64
1.18G
#define CODE_BIT 16
65
2.05M
#define NT (CODE_BIT + 3)
66
57.5k
#define PBIT 5
67
57.5k
#define TBIT 5
68
977M
#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
69
15.0M
#define NP (MAXDICBIT + 1)
70
109k
#define CBIT 9
71
88.5M
#define CTABLESIZE 4096
72
42.2k
#define PTABLESIZE 256
73
50.3M
#define STRTP 9
74
55.6M
#define STOPP 13
75
76
760M
#define STRTL 0
77
443M
#define STOPL 7
78
79
#if NT > NP
80
890k
#define NPT NT
81
#else
82
#define NPT NP
83
#endif
84
85
1.18M
#define GARBLE_FLAG 0x01
86
87
#ifndef HAVE_ATTRIB_PACKED
88
#define __attribute__(x)
89
#endif
90
91
#ifdef HAVE_PRAGMA_PACK
92
#pragma pack(1)
93
#endif
94
95
#ifdef HAVE_PRAGMA_PACK_HPPA
96
#pragma pack 1
97
#endif
98
99
typedef struct arj_main_hdr_tag {
100
    uint8_t first_hdr_size; /* must be 30 bytes */
101
    uint8_t version;
102
    uint8_t min_version;
103
    uint8_t host_os;
104
    uint8_t flags;
105
    uint8_t security_version;
106
    uint8_t file_type;
107
    uint8_t pad;
108
    uint32_t time_created __attribute__((packed));
109
    uint32_t time_modified __attribute__((packed));
110
    uint32_t archive_size __attribute__((packed));
111
    uint32_t sec_env_file_position __attribute__((packed));
112
    uint16_t entryname_pos __attribute__((packed));
113
    uint16_t sec_trail_size __attribute__((packed));
114
    uint16_t host_data __attribute__((packed));
115
} arj_main_hdr_t;
116
117
typedef struct arj_file_hdr_tag {
118
    uint8_t first_hdr_size; /* must be 30 bytes */
119
    uint8_t version;
120
    uint8_t min_version;
121
    uint8_t host_os;
122
    uint8_t flags;
123
    uint8_t method;
124
    uint8_t file_type;
125
    uint8_t password_mod;
126
    uint32_t time_modified __attribute__((packed));
127
    uint32_t comp_size __attribute__((packed));
128
    uint32_t orig_size __attribute__((packed));
129
    uint32_t orig_crc __attribute__((packed));
130
    uint16_t entryname_pos __attribute__((packed));
131
    uint16_t file_mode __attribute__((packed));
132
    uint16_t host_data __attribute__((packed));
133
} arj_file_hdr_t;
134
135
#ifdef HAVE_PRAGMA_PACK
136
#pragma pack()
137
#endif
138
139
#ifdef HAVE_PRAGMA_PACK_HPPA
140
#pragma pack
141
#endif
142
143
typedef struct arj_decode_tag {
144
    unsigned char *text;
145
    fmap_t *map;
146
    size_t offset;
147
    const uint8_t *buf;
148
    const void *bufend;
149
    uint16_t blocksize;
150
    uint16_t bit_buf;
151
    int bit_count;
152
    uint32_t comp_size;
153
    int16_t getlen, getbuf;
154
    uint16_t left[2 * NC - 1];
155
    uint16_t right[2 * NC - 1];
156
    unsigned char c_len[NC];
157
    uint16_t c_table[CTABLESIZE];
158
    unsigned char pt_len[NPT];
159
    unsigned char sub_bit_buf;
160
    uint16_t pt_table[PTABLESIZE];
161
    int status;
162
} arj_decode_t;
163
164
static cl_error_t fill_buf(arj_decode_t *decode_data, int n)
165
1.36G
{
166
1.36G
    if (decode_data->status == CL_EFORMAT)
167
8.91k
        return CL_EFORMAT;
168
1.36G
    if (((uint64_t)decode_data->bit_buf) * (n > 0 ? 2 << (n - 1) : 0) > UINT32_MAX)
169
11.5k
        return CL_EFORMAT;
170
1.36G
    decode_data->bit_buf = (((uint64_t)decode_data->bit_buf) << n) & 0xFFFF;
171
1.82G
    while (n > decode_data->bit_count) {
172
460M
        decode_data->bit_buf |= decode_data->sub_bit_buf << (n -= decode_data->bit_count);
173
460M
        if (decode_data->comp_size != 0) {
174
139M
            decode_data->comp_size--;
175
139M
            if (decode_data->buf == decode_data->bufend) {
176
101k
                size_t len;
177
101k
                decode_data->buf = fmap_need_off_once_len(decode_data->map, decode_data->offset, 8192, &len);
178
101k
                if (!decode_data->buf || !len) {
179
                    /* the file is most likely corrupted, so
180
                     * we return CL_EFORMAT instead of CL_EREAD
181
                     */
182
26.1k
                    decode_data->status = CL_EFORMAT;
183
26.1k
                    return CL_EFORMAT;
184
26.1k
                }
185
75.4k
                decode_data->bufend = decode_data->buf + len;
186
75.4k
            }
187
139M
            decode_data->sub_bit_buf = *decode_data->buf++;
188
139M
            decode_data->offset++;
189
321M
        } else {
190
321M
            decode_data->sub_bit_buf = 0;
191
321M
        }
192
460M
        decode_data->bit_count = CHAR_BIT;
193
460M
    }
194
1.36G
    decode_data->bit_buf |= decode_data->sub_bit_buf >> (decode_data->bit_count -= n);
195
1.36G
    return CL_SUCCESS;
196
1.36G
}
197
198
static cl_error_t init_getbits(arj_decode_t *decode_data)
199
66.5k
{
200
66.5k
    decode_data->bit_buf     = 0;
201
66.5k
    decode_data->sub_bit_buf = 0;
202
66.5k
    decode_data->bit_count   = 0;
203
66.5k
    return fill_buf(decode_data, 2 * CHAR_BIT);
204
66.5k
}
205
206
static unsigned short arj_getbits(arj_decode_t *decode_data, int n)
207
3.78M
{
208
3.78M
    unsigned short x;
209
210
3.78M
    x = decode_data->bit_buf >> (2 * CHAR_BIT - n);
211
3.78M
    fill_buf(decode_data, n);
212
3.78M
    return x;
213
3.78M
}
214
215
static cl_error_t decode_start(arj_decode_t *decode_data)
216
37.8k
{
217
37.8k
    decode_data->blocksize = 0;
218
37.8k
    return init_getbits(decode_data);
219
37.8k
}
220
221
static cl_error_t write_text(int ofd, unsigned char *data, size_t length)
222
98.9k
{
223
98.9k
    size_t count;
224
225
98.9k
    count = cli_writen(ofd, data, length);
226
98.9k
    if (count != length) {
227
0
        return CL_EWRITE;
228
0
    }
229
98.9k
    return CL_SUCCESS;
230
98.9k
}
231
232
static cl_error_t make_table(arj_decode_t *decode_data, int nchar, unsigned char *bitlen, int tablebits,
233
                             unsigned short *table, int tablesize)
234
58.5k
{
235
58.5k
    unsigned short count[17], weight[17], start[18], *p;
236
58.5k
    unsigned int i, k, len, ch, jutbits, avail, nextcode, mask;
237
238
995k
    for (i = 1; i <= 16; i++) {
239
937k
        count[i] = 0;
240
937k
    }
241
9.14M
    for (i = 0; (int)i < nchar; i++) {
242
9.09M
        if (bitlen[i] >= 17) {
243
1.18k
            cli_dbgmsg("UNARJ: bounds exceeded\n");
244
1.18k
            decode_data->status = CL_EUNPACK;
245
1.18k
            return CL_EUNPACK;
246
1.18k
        }
247
9.09M
        count[bitlen[i]]++;
248
9.09M
    }
249
250
57.3k
    start[1] = 0;
251
975k
    for (i = 1; i <= 16; i++) {
252
918k
        start[i + 1] = start[i] + (count[i] << (16 - i));
253
918k
    }
254
57.3k
    if (start[17] != (unsigned short)(1 << 16)) {
255
23.0k
        decode_data->status = CL_EUNPACK;
256
23.0k
        return CL_EUNPACK;
257
23.0k
    }
258
259
34.3k
    jutbits = 16 - tablebits;
260
34.3k
    if (tablebits >= 17) {
261
0
        cli_dbgmsg("UNARJ: bounds exceeded\n");
262
0
        decode_data->status = CL_EUNPACK;
263
0
        return CL_EUNPACK;
264
0
    }
265
367k
    for (i = 1; (int)i <= tablebits; i++) {
266
333k
        start[i] >>= jutbits;
267
333k
        weight[i] = 1 << (tablebits - i);
268
333k
    }
269
250k
    while (i <= 16) {
270
216k
        weight[i] = 1 << (16 - i);
271
216k
        i++;
272
216k
    }
273
274
34.3k
    i = start[tablebits + 1] >> jutbits;
275
34.3k
    if (i != (unsigned short)(1 << 16)) {
276
0
        k = 1 << tablebits;
277
0
        while (i != k) {
278
0
            if (i >= (unsigned int)tablesize) {
279
0
                cli_dbgmsg("UNARJ: bounds exceeded\n");
280
0
                decode_data->status = CL_EUNPACK;
281
0
                return CL_EUNPACK;
282
0
            }
283
0
            table[i++] = 0;
284
0
        }
285
0
    }
286
287
34.3k
    avail = nchar;
288
34.3k
    mask  = 1 << (15 - tablebits);
289
7.75M
    for (ch = 0; (int)ch < nchar; ch++) {
290
7.72M
        if ((len = bitlen[ch]) == 0) {
291
7.37M
            continue;
292
7.37M
        }
293
345k
        if (len >= 17) {
294
0
            cli_dbgmsg("UNARJ: bounds exceeded\n");
295
0
            decode_data->status = CL_EUNPACK;
296
0
            return CL_EUNPACK;
297
0
        }
298
345k
        k        = start[len];
299
345k
        nextcode = k + weight[len];
300
345k
        if ((int)len <= tablebits) {
301
345k
            if (nextcode > (unsigned int)tablesize) {
302
2.15k
                decode_data->status = CL_EUNPACK;
303
2.15k
                return CL_EUNPACK;
304
2.15k
            }
305
29.3M
            for (i = start[len]; i < nextcode; i++) {
306
28.9M
                table[i] = ch;
307
28.9M
            }
308
343k
        } else {
309
0
            p = &table[k >> jutbits];
310
0
            i = len - tablebits;
311
0
            while (i != 0) {
312
0
                if (*p == 0) {
313
0
                    if (avail >= (2 * NC - 1)) {
314
0
                        cli_dbgmsg("UNARJ: bounds exceeded\n");
315
0
                        decode_data->status = CL_EUNPACK;
316
0
                        return CL_EUNPACK;
317
0
                    }
318
0
                    decode_data->right[avail] = decode_data->left[avail] = 0;
319
0
                    *p                                                   = avail++;
320
0
                }
321
0
                if (*p >= (2 * NC - 1)) {
322
0
                    cli_dbgmsg("UNARJ: bounds exceeded\n");
323
0
                    decode_data->status = CL_EUNPACK;
324
0
                    return CL_EUNPACK;
325
0
                }
326
0
                if (k & mask) {
327
0
                    p = &decode_data->right[*p];
328
0
                } else {
329
0
                    p = &decode_data->left[*p];
330
0
                }
331
0
                k <<= 1;
332
0
                i--;
333
0
            }
334
0
            *p = ch;
335
0
        }
336
343k
        start[len] = nextcode;
337
343k
    }
338
32.1k
    return CL_SUCCESS;
339
34.3k
}
340
341
static cl_error_t read_pt_len(arj_decode_t *decode_data, int nn, int nbit, int i_special)
342
115k
{
343
115k
    int i, n;
344
115k
    short c;
345
115k
    unsigned short mask;
346
347
115k
    n = arj_getbits(decode_data, nbit);
348
115k
    if (n == 0) {
349
61.3k
        if (nn > NPT) {
350
0
            cli_dbgmsg("UNARJ: bounds exceeded\n");
351
0
            decode_data->status = CL_EUNPACK;
352
0
            return CL_EUNPACK;
353
0
        }
354
61.3k
        c = arj_getbits(decode_data, nbit);
355
1.22M
        for (i = 0; i < nn; i++) {
356
1.16M
            decode_data->pt_len[i] = 0;
357
1.16M
        }
358
15.7M
        for (i = 0; i < 256; i++) {
359
15.7M
            decode_data->pt_table[i] = c;
360
15.7M
        }
361
61.3k
    } else {
362
53.7k
        i = 0;
363
545k
        while ((i < n) && (i < NPT)) {
364
503k
            c = decode_data->bit_buf >> 13;
365
503k
            if (c == 7) {
366
29.8k
                mask = 1 << 12;
367
204k
                while (mask & decode_data->bit_buf) {
368
175k
                    mask >>= 1;
369
175k
                    c++;
370
175k
                }
371
29.8k
            }
372
503k
            fill_buf(decode_data, (c < 7) ? 3 : (int)(c - 3));
373
503k
            if (decode_data->status != CL_SUCCESS) {
374
11.4k
                return decode_data->status;
375
11.4k
            }
376
491k
            decode_data->pt_len[i++] = (unsigned char)c;
377
491k
            if (i == i_special) {
378
22.8k
                c = arj_getbits(decode_data, 2);
379
22.8k
                if (decode_data->status != CL_SUCCESS) {
380
0
                    return decode_data->status;
381
0
                }
382
53.6k
                while ((--c >= 0) && (i < NPT)) {
383
30.7k
                    decode_data->pt_len[i++] = 0;
384
30.7k
                }
385
22.8k
            }
386
491k
        }
387
323k
        while ((i < nn) && (i < NPT)) {
388
281k
            decode_data->pt_len[i++] = 0;
389
281k
        }
390
42.2k
        if (make_table(decode_data, nn, decode_data->pt_len, 8, decode_data->pt_table, PTABLESIZE) != CL_SUCCESS) {
391
24.5k
            return CL_EUNPACK;
392
24.5k
        }
393
42.2k
    }
394
79.0k
    return CL_SUCCESS;
395
115k
}
396
397
static cl_error_t read_c_len(arj_decode_t *decode_data)
398
57.5k
{
399
57.5k
    short i, c, n;
400
57.5k
    unsigned short mask;
401
402
57.5k
    n = arj_getbits(decode_data, CBIT);
403
57.5k
    if (decode_data->status != CL_SUCCESS) {
404
17.9k
        return decode_data->status;
405
17.9k
    }
406
39.5k
    if (n == 0) {
407
21.6k
        c = arj_getbits(decode_data, CBIT);
408
21.6k
        if (decode_data->status != CL_SUCCESS) {
409
31
            return decode_data->status;
410
31
        }
411
11.0M
        for (i = 0; i < NC; i++) {
412
11.0M
            decode_data->c_len[i] = 0;
413
11.0M
        }
414
88.5M
        for (i = 0; i < CTABLESIZE; i++) {
415
88.4M
            decode_data->c_table[i] = c;
416
88.4M
        }
417
21.6k
    } else {
418
17.9k
        i = 0;
419
1.01M
        while (i < n) {
420
993k
            c = decode_data->pt_table[decode_data->bit_buf >> 8];
421
993k
            if (c >= NT) {
422
56.4k
                mask = 1 << 7;
423
56.4k
                do {
424
56.4k
                    if (c >= (2 * NC - 1)) {
425
0
                        cli_dbgmsg("ERROR: bounds exceeded\n");
426
0
                        decode_data->status = CL_EFORMAT;
427
0
                        return CL_EFORMAT;
428
0
                    }
429
56.4k
                    if (decode_data->bit_buf & mask) {
430
7.72k
                        c = decode_data->right[c];
431
48.7k
                    } else {
432
48.7k
                        c = decode_data->left[c];
433
48.7k
                    }
434
56.4k
                    mask >>= 1;
435
56.4k
                } while (c >= NT);
436
56.4k
            }
437
993k
            if (c >= 19) {
438
0
                cli_dbgmsg("UNARJ: bounds exceeded\n");
439
0
                decode_data->status = CL_EUNPACK;
440
0
                return CL_EUNPACK;
441
0
            }
442
993k
            fill_buf(decode_data, (int)(decode_data->pt_len[c]));
443
993k
            if (decode_data->status != CL_SUCCESS) {
444
330
                return decode_data->status;
445
330
            }
446
993k
            if (c <= 2) {
447
417k
                if (c == 0) {
448
295k
                    c = 1;
449
295k
                } else if (c == 1) {
450
91.4k
                    c = arj_getbits(decode_data, 4) + 3;
451
91.4k
                } else {
452
30.6k
                    c = arj_getbits(decode_data, CBIT) + 20;
453
30.6k
                }
454
417k
                if (decode_data->status != CL_SUCCESS) {
455
348
                    return decode_data->status;
456
348
                }
457
2.80M
                while (--c >= 0) {
458
2.39M
                    if (i >= NC) {
459
794
                        cli_dbgmsg("ERROR: bounds exceeded\n");
460
794
                        decode_data->status = CL_EFORMAT;
461
794
                        return CL_EFORMAT;
462
794
                    }
463
2.38M
                    decode_data->c_len[i++] = 0;
464
2.38M
                }
465
575k
            } else {
466
575k
                if (i >= NC) {
467
178
                    cli_dbgmsg("ERROR: bounds exceeded\n");
468
178
                    decode_data->status = CL_EFORMAT;
469
178
                    return CL_EFORMAT;
470
178
                }
471
575k
                decode_data->c_len[i++] = (unsigned char)(c - 2);
472
575k
            }
473
993k
        }
474
6.06M
        while (i < NC) {
475
6.04M
            decode_data->c_len[i++] = 0;
476
6.04M
        }
477
16.2k
        if (make_table(decode_data, NC, decode_data->c_len, 12, decode_data->c_table, CTABLESIZE) != CL_SUCCESS) {
478
1.84k
            return CL_EUNPACK;
479
1.84k
        }
480
16.2k
    }
481
36.0k
    return CL_SUCCESS;
482
39.5k
}
483
484
static uint16_t decode_c(arj_decode_t *decode_data)
485
955M
{
486
955M
    uint16_t j, mask;
487
488
955M
    if (decode_data->blocksize == 0) {
489
57.5k
        decode_data->blocksize = arj_getbits(decode_data, 16);
490
57.5k
        read_pt_len(decode_data, NT, TBIT, 3);
491
57.5k
        read_c_len(decode_data);
492
57.5k
        read_pt_len(decode_data, NT, PBIT, -1);
493
57.5k
    }
494
955M
    decode_data->blocksize--;
495
955M
    j = decode_data->c_table[decode_data->bit_buf >> 4];
496
955M
    if (j >= NC) {
497
420k
        mask = 1 << 3;
498
420k
        do {
499
420k
            if (j >= (2 * NC - 1)) {
500
0
                cli_dbgmsg("ERROR: bounds exceeded\n");
501
0
                decode_data->status = CL_EUNPACK;
502
0
                return 0;
503
0
            }
504
420k
            if (decode_data->bit_buf & mask) {
505
26.6k
                j = decode_data->right[j];
506
393k
            } else {
507
393k
                j = decode_data->left[j];
508
393k
            }
509
420k
            mask >>= 1;
510
420k
        } while (j >= NC);
511
420k
    }
512
955M
    fill_buf(decode_data, (int)(decode_data->c_len[j]));
513
955M
    return j;
514
955M
}
515
516
static uint16_t decode_p(arj_decode_t *decode_data)
517
14.0M
{
518
14.0M
    unsigned short j, mask;
519
520
14.0M
    j = decode_data->pt_table[decode_data->bit_buf >> 8];
521
14.0M
    if (j >= NP) {
522
1.03M
        mask = 1 << 7;
523
1.03M
        do {
524
1.03M
            if (j >= (2 * NC - 1)) {
525
0
                cli_dbgmsg("ERROR: bounds exceeded\n");
526
0
                decode_data->status = CL_EUNPACK;
527
0
                return 0;
528
0
            }
529
1.03M
            if (decode_data->bit_buf & mask) {
530
1.02M
                j = decode_data->right[j];
531
1.02M
            } else {
532
8.37k
                j = decode_data->left[j];
533
8.37k
            }
534
1.03M
            mask >>= 1;
535
1.03M
        } while (j >= NP);
536
1.03M
    }
537
14.0M
    fill_buf(decode_data, (int)(decode_data->pt_len[j]));
538
14.0M
    if (j != 0) {
539
3.33M
        j--;
540
3.33M
        j = (1 << j) + arj_getbits(decode_data, (int)j);
541
3.33M
    }
542
14.0M
    return j;
543
14.0M
}
544
545
static cl_error_t decode(arj_metadata_t *metadata)
546
37.8k
{
547
37.8k
    cl_error_t ret;
548
549
37.8k
    arj_decode_t decode_data;
550
37.8k
    uint32_t count = 0, out_ptr = 0;
551
37.8k
    int16_t chr, i, j;
552
553
37.8k
    memset(&decode_data, 0, sizeof(decode_data));
554
37.8k
    decode_data.text = (unsigned char *)cli_calloc(DDICSIZ, 1);
555
37.8k
    if (!decode_data.text) {
556
0
        return CL_EMEM;
557
0
    }
558
37.8k
    decode_data.map       = metadata->map;
559
37.8k
    decode_data.offset    = metadata->offset;
560
37.8k
    decode_data.comp_size = metadata->comp_size;
561
37.8k
    ret                   = decode_start(&decode_data);
562
37.8k
    if (ret != CL_SUCCESS) {
563
272
        free(decode_data.text);
564
272
        metadata->offset = decode_data.offset;
565
272
        return ret;
566
272
    }
567
37.5k
    decode_data.status = CL_SUCCESS;
568
569
955M
    while (count < metadata->orig_size) {
570
955M
        if ((chr = decode_c(&decode_data)) <= UCHAR_MAX) {
571
941M
            decode_data.text[out_ptr] = (unsigned char)chr;
572
941M
            count++;
573
941M
            if (++out_ptr >= DDICSIZ) {
574
33.4k
                out_ptr = 0;
575
33.4k
                if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
576
0
                    free(decode_data.text);
577
0
                    metadata->offset = decode_data.offset;
578
0
                    return CL_EWRITE;
579
0
                }
580
33.4k
            }
581
941M
        } else {
582
14.0M
            j = chr - (UCHAR_MAX + 1 - THRESHOLD);
583
14.0M
            count += j;
584
14.0M
            i = decode_p(&decode_data);
585
14.0M
            if ((i = out_ptr - i - 1) < 0) {
586
201k
                i += DDICSIZ;
587
201k
            }
588
14.0M
            if ((i >= DDICSIZ) || (i < 0)) {
589
2.71k
                cli_dbgmsg("UNARJ: bounds exceeded - probably a corrupted file.\n");
590
2.71k
                break;
591
2.71k
            }
592
14.0M
            if (out_ptr > (uint32_t)i && out_ptr < DDICSIZ - MAXMATCH - 1) {
593
603M
                while ((--j >= 0) && (i < DDICSIZ) && (out_ptr < DDICSIZ)) {
594
590M
                    decode_data.text[out_ptr++] = decode_data.text[i++];
595
590M
                }
596
13.6M
            } else {
597
21.1M
                while (--j >= 0) {
598
20.8M
                    decode_data.text[out_ptr] = decode_data.text[i];
599
20.8M
                    if (++out_ptr >= DDICSIZ) {
600
21.1k
                        out_ptr = 0;
601
21.1k
                        if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
602
0
                            free(decode_data.text);
603
0
                            metadata->offset = decode_data.offset;
604
0
                            return CL_EWRITE;
605
0
                        }
606
21.1k
                    }
607
20.8M
                    if (++i >= DDICSIZ) {
608
27.0k
                        i = 0;
609
27.0k
                    }
610
20.8M
                }
611
327k
            }
612
14.0M
        }
613
955M
        if (decode_data.status != CL_SUCCESS) {
614
29.7k
            free(decode_data.text);
615
29.7k
            metadata->offset = decode_data.offset;
616
29.7k
            return decode_data.status;
617
29.7k
        }
618
955M
    }
619
7.78k
    if (out_ptr != 0) {
620
5.21k
        write_text(metadata->ofd, decode_data.text, out_ptr);
621
5.21k
    }
622
623
7.78k
    free(decode_data.text);
624
7.78k
    metadata->offset = decode_data.offset;
625
7.78k
    return CL_SUCCESS;
626
37.5k
}
627
628
#define ARJ_BFIL(dd)                             \
629
386M
    {                                            \
630
386M
        dd->getbuf |= dd->bit_buf >> dd->getlen; \
631
386M
        fill_buf(dd, CODE_BIT - dd->getlen);     \
632
386M
        dd->getlen = CODE_BIT;                   \
633
386M
    }
634
#define ARJ_GETBIT(dd, c)                 \
635
491M
    {                                     \
636
491M
        if (dd->getlen <= 0) ARJ_BFIL(dd) \
637
491M
        c = (dd->getbuf & 0x8000) != 0;   \
638
491M
        dd->getbuf *= 2;                  \
639
491M
        dd->getlen--;                     \
640
491M
    }
641
#define ARJ_BPUL(dd, l)           \
642
405M
    do {                          \
643
405M
        int i;                    \
644
405M
        int j = l;                \
645
3.56G
        for (i = 0; i < j; i++) { \
646
3.16G
            dd->getbuf *= 2;      \
647
3.16G
        }                         \
648
405M
        dd->getlen -= l;          \
649
405M
    } while (0)
650
#define ARJ_GETBITS(dd, c, l)                       \
651
405M
    {                                               \
652
405M
        if (dd->getlen < l) ARJ_BFIL(dd)            \
653
405M
        c = (uint16_t)dd->getbuf >> (CODE_BIT - l); \
654
405M
        ARJ_BPUL(dd, l);                            \
655
405M
    }
656
657
static uint16_t decode_ptr(arj_decode_t *decode_data)
658
25.1M
{
659
25.1M
    uint16_t c, width, plus, pwr;
660
661
25.1M
    plus = 0;
662
25.1M
    pwr  = 1 << STRTP;
663
55.6M
    for (width = STRTP; width < STOPP; width++) {
664
50.7M
        ARJ_GETBIT(decode_data, c);
665
50.7M
        if (c == 0) {
666
20.2M
            break;
667
20.2M
        }
668
30.4M
        plus += pwr;
669
30.4M
        pwr <<= 1;
670
30.4M
    }
671
25.1M
    if (width != 0) {
672
25.1M
        ARJ_GETBITS(decode_data, c, width);
673
25.1M
    }
674
25.1M
    c += plus;
675
25.1M
    return c;
676
25.1M
}
677
678
static uint16_t decode_len(arj_decode_t *decode_data)
679
380M
{
680
380M
    uint16_t c, width, plus, pwr;
681
682
380M
    plus = 0;
683
380M
    pwr  = 1 << STRTL;
684
443M
    for (width = STRTL; width < STOPL; width++) {
685
440M
        ARJ_GETBIT(decode_data, c);
686
440M
        if (c == 0) {
687
377M
            break;
688
377M
        }
689
63.4M
        plus += pwr;
690
63.4M
        pwr <<= 1;
691
63.4M
    }
692
380M
    if (width != 0) {
693
25.1M
        ARJ_GETBITS(decode_data, c, width);
694
25.1M
    }
695
380M
    c += plus;
696
380M
    return c;
697
380M
}
698
699
static cl_error_t decode_f(arj_metadata_t *metadata)
700
28.7k
{
701
28.7k
    cl_error_t ret;
702
703
28.7k
    arj_decode_t decode_data, *dd;
704
28.7k
    uint32_t count = 0, out_ptr = 0;
705
28.7k
    int16_t chr, i, j, pos;
706
707
28.7k
    dd = &decode_data;
708
28.7k
    memset(&decode_data, 0, sizeof(decode_data));
709
28.7k
    decode_data.text = (unsigned char *)cli_calloc(DDICSIZ, 1);
710
28.7k
    if (!decode_data.text) {
711
0
        return CL_EMEM;
712
0
    }
713
28.7k
    decode_data.map       = metadata->map;
714
28.7k
    decode_data.offset    = metadata->offset;
715
28.7k
    decode_data.comp_size = metadata->comp_size;
716
28.7k
    ret                   = init_getbits(&decode_data);
717
28.7k
    if (ret != CL_SUCCESS) {
718
17
        free(decode_data.text);
719
17
        metadata->offset = decode_data.offset;
720
17
        return ret;
721
17
    }
722
28.7k
    decode_data.getlen = decode_data.getbuf = 0;
723
28.7k
    decode_data.status                      = CL_SUCCESS;
724
725
380M
    while (count < metadata->orig_size) {
726
380M
        chr = decode_len(&decode_data);
727
380M
        if (decode_data.status != CL_SUCCESS) {
728
4.71k
            free(decode_data.text);
729
4.71k
            metadata->offset = decode_data.offset;
730
4.71k
            return decode_data.status;
731
4.71k
        }
732
380M
        if (chr == 0) {
733
355M
            ARJ_GETBITS(dd, chr, CHAR_BIT);
734
355M
            if (decode_data.status != CL_SUCCESS) {
735
11.2k
                free(decode_data.text);
736
11.2k
                metadata->offset = decode_data.offset;
737
11.2k
                return decode_data.status;
738
11.2k
            }
739
355M
            decode_data.text[out_ptr] = (unsigned char)chr;
740
355M
            count++;
741
355M
            if (++out_ptr >= DDICSIZ) {
742
12.1k
                out_ptr = 0;
743
12.1k
                if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
744
0
                    free(decode_data.text);
745
0
                    metadata->offset = decode_data.offset;
746
0
                    return CL_EWRITE;
747
0
                }
748
12.1k
            }
749
355M
        } else {
750
25.1M
            j = chr - 1 + THRESHOLD;
751
25.1M
            count += j;
752
25.1M
            pos = decode_ptr(&decode_data);
753
25.1M
            if (decode_data.status != CL_SUCCESS) {
754
7.47k
                free(decode_data.text);
755
7.47k
                metadata->offset = decode_data.offset;
756
7.47k
                return decode_data.status;
757
7.47k
            }
758
25.1M
            if ((i = out_ptr - pos - 1) < 0) {
759
3.21M
                i += DDICSIZ;
760
3.21M
            }
761
25.1M
            if ((i >= DDICSIZ) || (i < 0)) {
762
0
                cli_dbgmsg("UNARJ: bounds exceeded - probably a corrupted file.\n");
763
0
                break;
764
0
            }
765
888M
            while (j-- > 0) {
766
863M
                decode_data.text[out_ptr] = decode_data.text[i];
767
863M
                if (++out_ptr >= DDICSIZ) {
768
24.6k
                    out_ptr = 0;
769
24.6k
                    if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
770
0
                        free(decode_data.text);
771
0
                        metadata->offset = decode_data.offset;
772
0
                        return CL_EWRITE;
773
0
                    }
774
24.6k
                }
775
863M
                if (++i >= DDICSIZ) {
776
35.0k
                    i = 0;
777
35.0k
                }
778
863M
            }
779
25.1M
        }
780
380M
    }
781
5.29k
    if (out_ptr != 0) {
782
2.36k
        write_text(metadata->ofd, decode_data.text, out_ptr);
783
2.36k
    }
784
785
5.29k
    free(decode_data.text);
786
5.29k
    metadata->offset = decode_data.offset;
787
5.29k
    return CL_SUCCESS;
788
28.7k
}
789
790
static cl_error_t arj_unstore(arj_metadata_t *metadata, int ofd, uint32_t len)
791
1.04M
{
792
1.04M
    const unsigned char *data;
793
1.04M
    uint32_t rem;
794
1.04M
    unsigned int todo;
795
1.04M
    size_t count;
796
797
1.04M
    cli_dbgmsg("in arj_unstore\n");
798
1.04M
    rem = len;
799
800
2.34M
    while (rem > 0) {
801
2.32M
        todo = (unsigned int)MIN(8192, rem);
802
2.32M
        data = fmap_need_off_once_len(metadata->map, metadata->offset, todo, &count);
803
2.32M
        if (!data || !count) {
804
            /* Truncated file, not enough bytes available */
805
1.02M
            return CL_EFORMAT;
806
1.02M
        }
807
1.29M
        metadata->offset += count;
808
1.29M
        if (cli_writen(ofd, data, count) != count) {
809
            /* File writing problem */
810
0
            return CL_EWRITE;
811
0
        }
812
1.29M
        rem -= count;
813
1.29M
    }
814
21.8k
    return CL_SUCCESS;
815
1.04M
}
816
817
static int is_arj_archive(arj_metadata_t *metadata)
818
5.28M
{
819
5.28M
    const char header_id[2] = {0x60, 0xea};
820
5.28M
    const char *mark;
821
822
5.28M
    mark = fmap_need_off_once(metadata->map, metadata->offset, 2);
823
5.28M
    if (!mark)
824
1.05M
        return FALSE;
825
4.22M
    metadata->offset += 2;
826
4.22M
    if (memcmp(&mark[0], &header_id[0], 2) == 0) {
827
3.84M
        return TRUE;
828
3.84M
    }
829
384k
    cli_dbgmsg("Not an ARJ archive\n");
830
384k
    return FALSE;
831
4.22M
}
832
833
static int arj_read_main_header(arj_metadata_t *metadata)
834
2.37M
{
835
2.37M
    uint16_t header_size, count;
836
2.37M
    arj_main_hdr_t main_hdr;
837
2.37M
    const char *filename = NULL;
838
2.37M
    const char *comment  = NULL;
839
2.37M
    struct text_norm_state fnstate, comstate;
840
2.37M
    unsigned char *fnnorm  = NULL;
841
2.37M
    unsigned char *comnorm = NULL;
842
2.37M
    uint32_t ret           = TRUE;
843
844
2.37M
    size_t filename_max_len = 0;
845
2.37M
    size_t filename_len     = 0;
846
2.37M
    size_t comment_max_len  = 0;
847
2.37M
    size_t comment_len      = 0;
848
2.37M
    size_t orig_offset      = metadata->offset;
849
850
2.37M
    if (fmap_readn(metadata->map, &header_size, metadata->offset, 2) != 2)
851
0
        return FALSE;
852
853
2.37M
    metadata->offset += 2;
854
2.37M
    header_size = le16_to_host(header_size);
855
2.37M
    cli_dbgmsg("Header Size: %d\n", header_size);
856
2.37M
    if (header_size == 0) {
857
        /* End of archive */
858
2.53k
        ret = FALSE;
859
2.53k
        goto done;
860
2.53k
    }
861
2.37M
    if (header_size > HEADERSIZE_MAX) {
862
30.8k
        cli_dbgmsg("arj_read_header: invalid header_size: %u\n ", header_size);
863
30.8k
        ret = FALSE;
864
30.8k
        goto done;
865
30.8k
    }
866
2.34M
    if ((header_size + sizeof(header_size)) > (metadata->map->len - metadata->offset)) {
867
41.5k
        cli_dbgmsg("arj_read_header: invalid header_size: %u, exceeds length of file.\n", header_size);
868
41.5k
        ret = FALSE;
869
41.5k
        goto done;
870
41.5k
    }
871
2.30M
    if (fmap_readn(metadata->map, &main_hdr, metadata->offset, 30) != 30) {
872
10
        ret = FALSE;
873
10
        goto done;
874
10
    }
875
2.30M
    metadata->offset += 30;
876
877
2.30M
    cli_dbgmsg("ARJ Main File Header\n");
878
2.30M
    cli_dbgmsg("First Header Size: %d\n", main_hdr.first_hdr_size);
879
2.30M
    cli_dbgmsg("Version: %d\n", main_hdr.version);
880
2.30M
    cli_dbgmsg("Min version: %d\n", main_hdr.min_version);
881
2.30M
    cli_dbgmsg("Host OS: %d\n", main_hdr.host_os);
882
2.30M
    cli_dbgmsg("Flags: 0x%x\n", main_hdr.flags);
883
2.30M
    cli_dbgmsg("Security version: %d\n", main_hdr.security_version);
884
2.30M
    cli_dbgmsg("File type: %d\n", main_hdr.file_type);
885
886
2.30M
    if (main_hdr.first_hdr_size < 30) {
887
12.1k
        cli_dbgmsg("Format error. First Header Size < 30\n");
888
12.1k
        ret = FALSE;
889
12.1k
        goto done;
890
12.1k
    }
891
2.29M
    if (main_hdr.first_hdr_size > 30) {
892
2.28M
        metadata->offset += main_hdr.first_hdr_size - 30;
893
2.28M
    }
894
895
2.29M
    filename_max_len = (header_size + sizeof(header_size)) - (metadata->offset - orig_offset);
896
2.29M
    if (filename_max_len > header_size) {
897
19.8k
        cli_dbgmsg("UNARJ: Format error. First Header Size invalid\n");
898
19.8k
        ret = FALSE;
899
19.8k
        goto done;
900
19.8k
    }
901
2.27M
    if (filename_max_len > 0) {
902
2.26M
        fnnorm   = cli_calloc(sizeof(unsigned char), filename_max_len + 1);
903
2.26M
        filename = fmap_need_offstr(metadata->map, metadata->offset, filename_max_len + 1);
904
2.26M
        if (!filename || !fnnorm) {
905
113k
            cli_dbgmsg("UNARJ: Unable to allocate memory for filename\n");
906
113k
            ret = FALSE;
907
113k
            goto done;
908
113k
        }
909
2.15M
        filename_len = CLI_STRNLEN(filename, filename_max_len);
910
2.15M
    }
911
2.15M
    metadata->offset += filename_len + 1;
912
913
2.15M
    comment_max_len = (header_size + sizeof(header_size)) - (metadata->offset - orig_offset);
914
2.15M
    if (comment_max_len > header_size) {
915
9.93k
        cli_dbgmsg("UNARJ: Format error. First Header Size invalid\n");
916
9.93k
        ret = FALSE;
917
9.93k
        goto done;
918
9.93k
    }
919
2.14M
    if (comment_max_len > 0) {
920
2.11M
        comnorm = cli_calloc(sizeof(unsigned char), comment_max_len + 1);
921
2.11M
        comment = fmap_need_offstr(metadata->map, metadata->offset, comment_max_len + 1);
922
2.11M
        if (!comment || !comnorm) {
923
89.1k
            cli_dbgmsg("UNARJ: Unable to allocate memory for comment\n");
924
89.1k
            ret = FALSE;
925
89.1k
            goto done;
926
89.1k
        }
927
2.03M
        comment_len = CLI_STRNLEN(comment, comment_max_len);
928
2.03M
    }
929
2.05M
    metadata->offset += comment_len + 1;
930
931
2.05M
    text_normalize_init(&fnstate, fnnorm, filename_max_len);
932
2.05M
    text_normalize_init(&comstate, comnorm, comment_max_len);
933
934
2.05M
    text_normalize_buffer(&fnstate, (const unsigned char *)filename, filename_len);
935
2.05M
    text_normalize_buffer(&comstate, (const unsigned char *)comment, comment_len);
936
937
2.05M
    cli_dbgmsg("Filename: %s\n", fnnorm);
938
2.05M
    cli_dbgmsg("Comment: %s\n", comnorm);
939
940
2.05M
    metadata->offset += 4; /* crc */
941
    /* Skip past any extended header data */
942
2.53M
    for (;;) {
943
2.53M
        const uint16_t *countp = fmap_need_off_once(metadata->map, metadata->offset, 2);
944
2.53M
        if (!countp) {
945
332k
            ret = FALSE;
946
332k
            goto done;
947
332k
        }
948
2.19M
        count = cli_readint16(countp);
949
2.19M
        metadata->offset += 2;
950
2.19M
        cli_dbgmsg("Extended header size: %d\n", count);
951
2.19M
        if (count == 0) {
952
1.72M
            break;
953
1.72M
        }
954
        /* Skip extended header + 4byte CRC */
955
473k
        metadata->offset += count + 4;
956
473k
    }
957
958
2.37M
done:
959
960
2.37M
    if (fnnorm) {
961
2.26M
        free(fnnorm);
962
2.26M
        fnnorm = NULL;
963
2.26M
    }
964
965
2.37M
    if (comnorm) {
966
2.11M
        free(comnorm);
967
2.11M
        comnorm = NULL;
968
2.11M
    }
969
2.37M
    return ret;
970
2.05M
}
971
972
static cl_error_t arj_read_file_header(arj_metadata_t *metadata)
973
1.46M
{
974
1.46M
    uint16_t header_size, count;
975
1.46M
    const char *filename = NULL, *comment = NULL;
976
1.46M
    arj_file_hdr_t file_hdr;
977
1.46M
    struct text_norm_state fnstate, comstate;
978
1.46M
    unsigned char *fnnorm  = NULL;
979
1.46M
    unsigned char *comnorm = NULL;
980
1.46M
    cl_error_t ret         = CL_SUCCESS;
981
982
1.46M
    size_t filename_max_len = 0;
983
1.46M
    size_t filename_len     = 0;
984
1.46M
    size_t comment_max_len  = 0;
985
1.46M
    size_t comment_len      = 0;
986
1.46M
    size_t orig_offset      = metadata->offset;
987
988
1.46M
    if (fmap_readn(metadata->map, &header_size, metadata->offset, 2) != 2)
989
9.02k
        return CL_EFORMAT;
990
1.45M
    header_size = le16_to_host(header_size);
991
1.45M
    metadata->offset += 2;
992
993
1.45M
    cli_dbgmsg("Header Size: %d\n", header_size);
994
1.45M
    if (header_size == 0) {
995
        /* End of archive */
996
1.71k
        ret = CL_BREAK;
997
1.71k
        goto done;
998
1.71k
    }
999
1.45M
    if (header_size > HEADERSIZE_MAX) {
1000
30.4k
        cli_dbgmsg("arj_read_file_header: invalid header_size: %u\n ", header_size);
1001
30.4k
        ret = CL_EFORMAT;
1002
30.4k
        goto done;
1003
30.4k
    }
1004
1.42M
    if ((header_size + sizeof(header_size)) > (metadata->map->len - metadata->offset)) {
1005
29.6k
        cli_dbgmsg("arj_read_file_header: invalid header_size: %u, exceeds length of file.\n", header_size);
1006
29.6k
        ret = CL_EFORMAT;
1007
29.6k
        goto done;
1008
29.6k
    }
1009
1.39M
    if (fmap_readn(metadata->map, &file_hdr, metadata->offset, 30) != 30) {
1010
18
        ret = CL_EFORMAT;
1011
18
        goto done;
1012
18
    }
1013
1.39M
    metadata->offset += 30;
1014
1.39M
    file_hdr.comp_size = le32_to_host(file_hdr.comp_size);
1015
1.39M
    file_hdr.orig_size = le32_to_host(file_hdr.orig_size);
1016
1017
1.39M
    cli_dbgmsg("ARJ File Header\n");
1018
1.39M
    cli_dbgmsg("First Header Size: %d\n", file_hdr.first_hdr_size);
1019
1.39M
    cli_dbgmsg("Version: %d\n", file_hdr.version);
1020
1.39M
    cli_dbgmsg("Min version: %d\n", file_hdr.min_version);
1021
1.39M
    cli_dbgmsg("Host OS: %d\n", file_hdr.host_os);
1022
1.39M
    cli_dbgmsg("Flags: 0x%x\n", file_hdr.flags);
1023
1.39M
    cli_dbgmsg("Method: %d\n", file_hdr.method);
1024
1.39M
    cli_dbgmsg("File type: %d\n", file_hdr.file_type);
1025
1.39M
    cli_dbgmsg("File type: %d\n", file_hdr.password_mod);
1026
1.39M
    cli_dbgmsg("Compressed size: %u\n", file_hdr.comp_size);
1027
1.39M
    cli_dbgmsg("Original size: %u\n", file_hdr.orig_size);
1028
1029
1.39M
    if (file_hdr.first_hdr_size < 30) {
1030
9.18k
        cli_dbgmsg("Format error. First Header Size < 30\n");
1031
9.18k
        ret = CL_EFORMAT;
1032
9.18k
        goto done;
1033
9.18k
    }
1034
1035
    /* Note: this skips past any extended file start position data (multi-volume) */
1036
1.38M
    if (file_hdr.first_hdr_size > 30) {
1037
1.01M
        metadata->offset += file_hdr.first_hdr_size - 30;
1038
1.01M
    }
1039
1040
1.38M
    filename_max_len = (header_size + sizeof(header_size)) - (metadata->offset - orig_offset);
1041
1.38M
    if (filename_max_len > header_size) {
1042
20.8k
        cli_dbgmsg("UNARJ: Format error. First Header Size invalid\n");
1043
20.8k
        ret = CL_EFORMAT;
1044
20.8k
        goto done;
1045
20.8k
    }
1046
1.36M
    if (filename_max_len > 0) {
1047
1.36M
        fnnorm = cli_calloc(sizeof(unsigned char), filename_max_len + 1);
1048
1.36M
        if (!fnnorm) {
1049
0
            cli_dbgmsg("UNARJ: Unable to allocate memory for filename\n");
1050
0
            ret = CL_EMEM;
1051
0
            goto done;
1052
0
        }
1053
1.36M
        filename = fmap_need_offstr(metadata->map, metadata->offset, filename_max_len + 1);
1054
1.36M
        if (!filename) {
1055
37.7k
            cli_dbgmsg("UNARJ: Filename is out of file\n");
1056
37.7k
            ret = CL_EFORMAT;
1057
37.7k
            goto done;
1058
37.7k
        }
1059
1.32M
        filename_len = CLI_STRNLEN(filename, filename_max_len);
1060
1.32M
    }
1061
1.32M
    metadata->offset += filename_len + 1;
1062
1063
1.32M
    comment_max_len = (header_size + sizeof(header_size)) - (metadata->offset - orig_offset);
1064
1.32M
    if (comment_max_len > header_size) {
1065
2.78k
        cli_dbgmsg("UNARJ: Format error. First Header Size invalid\n");
1066
2.78k
        ret = CL_EFORMAT;
1067
2.78k
        goto done;
1068
2.78k
    }
1069
1.32M
    if (comment_max_len > 0) {
1070
1.30M
        comnorm = cli_calloc(sizeof(unsigned char), comment_max_len + 1);
1071
1.30M
        if (!comnorm) {
1072
0
            cli_dbgmsg("UNARJ: Unable to allocate memory for comment\n");
1073
0
            ret = CL_EMEM;
1074
0
            goto done;
1075
0
        }
1076
1.30M
        comment = fmap_need_offstr(metadata->map, metadata->offset, comment_max_len + 1);
1077
1.30M
        if (!comment) {
1078
6.93k
            cli_dbgmsg("UNARJ: comment is out of file\n");
1079
6.93k
            ret = CL_EFORMAT;
1080
6.93k
            goto done;
1081
6.93k
        }
1082
1.30M
        comment_len += CLI_STRNLEN(comment, comment_max_len);
1083
1.30M
    }
1084
1.31M
    metadata->offset += comment_len + 1;
1085
1086
1.31M
    text_normalize_init(&fnstate, fnnorm, filename_max_len);
1087
1.31M
    text_normalize_init(&comstate, comnorm, comment_max_len);
1088
1089
1.31M
    text_normalize_buffer(&fnstate, (const unsigned char *)filename, filename_len);
1090
1.31M
    text_normalize_buffer(&comstate, (const unsigned char *)comment, comment_len);
1091
1092
1.31M
    cli_dbgmsg("Filename: %s\n", fnnorm);
1093
1.31M
    cli_dbgmsg("Comment: %s\n", comnorm);
1094
1.31M
    metadata->filename = CLI_STRNDUP(filename, filename_len);
1095
1096
    /* Skip CRC */
1097
1.31M
    metadata->offset += 4;
1098
1099
    /* Skip past any extended header data */
1100
1.53M
    for (;;) {
1101
1.53M
        const uint16_t *countp = fmap_need_off_once(metadata->map, metadata->offset, 2);
1102
1.53M
        if (!countp) {
1103
128k
            if (metadata->filename)
1104
128k
                free(metadata->filename);
1105
128k
            metadata->filename = NULL;
1106
128k
            ret                = CL_EFORMAT;
1107
128k
            goto done;
1108
128k
        }
1109
1.40M
        count = cli_readint16(countp);
1110
1.40M
        metadata->offset += 2;
1111
1.40M
        cli_dbgmsg("Extended header size: %d\n", count);
1112
1.40M
        if (count == 0) {
1113
1.18M
            break;
1114
1.18M
        }
1115
        /* Skip extended header + 4byte CRC */
1116
222k
        metadata->offset += count + 4;
1117
222k
    }
1118
1.18M
    metadata->comp_size = file_hdr.comp_size;
1119
1.18M
    metadata->orig_size = file_hdr.orig_size;
1120
1.18M
    metadata->method    = file_hdr.method;
1121
1.18M
    metadata->encrypted = ((file_hdr.flags & GARBLE_FLAG) != 0) ? TRUE : FALSE;
1122
1.18M
    metadata->ofd       = -1;
1123
1.18M
    if (!metadata->filename) {
1124
0
        ret = CL_EMEM;
1125
0
        goto done;
1126
0
    }
1127
1128
1.45M
done:
1129
1130
1.45M
    if (fnnorm) {
1131
1.36M
        free(fnnorm);
1132
1.36M
        fnnorm = NULL;
1133
1.36M
    }
1134
1135
1.45M
    if (comnorm) {
1136
1.30M
        free(comnorm);
1137
1.30M
        comnorm = NULL;
1138
1.30M
    }
1139
1.45M
    return ret;
1140
1.18M
}
1141
1142
cl_error_t cli_unarj_open(fmap_t *map, const char *dirname, arj_metadata_t *metadata)
1143
2.37M
{
1144
2.37M
    UNUSEDPARAM(dirname);
1145
2.37M
    cli_dbgmsg("in cli_unarj_open\n");
1146
2.37M
    metadata->map    = map;
1147
2.37M
    metadata->offset = 0;
1148
2.37M
    if (!is_arj_archive(metadata)) {
1149
0
        cli_dbgmsg("Not in ARJ format\n");
1150
0
        return CL_EFORMAT;
1151
0
    }
1152
2.37M
    if (!arj_read_main_header(metadata)) {
1153
652k
        cli_dbgmsg("Failed to read main header\n");
1154
652k
        return CL_EFORMAT;
1155
652k
    }
1156
1.72M
    return CL_SUCCESS;
1157
2.37M
}
1158
1159
cl_error_t cli_unarj_prepare_file(const char *dirname, arj_metadata_t *metadata)
1160
2.90M
{
1161
2.90M
    cli_dbgmsg("in cli_unarj_prepare_file\n");
1162
2.90M
    if (!metadata || !dirname) {
1163
0
        return CL_ENULLARG;
1164
0
    }
1165
    /* Each file is preceded by the ARJ file marker */
1166
2.90M
    if (!is_arj_archive(metadata)) {
1167
1.44M
        cli_dbgmsg("Not in ARJ format\n");
1168
1.44M
        return CL_EFORMAT;
1169
1.44M
    }
1170
1.46M
    return arj_read_file_header(metadata);
1171
2.90M
}
1172
1173
cl_error_t cli_unarj_extract_file(const char *dirname, arj_metadata_t *metadata)
1174
1.13M
{
1175
1.13M
    cl_error_t ret = CL_SUCCESS;
1176
1.13M
    char filename[1024];
1177
1178
1.13M
    cli_dbgmsg("in cli_unarj_extract_file\n");
1179
1.13M
    if (!metadata || !dirname) {
1180
0
        return CL_ENULLARG;
1181
0
    }
1182
1183
1.13M
    if (metadata->encrypted) {
1184
10.3k
        cli_dbgmsg("PASSWORDed file (skipping)\n");
1185
10.3k
        metadata->offset += metadata->comp_size;
1186
10.3k
        cli_dbgmsg("Target offset: %lu\n", (unsigned long int)metadata->offset);
1187
10.3k
        return CL_SUCCESS;
1188
10.3k
    }
1189
1190
1.12M
    snprintf(filename, 1024, "%s" PATHSEP "file.uar", dirname);
1191
1.12M
    cli_dbgmsg("Filename: %s\n", filename);
1192
1.12M
    metadata->ofd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600);
1193
1.12M
    if (metadata->ofd < 0) {
1194
0
        return CL_EOPEN;
1195
0
    }
1196
1.12M
    switch (metadata->method) {
1197
1.04M
        case 0:
1198
1.04M
            ret = arj_unstore(metadata, metadata->ofd, metadata->comp_size);
1199
1.04M
            break;
1200
13.2k
        case 1:
1201
22.6k
        case 2:
1202
37.8k
        case 3:
1203
37.8k
            ret = decode(metadata);
1204
37.8k
            break;
1205
28.7k
        case 4:
1206
28.7k
            ret = decode_f(metadata);
1207
28.7k
            break;
1208
6.28k
        default:
1209
6.28k
            ret = CL_EFORMAT;
1210
6.28k
            break;
1211
1.12M
    }
1212
1.12M
    return ret;
1213
1.12M
}