Coverage Report

Created: 2026-10-08 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libzip/lib/zip_dirent.c
Line
Count
Source
1
/*
2
  zip_dirent.c -- read directory entry (local or central), clean dirent
3
  Copyright (C) 1999-2025 Dieter Baron and Thomas Klausner
4
5
  This file is part of libzip, a library to manipulate ZIP archives.
6
  The authors can be contacted at <info@libzip.org>
7
8
  Redistribution and use in source and binary forms, with or without
9
  modification, are permitted provided that the following conditions
10
  are met:
11
  1. Redistributions of source code must retain the above copyright
12
     notice, this list of conditions and the following disclaimer.
13
  2. Redistributions in binary form must reproduce the above copyright
14
     notice, this list of conditions and the following disclaimer in
15
     the documentation and/or other materials provided with the
16
     distribution.
17
  3. The names of the authors may not be used to endorse or promote
18
     products derived from this software without specific prior
19
     written permission.
20
21
  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22
  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29
  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31
  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
*/
33
34
#include "zipint.h"
35
36
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <sys/types.h>
41
#include <time.h>
42
#include <zlib.h>
43
44
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str, bool check_consistency);
45
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
46
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error);
47
48
49
113k
void _zip_cdir_free(zip_cdir_t *cd) {
50
113k
    zip_uint64_t i;
51
52
113k
    if (cd == NULL) {
53
0
        return;
54
0
    }
55
56
120M
    for (i = 0; i < cd->nentry; i++) {
57
120M
        _zip_entry_finalize(cd->entry + i);
58
120M
    }
59
113k
    free(cd->entry);
60
113k
    _zip_string_free(cd->comment);
61
113k
    free(cd);
62
113k
}
63
64
65
122k
zip_cdir_t *_zip_cdir_new(zip_error_t *error) {
66
122k
    zip_cdir_t *cd;
67
68
122k
    if ((cd = (zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
69
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
70
0
        return NULL;
71
0
    }
72
73
122k
    cd->entry = NULL;
74
122k
    cd->nentry = cd->nentry_alloc = 0;
75
122k
    cd->size = cd->offset = 0;
76
122k
    cd->comment = NULL;
77
122k
    cd->is_zip64 = false;
78
79
122k
    return cd;
80
122k
}
81
82
83
14.3k
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
84
14.3k
    zip_uint64_t i;
85
86
14.3k
    if (additional_entries == 0) {
87
2.24k
        return true;
88
2.24k
    }
89
90
12.1k
    if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
91
0
        return false;
92
0
    }
93
94
120M
    for (i = cd->nentry; i < cd->nentry_alloc; i++) {
95
120M
        _zip_entry_init(cd->entry + i);
96
120M
    }
97
98
12.1k
    cd->nentry = cd->nentry_alloc;
99
100
12.1k
    return true;
101
12.1k
}
102
103
104
5.31k
zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
105
5.31k
    zip_uint64_t offset, size;
106
5.31k
    zip_string_t *comment;
107
5.31k
    zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
108
5.31k
    zip_buffer_t *buffer;
109
5.31k
    zip_int64_t off;
110
5.31k
    zip_uint64_t i;
111
5.31k
    zip_uint32_t cdir_crc;
112
113
5.31k
    if ((off = zip_source_tell_write(za->src)) < 0) {
114
0
        zip_error_set_from_source(&za->error, za->src);
115
0
        return -1;
116
0
    }
117
5.31k
    offset = (zip_uint64_t)off;
118
119
5.31k
    if (ZIP_WANT_TORRENTZIP(za)) {
120
0
        cdir_crc = (zip_uint32_t)crc32(0, NULL, 0);
121
0
        za->write_crc = &cdir_crc;
122
0
    }
123
124
28.0k
    for (i = 0; i < survivors; i++) {
125
22.7k
        zip_entry_t *entry = za->entry + filelist[i].idx;
126
127
22.7k
        if (_zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL) < 0) {
128
0
            za->write_crc = NULL;
129
0
            return -1;
130
0
        }
131
22.7k
    }
132
133
5.31k
    za->write_crc = NULL;
134
135
5.31k
    if ((off = zip_source_tell_write(za->src)) < 0) {
136
0
        zip_error_set_from_source(&za->error, za->src);
137
0
        return -1;
138
0
    }
139
5.31k
    size = (zip_uint64_t)off - offset;
140
141
5.31k
    if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
142
0
        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
143
0
        return -1;
144
0
    }
145
146
5.31k
    if (survivors > ZIP_UINT16_MAX || offset > ZIP_UINT32_MAX || size > ZIP_UINT32_MAX) {
147
0
        _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
148
0
        _zip_buffer_put_64(buffer, EOCD64LEN - 12);
149
0
        _zip_buffer_put_16(buffer, 45);
150
0
        _zip_buffer_put_16(buffer, 45);
151
0
        _zip_buffer_put_32(buffer, 0);
152
0
        _zip_buffer_put_32(buffer, 0);
153
0
        _zip_buffer_put_64(buffer, survivors);
154
0
        _zip_buffer_put_64(buffer, survivors);
155
0
        _zip_buffer_put_64(buffer, size);
156
0
        _zip_buffer_put_64(buffer, offset);
157
0
        _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4);
158
0
        _zip_buffer_put_32(buffer, 0);
159
0
        _zip_buffer_put_64(buffer, offset + size);
160
0
        _zip_buffer_put_32(buffer, 1);
161
0
    }
162
163
5.31k
    _zip_buffer_put(buffer, EOCD_MAGIC, 4);
164
5.31k
    _zip_buffer_put_32(buffer, 0);
165
5.31k
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
166
5.31k
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
167
5.31k
    _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
168
5.31k
    _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset);
169
170
5.31k
    comment = za->comment_changed ? za->comment_changes : za->comment_orig;
171
172
5.31k
    if (ZIP_WANT_TORRENTZIP(za)) {
173
0
        _zip_buffer_put_16(buffer, TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH);
174
0
    }
175
5.31k
    else {
176
5.31k
        _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
177
5.31k
    }
178
179
180
5.31k
    if (!_zip_buffer_ok(buffer)) {
181
0
        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
182
0
        _zip_buffer_free(buffer);
183
0
        return -1;
184
0
    }
185
186
5.31k
    if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) {
187
0
        _zip_buffer_free(buffer);
188
0
        return -1;
189
0
    }
190
191
5.31k
    _zip_buffer_free(buffer);
192
193
5.31k
    if (ZIP_WANT_TORRENTZIP(za)) {
194
0
        char torrentzip_comment[TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH + 1];
195
0
        snprintf(torrentzip_comment, sizeof(torrentzip_comment), TORRENTZIP_SIGNATURE "%08X", cdir_crc);
196
197
0
        if (_zip_write(za, torrentzip_comment, strlen(torrentzip_comment)) < 0) {
198
0
            return -1;
199
0
        }
200
0
    }
201
5.31k
    else if (comment != NULL) {
202
581
        if (_zip_write(za, comment->raw, comment->length) < 0) {
203
0
            return -1;
204
0
        }
205
581
    }
206
207
5.31k
    return (zip_int64_t)size;
208
5.31k
}
209
210
211
23.0k
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *sde) {
212
23.0k
    zip_dirent_t *tde;
213
214
    /*
215
     This does a shallow copy. Allocated members are copied when they are modified.
216
     The changed flags keep track of which members need to be freed when a cloned entry is freed.
217
     */
218
219
23.0k
    if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL) {
220
0
        return NULL;
221
0
    }
222
223
23.0k
    if (sde) {
224
0
        (void)memcpy_s(tde, sizeof(*tde), sde, sizeof(*sde));
225
0
    }
226
23.0k
    else {
227
23.0k
        _zip_dirent_init(tde);
228
23.0k
    }
229
230
23.0k
    tde->changed = 0;
231
23.0k
    tde->cloned = 1;
232
233
23.0k
    return tde;
234
23.0k
}
235
236
237
315k
void _zip_dirent_finalize(zip_dirent_t *zde) {
238
315k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
239
315k
        _zip_string_free(zde->filename);
240
315k
        zde->filename = NULL;
241
315k
    }
242
315k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
243
315k
        _zip_extra_fields_fini(&zde->extra_fields);
244
315k
    }
245
315k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
246
295k
        _zip_string_free(zde->comment);
247
295k
        zde->comment = NULL;
248
295k
    }
249
315k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
250
307k
        if (zde->password) {
251
15.6k
            _zip_crypto_clear(zde->password, strlen(zde->password));
252
15.6k
        }
253
307k
        free(zde->password);
254
307k
        zde->password = NULL;
255
307k
    }
256
315k
}
257
258
259
241M
void _zip_dirent_free(zip_dirent_t *zde) {
260
241M
    if (zde == NULL) {
261
241M
        return;
262
241M
    }
263
264
315k
    _zip_dirent_finalize(zde);
265
315k
    free(zde);
266
315k
}
267
268
269
0
bool _zip_dirent_merge(zip_dirent_t *de, zip_dirent_t *de_orig, bool replacing_data, zip_error_t *error) {
270
0
    if (!de->cloned) {
271
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
272
0
        return false;
273
0
    }
274
275
0
    if (!(de->changed & ZIP_DIRENT_ATTRIBUTES)) {
276
0
        de->ext_attrib = de_orig->ext_attrib;
277
0
        de->int_attrib = de_orig->int_attrib;
278
0
    }
279
0
    if (!(de->changed & ZIP_DIRENT_COMMENT)) {
280
0
        de->comment = de_orig->comment;
281
0
    }
282
0
    if (!(de->changed & ZIP_DIRENT_COMP_METHOD)) {
283
0
        if (replacing_data) {
284
0
            de->comp_method = ZIP_CM_DEFAULT;
285
0
            de->compression_level = 0;
286
0
        }
287
0
        else {
288
0
            de->comp_method = de_orig->comp_method;
289
0
            de->compression_level = de_orig->compression_level;
290
0
        }
291
0
    }
292
0
    if (!(de->changed & ZIP_DIRENT_ENCRYPTION_METHOD)) {
293
0
        if (replacing_data) {
294
0
            de->encryption_method = ZIP_EM_NONE;
295
0
        }
296
0
        else {
297
0
            de->encryption_method = de_orig->encryption_method;
298
0
        }
299
0
    }
300
0
    if (!(de->changed & ZIP_DIRENT_EXTRA_FIELD)) {
301
0
        de->extra_fields = de_orig->extra_fields;
302
0
    }
303
0
    if (!(de->changed & ZIP_DIRENT_FILENAME)) {
304
0
        de->filename = de_orig->filename;
305
0
    }
306
0
    if (!(de->changed & ZIP_DIRENT_LAST_MOD)) {
307
0
        de->last_mod = de_orig->last_mod;
308
0
    }
309
0
    if (!(de->changed & ZIP_DIRENT_PASSWORD)) {
310
0
        de->password = de_orig->password;
311
0
    }
312
313
0
    return true;
314
0
}
315
316
317
606k
void _zip_dirent_init(zip_dirent_t *de) {
318
606k
    de->changed = 0;
319
606k
    de->local_extra_fields_read = 0;
320
606k
    de->cloned = 0;
321
322
606k
    de->crc_valid = true;
323
606k
    de->last_mod_mtime_valid = false;
324
606k
    de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
325
606k
    de->version_needed = 10; /* 1.0 */
326
606k
    de->bitflags = 0;
327
606k
    de->comp_method = ZIP_CM_DEFAULT;
328
606k
    de->last_mod.date = 0;
329
606k
    de->last_mod.time = 0;
330
606k
    de->crc = 0;
331
606k
    de->comp_size = 0;
332
606k
    de->uncomp_size = 0;
333
606k
    de->filename = NULL;
334
606k
    _zip_extra_fields_init(&de->extra_fields);
335
606k
    de->comment = NULL;
336
606k
    de->disk_number = 0;
337
606k
    de->int_attrib = 0;
338
606k
    de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
339
606k
    de->offset = 0;
340
606k
    de->compression_level = 0;
341
606k
    de->encryption_method = ZIP_EM_NONE;
342
606k
    de->password = NULL;
343
606k
}
344
345
346
95.2k
bool _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) {
347
95.2k
    if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX)) {
348
0
        return true;
349
0
    }
350
351
95.2k
    return false;
352
95.2k
}
353
354
355
292k
zip_dirent_t *_zip_dirent_new(void) {
356
292k
    zip_dirent_t *de;
357
358
292k
    if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL) {
359
0
        return NULL;
360
0
    }
361
362
292k
    _zip_dirent_init(de);
363
292k
    return de;
364
292k
}
365
366
367
/*
368
   Fills the zip directory entry zde.
369
370
   If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
371
372
   If local is true, it reads a local header instead of a central directory entry.
373
374
   Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
375
*/
376
377
292k
zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, bool is_zip64, zip_uint64_t central_compressed_size, bool check_consistency, zip_error_t *error) {
378
292k
    zip_uint8_t buf[CDENTRYSIZE];
379
292k
    zip_uint32_t size, variable_size;
380
292k
    zip_uint16_t filename_len, comment_len, ef_len;
381
292k
    zip_string_t *utf8_string;
382
292k
    zip_extra_field_t **efp;
383
384
292k
    bool from_buffer = (buffer != NULL);
385
386
292k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
387
388
292k
    if (buffer) {
389
115k
        if (_zip_buffer_left(buffer) < size) {
390
461
            zip_error_set(error, ZIP_ER_NOZIP, 0);
391
461
            return -1;
392
461
        }
393
115k
    }
394
176k
    else {
395
176k
        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
396
29
            return -1;
397
29
        }
398
176k
    }
399
400
291k
    if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
401
279
        zip_error_set(error, ZIP_ER_NOZIP, 0);
402
279
        if (!from_buffer) {
403
103
            _zip_buffer_free(buffer);
404
103
        }
405
279
        return -1;
406
279
    }
407
408
    /* convert buffercontents to zip_dirent */
409
410
291k
    _zip_dirent_init(zde);
411
291k
    if (!local) {
412
291k
        zde->version_madeby = _zip_buffer_get_16(buffer);
413
291k
    }
414
0
    else {
415
0
        zde->version_madeby = 0;
416
0
    }
417
291k
    zde->version_needed = _zip_buffer_get_16(buffer);
418
291k
    zde->bitflags = _zip_buffer_get_16(buffer);
419
291k
    zde->comp_method = _zip_buffer_get_16(buffer);
420
421
    /* convert to time_t */
422
291k
    zde->last_mod.time = _zip_buffer_get_16(buffer);
423
291k
    zde->last_mod.date = _zip_buffer_get_16(buffer);
424
425
291k
    zde->crc = _zip_buffer_get_32(buffer);
426
291k
    zde->comp_size = _zip_buffer_get_32(buffer);
427
291k
    zde->uncomp_size = _zip_buffer_get_32(buffer);
428
429
291k
    filename_len = _zip_buffer_get_16(buffer);
430
291k
    ef_len = _zip_buffer_get_16(buffer);
431
432
291k
    if (local) {
433
0
        comment_len = 0;
434
0
        zde->disk_number = 0;
435
0
        zde->int_attrib = 0;
436
0
        zde->ext_attrib = 0;
437
0
        zde->offset = 0;
438
0
    }
439
291k
    else {
440
291k
        comment_len = _zip_buffer_get_16(buffer);
441
291k
        zde->disk_number = _zip_buffer_get_16(buffer);
442
291k
        zde->int_attrib = _zip_buffer_get_16(buffer);
443
291k
        zde->ext_attrib = _zip_buffer_get_32(buffer);
444
291k
        zde->offset = _zip_buffer_get_32(buffer);
445
291k
    }
446
447
291k
    if (!_zip_buffer_ok(buffer)) {
448
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
449
0
        if (!from_buffer) {
450
0
            _zip_buffer_free(buffer);
451
0
        }
452
0
        return -1;
453
0
    }
454
455
291k
    if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
456
54.6k
        if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
457
            /* TODO */
458
24.4k
            zde->encryption_method = ZIP_EM_UNKNOWN;
459
24.4k
        }
460
30.1k
        else {
461
30.1k
            zde->encryption_method = ZIP_EM_TRAD_PKWARE;
462
30.1k
        }
463
54.6k
    }
464
236k
    else {
465
236k
        zde->encryption_method = ZIP_EM_NONE;
466
236k
    }
467
468
291k
    zde->filename = NULL;
469
291k
    _zip_extra_fields_init(&zde->extra_fields);
470
291k
    zde->comment = NULL;
471
472
291k
    variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
473
474
291k
    if (from_buffer) {
475
115k
        if (_zip_buffer_left(buffer) < variable_size) {
476
204
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
477
204
            return -1;
478
204
        }
479
115k
    }
480
176k
    else {
481
176k
        _zip_buffer_free(buffer);
482
483
176k
        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
484
70
            return -1;
485
70
        }
486
176k
    }
487
488
290k
    if (filename_len) {
489
153k
        zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
490
153k
        if (zde->filename == NULL) {
491
0
            if (zip_error_code_zip(error) == ZIP_ER_EOF) {
492
0
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
493
0
            }
494
0
            if (!from_buffer) {
495
0
                _zip_buffer_free(buffer);
496
0
            }
497
0
            return -1;
498
0
        }
499
500
153k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
501
11.7k
            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
502
99
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME);
503
99
                if (!from_buffer) {
504
25
                    _zip_buffer_free(buffer);
505
25
                }
506
99
                return -1;
507
99
            }
508
11.7k
        }
509
153k
    }
510
511
290k
    if (ef_len) {
512
79.0k
        zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
513
514
79.0k
        if (ef == NULL) {
515
0
            if (!from_buffer) {
516
0
                _zip_buffer_free(buffer);
517
0
            }
518
0
            return -1;
519
0
        }
520
79.0k
        if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, (local ? &zde->extra_fields.local : &zde->extra_fields.central), error)) {
521
405
            free(ef);
522
405
            if (!from_buffer) {
523
63
                _zip_buffer_free(buffer);
524
63
            }
525
405
            return -1;
526
405
        }
527
78.6k
        free(ef);
528
78.6k
        if (local) {
529
0
            zde->local_extra_fields_read = 1;
530
0
        }
531
78.6k
    }
532
533
290k
    if (comment_len) {
534
15.0k
        zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
535
15.0k
        if (zde->comment == NULL) {
536
0
            if (!from_buffer) {
537
0
                _zip_buffer_free(buffer);
538
0
            }
539
0
            return -1;
540
0
        }
541
15.0k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
542
5.82k
            if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
543
64
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT);
544
64
                if (!from_buffer) {
545
15
                    _zip_buffer_free(buffer);
546
15
                }
547
64
                return -1;
548
64
            }
549
5.82k
        }
550
15.0k
    }
551
552
290k
    if ((utf8_string = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename, check_consistency)) == NULL && zde->filename != NULL) {
553
0
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_UTF8_FILENAME_MISMATCH);
554
0
        if (!from_buffer) {
555
0
            _zip_buffer_free(buffer);
556
0
        }
557
0
        return -1;
558
0
    }
559
290k
    zde->filename = utf8_string;
560
561
    /* Check for a NUL byte in the final name; the Info-ZIP Unicode Path extra
562
       field can replace zde->filename above, so this must run after that. */
563
290k
    if (check_consistency && zde->filename != NULL) {
564
0
        zip_uint8_t *p;
565
566
0
        for (p = zde->filename->raw; p < zde->filename->raw + zde->filename->length; p++) {
567
0
            if (*p == 0) {
568
0
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_NUL_IN_FILENAME);
569
0
                if (!from_buffer) {
570
0
                    _zip_buffer_free(buffer);
571
0
                }
572
0
                return -1;
573
0
            }
574
0
        }
575
0
    }
576
577
290k
    if (!local) {
578
290k
        if ((utf8_string = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment, check_consistency)) == NULL && zde->comment != NULL) {
579
0
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_UTF8_COMMENT_MISMATCH);
580
0
            if (!from_buffer) {
581
0
                _zip_buffer_free(buffer);
582
0
            }
583
0
            return -1;
584
0
        }
585
290k
        zde->comment = utf8_string;
586
290k
    }
587
588
    /* Zip64 */
589
590
290k
    if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
591
26.7k
        zip_uint16_t got_len;
592
26.7k
        const zip_uint8_t *ef = _zip_extra_fields_get_by_id(&zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error);
593
26.7k
        if (ef != NULL) {
594
7.83k
            if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) {
595
1.51k
                if (!from_buffer) {
596
17
                    _zip_buffer_free(buffer);
597
17
                }
598
1.51k
                return -1;
599
1.51k
            }
600
7.83k
        }
601
18.9k
        else if (is_zip64) {
602
5
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_MISSING_ZIP64_EF);
603
5
            if (!from_buffer) {
604
3
                _zip_buffer_free(buffer);
605
3
            }
606
5
            return -1;
607
5
        }
608
26.7k
    }
609
610
611
288k
    if (!_zip_buffer_ok(buffer)) {
612
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
613
0
        if (!from_buffer) {
614
0
            _zip_buffer_free(buffer);
615
0
        }
616
0
        return -1;
617
0
    }
618
619
288k
    if (!from_buffer) {
620
175k
        _zip_buffer_free(buffer);
621
175k
    }
622
623
288k
    if (local && zde->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
624
0
        zip_uint32_t df_crc;
625
0
        zip_uint64_t df_comp_size, df_uncomp_size;
626
627
0
        if (zip_source_seek(src, central_compressed_size, SEEK_CUR) != 0 || (buffer = _zip_buffer_new_from_source(src, MAX_DATA_DESCRIPTOR_LENGTH, buf, error)) == NULL) {
628
0
            return -1;
629
0
        }
630
0
        if (memcmp(_zip_buffer_peek(buffer, MAGIC_LEN), DATADES_MAGIC, MAGIC_LEN) == 0) {
631
0
            _zip_buffer_skip(buffer, MAGIC_LEN);
632
0
        }
633
0
        df_crc = _zip_buffer_get_32(buffer);
634
0
        df_comp_size = is_zip64 ? _zip_buffer_get_64(buffer) : _zip_buffer_get_32(buffer);
635
0
        df_uncomp_size = is_zip64 ? _zip_buffer_get_64(buffer) : _zip_buffer_get_32(buffer);
636
637
0
        if (!_zip_buffer_ok(buffer)) {
638
0
            zip_error_set(error, ZIP_ER_INTERNAL, 0);
639
0
            _zip_buffer_free(buffer);
640
0
            return -1;
641
0
        }
642
0
        _zip_buffer_free(buffer);
643
644
        /* According to the appnote, it should be 0, but some implementations write the actual value. */
645
0
        if ((zde->crc != 0 && zde->crc != df_crc) || (zde->comp_size != 0 && zde->comp_size != df_comp_size) || (zde->uncomp_size != 0 && zde->uncomp_size != df_uncomp_size)) {
646
0
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_DATA_DESCRIPTOR_MISMATCH);
647
0
            return -1;
648
0
        }
649
0
        zde->crc = df_crc;
650
0
        zde->comp_size = df_comp_size;
651
0
        zde->uncomp_size = df_uncomp_size;
652
0
    }
653
654
    /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */
655
288k
    if (zde->offset > ZIP_INT64_MAX) {
656
267
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
657
267
        return -1;
658
267
    }
659
660
288k
    if (!_zip_dirent_process_winzip_aes(zde, error)) {
661
193
        return -1;
662
193
    }
663
664
288k
    efp = local ? &zde->extra_fields.local : &zde->extra_fields.central;
665
288k
    *efp = _zip_ef_remove_internal(*efp);
666
667
288k
    return (zip_int64_t)size + (zip_int64_t)variable_size;
668
288k
}
669
670
7.83k
bool zip_dirent_process_ef_zip64(zip_dirent_t *zde, const zip_uint8_t *ef, zip_uint64_t got_len, bool local, zip_error_t *error) {
671
7.83k
    zip_buffer_t *ef_buffer;
672
673
7.83k
    if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
674
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
675
0
        return false;
676
0
    }
677
678
7.83k
    if (zde->uncomp_size == ZIP_UINT32_MAX) {
679
4.69k
        zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
680
4.69k
    }
681
3.13k
    else if (local) {
682
        /* From appnote.txt: This entry in the Local header MUST
683
           include BOTH original and compressed file size fields. */
684
0
        (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
685
0
    }
686
7.83k
    if (zde->comp_size == ZIP_UINT32_MAX) {
687
4.77k
        zde->comp_size = _zip_buffer_get_64(ef_buffer);
688
4.77k
    }
689
3.05k
    else if (local) {
690
        /* From appnote.txt: This entry in the Local header MUST
691
           include BOTH original and compressed file size fields. */
692
0
        (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
693
0
    }
694
7.83k
    if (!local) {
695
7.83k
        if (zde->offset == ZIP_UINT32_MAX) {
696
2.69k
            zde->offset = _zip_buffer_get_64(ef_buffer);
697
2.69k
        }
698
7.83k
        if (zde->disk_number == ZIP_UINT16_MAX) {
699
1.05k
            zde->disk_number = _zip_buffer_get_32(ef_buffer);
700
1.05k
        }
701
7.83k
    }
702
703
7.83k
    if (!_zip_buffer_eof(ef_buffer)) {
704
        /* accept additional fields if values match */
705
3.36k
        bool ok = true;
706
3.36k
        switch (got_len) {
707
2.28k
        case 28:
708
2.28k
            _zip_buffer_set_offset(ef_buffer, 24);
709
2.28k
            if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
710
1.06k
                ok = false;
711
1.06k
            }
712
            /* fallthrough */
713
3.04k
        case 24:
714
3.04k
            _zip_buffer_set_offset(ef_buffer, 0);
715
3.04k
            if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) {
716
1.18k
                ok = false;
717
1.18k
            }
718
3.04k
            break;
719
720
322
        default:
721
322
            ok = false;
722
3.36k
        }
723
3.36k
        if (!ok) {
724
1.51k
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
725
1.51k
            _zip_buffer_free(ef_buffer);
726
1.51k
            return false;
727
1.51k
        }
728
3.36k
    }
729
6.31k
    _zip_buffer_free(ef_buffer);
730
731
6.31k
    return true;
732
7.83k
}
733
734
735
580k
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str, bool check_consistency) {
736
580k
    zip_uint16_t ef_len;
737
580k
    zip_uint32_t ef_crc;
738
580k
    zip_buffer_t *buffer;
739
740
580k
    const zip_uint8_t *ef = _zip_extra_fields_get_by_id(&de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
741
742
580k
    if (ef == NULL || ef_len < 5 || ef[0] != 1) {
743
559k
        return str;
744
559k
    }
745
746
20.8k
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
747
0
        return str;
748
0
    }
749
750
20.8k
    _zip_buffer_get_8(buffer);
751
20.8k
    ef_crc = _zip_buffer_get_32(buffer);
752
753
20.8k
    if (_zip_string_crc32(str) == ef_crc) {
754
17.4k
        zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
755
17.4k
        zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
756
757
17.4k
        if (ef_str != NULL) {
758
5.22k
            if (check_consistency) {
759
0
                if (!_zip_string_equal(str, ef_str) && _zip_string_is_ascii(ef_str)) {
760
0
                    _zip_string_free(ef_str);
761
0
                    _zip_buffer_free(buffer);
762
0
                    return NULL;
763
0
                }
764
0
            }
765
766
5.22k
            _zip_string_free(str);
767
5.22k
            str = ef_str;
768
5.22k
        }
769
17.4k
    }
770
771
20.8k
    _zip_buffer_free(buffer);
772
773
20.8k
    return str;
774
20.8k
}
775
776
777
288k
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
778
288k
    zip_uint16_t ef_len;
779
288k
    zip_buffer_t *buffer;
780
288k
    const zip_uint8_t *ef;
781
288k
    bool crc_valid;
782
288k
    zip_uint16_t enc_method;
783
784
785
288k
    if (de->comp_method != ZIP_CM_WINZIP_AES) {
786
277k
        return true;
787
277k
    }
788
789
10.6k
    ef = _zip_extra_fields_get_by_id(&de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
790
791
10.6k
    if (ef == NULL || ef_len < 7) {
792
42
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
793
42
        return false;
794
42
    }
795
796
10.6k
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
797
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
798
0
        return false;
799
0
    }
800
801
    /* version */
802
803
10.6k
    crc_valid = true;
804
10.6k
    switch (_zip_buffer_get_16(buffer)) {
805
7.58k
    case 1:
806
7.58k
        break;
807
808
3.06k
    case 2:
809
3.06k
        crc_valid = false;
810
        /* TODO: When checking consistency, check that crc is 0. */
811
3.06k
        break;
812
813
8
    default:
814
8
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
815
8
        _zip_buffer_free(buffer);
816
8
        return false;
817
10.6k
    }
818
819
    /* vendor */
820
10.6k
    if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
821
109
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
822
109
        _zip_buffer_free(buffer);
823
109
        return false;
824
109
    }
825
826
    /* mode */
827
10.5k
    switch (_zip_buffer_get_8(buffer)) {
828
2.88k
    case 1:
829
2.88k
        enc_method = ZIP_EM_AES_128;
830
2.88k
        break;
831
45
    case 2:
832
45
        enc_method = ZIP_EM_AES_192;
833
45
        break;
834
7.59k
    case 3:
835
7.59k
        enc_method = ZIP_EM_AES_256;
836
7.59k
        break;
837
19
    default:
838
19
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
839
19
        _zip_buffer_free(buffer);
840
19
        return false;
841
10.5k
    }
842
843
10.5k
    if (ef_len != 7) {
844
15
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
845
15
        _zip_buffer_free(buffer);
846
15
        return false;
847
15
    }
848
849
10.5k
    de->crc_valid = crc_valid;
850
10.5k
    de->encryption_method = enc_method;
851
10.5k
    de->comp_method = _zip_buffer_get_16(buffer);
852
853
10.5k
    _zip_buffer_free(buffer);
854
10.5k
    return true;
855
10.5k
}
856
857
858
50.8k
zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
859
50.8k
    zip_int32_t size;
860
50.8k
    bool local = (flags & ZIP_EF_LOCAL) != 0;
861
50.8k
    int i;
862
50.8k
    zip_uint8_t b[CDENTRYSIZE];
863
50.8k
    zip_buffer_t *buffer;
864
865
50.8k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
866
867
    /* Central header has fixed fields after size pointers. */
868
50.8k
    if ((buffer = _zip_buffer_new_from_source(src, local ? LENTRYSIZE : 34, b, error)) == NULL) {
869
72
        return -1;
870
72
    }
871
50.7k
    if (_zip_buffer_left(buffer) != (local ? LENTRYSIZE : 34)) {
872
0
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_ENTRY_INVALID);
873
0
        _zip_buffer_free(buffer);
874
0
        return -1;
875
0
    }
876
877
50.7k
    if (memcmp(_zip_buffer_peek(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
878
22.8k
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_ENTRY_INVALID);
879
22.8k
        _zip_buffer_free(buffer);
880
22.8k
        return -1;
881
22.8k
    }
882
883
    /* Skip to size pointers. */
884
27.9k
    _zip_buffer_skip(buffer, local ? 26 : 28);
885
886
83.7k
    for (i = 0; i < (local ? 2 : 3); i++) {
887
55.8k
        size += _zip_buffer_get_16(buffer);
888
55.8k
    }
889
890
27.9k
    _zip_buffer_free(buffer);
891
27.9k
    return size;
892
50.7k
}
893
894
895
/* _zip_dirent_write
896
   Writes zip directory entry.
897
898
   If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
899
   directory entry.  If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
900
901
   Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
902
   returned.
903
*/
904
905
67.3k
int _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
906
67.3k
    zip_dostime_t dostime;
907
67.3k
    zip_encoding_type_t com_enc, name_enc;
908
67.3k
    zip_extra_field_t *ef;
909
67.3k
    zip_extra_field_t *ef64;
910
67.3k
    zip_int32_t ef_size, de_ef_size;
911
67.3k
    bool is_zip64;
912
67.3k
    bool is_really_zip64;
913
67.3k
    zip_uint16_t winzip_aes_version;
914
67.3k
    zip_uint8_t buf[CDENTRYSIZE];
915
67.3k
    zip_buffer_t *buffer;
916
917
67.3k
    ef = NULL;
918
919
67.3k
    name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
920
67.3k
    com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
921
922
67.3k
    if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN)) {
923
1.08k
        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
924
1.08k
    }
925
66.2k
    else {
926
66.2k
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
927
66.2k
        if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
928
237
            ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
929
237
            if (ef == NULL) {
930
0
                return -1;
931
0
            }
932
237
        }
933
66.2k
        if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
934
104
            zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
935
104
            if (ef2 == NULL) {
936
0
                _zip_ef_free(ef);
937
0
                return -1;
938
0
            }
939
104
            ef2->next = ef;
940
104
            ef = ef2;
941
104
        }
942
66.2k
    }
943
944
67.3k
    if (de->encryption_method == ZIP_EM_NONE) {
945
35.4k
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
946
35.4k
    }
947
31.9k
    else {
948
31.9k
        de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
949
31.9k
    }
950
951
67.3k
    is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
952
67.3k
    is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
953
67.3k
    if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
954
        /* TODO: WinZip also uses AE-2 for bzip compressed files and maybe others? */
955
26.3k
        if (de->uncomp_size < 20) {
956
7.12k
            winzip_aes_version = 2;
957
7.12k
        }
958
19.1k
        else {
959
19.1k
            winzip_aes_version = 1;
960
19.1k
        }
961
26.3k
    }
962
41.0k
    else {
963
41.0k
        winzip_aes_version = 0;
964
41.0k
    }
965
966
67.3k
    if (is_zip64) {
967
0
        zip_uint8_t ef_zip64[EFZIP64SIZE];
968
0
        zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
969
0
        if (ef_buffer == NULL) {
970
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
971
0
            _zip_ef_free(ef);
972
0
            return -1;
973
0
        }
974
975
0
        if (flags & ZIP_FL_LOCAL) {
976
0
            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
977
0
                _zip_buffer_put_64(ef_buffer, de->uncomp_size);
978
0
                _zip_buffer_put_64(ef_buffer, de->comp_size);
979
0
            }
980
0
        }
981
0
        else {
982
0
            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
983
0
                if (de->uncomp_size >= ZIP_UINT32_MAX) {
984
0
                    _zip_buffer_put_64(ef_buffer, de->uncomp_size);
985
0
                }
986
0
                if (de->comp_size >= ZIP_UINT32_MAX) {
987
0
                    _zip_buffer_put_64(ef_buffer, de->comp_size);
988
0
                }
989
0
                if (de->offset >= ZIP_UINT32_MAX) {
990
0
                    _zip_buffer_put_64(ef_buffer, de->offset);
991
0
                }
992
0
            }
993
0
        }
994
995
0
        if (!_zip_buffer_ok(ef_buffer)) {
996
0
            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
997
0
            _zip_buffer_free(ef_buffer);
998
0
            _zip_ef_free(ef);
999
0
            return -1;
1000
0
        }
1001
1002
0
        ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64);
1003
0
        _zip_buffer_free(ef_buffer);
1004
0
        if (ef64 == NULL) {
1005
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
1006
0
            _zip_ef_free(ef);
1007
0
            return -1;
1008
0
        }
1009
0
        ef64->next = ef;
1010
0
        ef = ef64;
1011
0
    }
1012
1013
67.3k
    if (winzip_aes_version > 0) {
1014
26.3k
        zip_uint8_t data[EF_WINZIP_AES_SIZE];
1015
26.3k
        zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
1016
26.3k
        zip_extra_field_t *ef_winzip;
1017
1018
26.3k
        if (ef_buffer == NULL) {
1019
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
1020
0
            _zip_ef_free(ef);
1021
0
            return -1;
1022
0
        }
1023
1024
26.3k
        _zip_buffer_put_16(ef_buffer, winzip_aes_version);
1025
26.3k
        _zip_buffer_put(ef_buffer, "AE", 2);
1026
26.3k
        _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
1027
26.3k
        _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
1028
1029
26.3k
        if (!_zip_buffer_ok(ef_buffer)) {
1030
0
            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
1031
0
            _zip_buffer_free(ef_buffer);
1032
0
            _zip_ef_free(ef);
1033
0
            return -1;
1034
0
        }
1035
1036
26.3k
        ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data);
1037
26.3k
        _zip_buffer_free(ef_buffer);
1038
26.3k
        if (ef_winzip == NULL) {
1039
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
1040
0
            _zip_ef_free(ef);
1041
0
            return -1;
1042
0
        }
1043
26.3k
        ef_winzip->next = ef;
1044
26.3k
        ef = ef_winzip;
1045
26.3k
    }
1046
1047
67.3k
    if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) {
1048
0
        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
1049
0
        _zip_ef_free(ef);
1050
0
        return -1;
1051
0
    }
1052
1053
67.3k
    _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
1054
1055
67.3k
    if ((flags & ZIP_FL_LOCAL) == 0) {
1056
22.7k
        _zip_buffer_put_16(buffer, de->version_madeby);
1057
22.7k
    }
1058
67.3k
    _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
1059
67.3k
    _zip_buffer_put_16(buffer, de->bitflags);
1060
67.3k
    if (winzip_aes_version > 0) {
1061
26.3k
        _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
1062
26.3k
    }
1063
41.0k
    else {
1064
41.0k
        _zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
1065
41.0k
    }
1066
1067
67.3k
    if (ZIP_WANT_TORRENTZIP(za)) {
1068
0
        dostime.time = 0xbc00;
1069
0
        dostime.date = 0x2198;
1070
0
    }
1071
67.3k
    else {
1072
67.3k
        dostime = de->last_mod;
1073
67.3k
    }
1074
67.3k
    _zip_buffer_put_16(buffer, dostime.time);
1075
67.3k
    _zip_buffer_put_16(buffer, dostime.date);
1076
1077
67.3k
    if (winzip_aes_version == 2) {
1078
7.12k
        _zip_buffer_put_32(buffer, 0);
1079
7.12k
    }
1080
60.2k
    else {
1081
60.2k
        _zip_buffer_put_32(buffer, de->crc);
1082
60.2k
    }
1083
1084
67.3k
    if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
1085
        /* In local headers, if a ZIP64 EF is written, it MUST contain
1086
         * both compressed and uncompressed sizes (even if one of the
1087
         * two is smaller than 0xFFFFFFFF); on the other hand, those
1088
         * may only appear when the corresponding standard entry is
1089
         * 0xFFFFFFFF.  (appnote.txt 4.5.3) */
1090
0
        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1091
0
        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1092
0
    }
1093
67.3k
    else {
1094
67.3k
        if (de->comp_size < ZIP_UINT32_MAX) {
1095
67.3k
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
1096
67.3k
        }
1097
0
        else {
1098
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1099
0
        }
1100
67.3k
        if (de->uncomp_size < ZIP_UINT32_MAX) {
1101
67.3k
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
1102
67.3k
        }
1103
0
        else {
1104
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1105
0
        }
1106
67.3k
    }
1107
1108
67.3k
    _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
1109
1110
67.3k
    ef_size = _zip_ef_size(ef);
1111
67.3k
    if (!ZIP_WANT_TORRENTZIP(za)) {
1112
67.3k
        de_ef_size = _zip_ef_size((flags & ZIP_FL_LOCAL) ? de->extra_fields.local : de->extra_fields.central);
1113
67.3k
    }
1114
0
    else {
1115
0
        de_ef_size = 0;
1116
0
    }
1117
67.3k
    if (ef_size < 0 || de_ef_size < 0 || ef_size + de_ef_size > ZIP_UINT16_MAX) {
1118
0
        zip_error_set(&za->error, ZIP_ER_EF_TOO_LARGE, 0);
1119
0
        _zip_buffer_free(buffer);
1120
0
        _zip_ef_free(ef);
1121
0
        return -1;
1122
0
    }
1123
67.3k
    _zip_buffer_put_16(buffer, (zip_uint16_t)(ef_size + de_ef_size));
1124
1125
67.3k
    if ((flags & ZIP_FL_LOCAL) == 0) {
1126
22.7k
        _zip_buffer_put_16(buffer, ZIP_WANT_TORRENTZIP(za) ? 0 : _zip_string_length(de->comment));
1127
22.7k
        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
1128
22.7k
        _zip_buffer_put_16(buffer, de->int_attrib);
1129
22.7k
        _zip_buffer_put_32(buffer, de->ext_attrib);
1130
22.7k
        if (de->offset < ZIP_UINT32_MAX) {
1131
22.7k
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
1132
22.7k
        }
1133
0
        else {
1134
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1135
0
        }
1136
22.7k
    }
1137
1138
67.3k
    if (!_zip_buffer_ok(buffer)) {
1139
0
        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
1140
0
        _zip_buffer_free(buffer);
1141
0
        _zip_ef_free(ef);
1142
0
        return -1;
1143
0
    }
1144
1145
67.3k
    if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
1146
0
        _zip_buffer_free(buffer);
1147
0
        _zip_ef_free(ef);
1148
0
        return -1;
1149
0
    }
1150
1151
67.3k
    _zip_buffer_free(buffer);
1152
1153
67.3k
    if (de->filename) {
1154
67.3k
        if (_zip_string_write(za, de->filename) < 0) {
1155
0
            _zip_ef_free(ef);
1156
0
            return -1;
1157
0
        }
1158
67.3k
    }
1159
1160
67.3k
    if (ef) {
1161
26.5k
        if (_zip_ef_write(za, ef) < 0) {
1162
0
            _zip_ef_free(ef);
1163
0
            return -1;
1164
0
        }
1165
26.5k
    }
1166
67.3k
    _zip_ef_free(ef);
1167
67.3k
    ef = (flags & ZIP_FL_LOCAL) ? de->extra_fields.local : de->extra_fields.central;
1168
67.3k
    if (ef && !ZIP_WANT_TORRENTZIP(za)) {
1169
1.01k
        if (_zip_ef_write(za, ef) < 0) {
1170
0
            return -1;
1171
0
        }
1172
1.01k
    }
1173
1174
67.3k
    if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) {
1175
22.7k
        if (de->comment) {
1176
3.09k
            if (_zip_string_write(za, de->comment) < 0) {
1177
0
                return -1;
1178
0
            }
1179
3.09k
        }
1180
22.7k
    }
1181
1182
1183
67.3k
    return is_zip64;
1184
67.3k
}
1185
1186
1187
122k
time_t _zip_d2u_time(const zip_dostime_t *dtime) {
1188
122k
    struct tm tm;
1189
1190
122k
    memset(&tm, 0, sizeof(tm));
1191
1192
    /* let mktime decide if DST is in effect */
1193
122k
    tm.tm_isdst = -1;
1194
1195
122k
    tm.tm_year = ((dtime->date >> 9) & 127) + 1980 - 1900;
1196
122k
    tm.tm_mon = ((dtime->date >> 5) & 15) - 1;
1197
122k
    tm.tm_mday = dtime->date & 31;
1198
1199
122k
    tm.tm_hour = (dtime->time >> 11) & 31;
1200
122k
    tm.tm_min = (dtime->time >> 5) & 63;
1201
122k
    tm.tm_sec = (dtime->time << 1) & 62;
1202
1203
122k
    return mktime(&tm);
1204
122k
}
1205
1206
1207
341
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
1208
341
    const zip_uint8_t *raw;
1209
341
    zip_uint32_t len;
1210
341
    zip_buffer_t *buffer;
1211
341
    zip_extra_field_t *ef;
1212
1213
341
    if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
1214
        /* error already set */
1215
0
        return NULL;
1216
0
    }
1217
1218
341
    if (len + 5 > ZIP_UINT16_MAX) {
1219
0
        zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
1220
0
        return NULL;
1221
0
    }
1222
1223
341
    if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) {
1224
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
1225
0
        return NULL;
1226
0
    }
1227
1228
341
    _zip_buffer_put_8(buffer, 1);
1229
341
    _zip_buffer_put_32(buffer, _zip_string_crc32(str));
1230
341
    _zip_buffer_put(buffer, raw, len);
1231
1232
341
    if (!_zip_buffer_ok(buffer)) {
1233
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
1234
0
        _zip_buffer_free(buffer);
1235
0
        return NULL;
1236
0
    }
1237
1238
341
    ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer));
1239
341
    _zip_buffer_free(buffer);
1240
1241
341
    return ef;
1242
341
}
1243
1244
1245
898k
zip_dirent_t *_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
1246
898k
    if (error == NULL) {
1247
217k
        error = &za->error;
1248
217k
    }
1249
1250
898k
    if (idx >= za->nentry) {
1251
0
        zip_error_set(error, ZIP_ER_INVAL, 0);
1252
0
        return NULL;
1253
0
    }
1254
1255
898k
    if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1256
835k
        if (za->entry[idx].orig == NULL) {
1257
396
            zip_error_set(error, ZIP_ER_INVAL, 0);
1258
396
            return NULL;
1259
396
        }
1260
835k
        if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
1261
0
            zip_error_set(error, ZIP_ER_DELETED, 0);
1262
0
            return NULL;
1263
0
        }
1264
835k
        return za->entry[idx].orig;
1265
835k
    }
1266
63.3k
    else {
1267
63.3k
        return za->entry[idx].changes;
1268
63.3k
    }
1269
898k
}
1270
1271
1272
24.5k
int _zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
1273
24.5k
    struct tm *tpm;
1274
24.5k
    struct tm tm;
1275
24.5k
    tpm = zip_localtime(&intime, &tm);
1276
24.5k
    if (tpm == NULL) {
1277
        /* if localtime fails, return an arbitrary date (1980-01-01 00:00:00) */
1278
0
        dtime->date = (1 << 5) + 1;
1279
0
        dtime->time = 0;
1280
0
        if (ze) {
1281
0
            zip_error_set(ze, ZIP_ER_INVAL, errno);
1282
0
        }
1283
0
        return -1;
1284
0
    }
1285
24.5k
    if (tpm->tm_year < 80) {
1286
0
        tpm->tm_year = 80;
1287
0
    }
1288
1289
24.5k
    dtime->date = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
1290
24.5k
    dtime->time = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
1291
1292
24.5k
    return 0;
1293
24.5k
}
1294
1295
1296
45.4k
bool _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
1297
45.4k
    zip_uint16_t length;
1298
45.4k
    bool has_changed = false;
1299
45.4k
    zip_uint16_t version_madeby, version_needed;
1300
1301
45.4k
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
1302
24.6k
        zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
1303
24.6k
        zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
1304
24.6k
        if (de->bitflags != bitflags) {
1305
17.6k
            de->bitflags = bitflags;
1306
17.6k
            has_changed = true;
1307
17.6k
        }
1308
24.6k
    }
1309
45.4k
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
1310
0
        zip_uint16_t int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
1311
0
        if (de->int_attrib != int_attrib) {
1312
0
            de->int_attrib = int_attrib;
1313
0
            has_changed = true;
1314
0
        }
1315
0
    }
1316
    /* manually set attributes are preferred over attributes provided by source */
1317
45.4k
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
1318
0
        if (de->ext_attrib != attributes->external_file_attributes) {
1319
0
            de->ext_attrib = attributes->external_file_attributes;
1320
0
            has_changed = true;
1321
0
        }
1322
0
    }
1323
1324
45.4k
    if (de->comp_method == ZIP_CM_LZMA) {
1325
0
        version_needed = 63;
1326
0
    }
1327
45.4k
    else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
1328
17.5k
        version_needed = 51;
1329
17.5k
    }
1330
27.8k
    else if (de->comp_method == ZIP_CM_BZIP2) {
1331
0
        version_needed = 46;
1332
0
    }
1333
27.8k
    else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1334
0
        version_needed = 45;
1335
0
    }
1336
27.8k
    else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1337
4.99k
        version_needed = 20;
1338
4.99k
    }
1339
22.8k
    else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
1340
14.4k
        version_needed = 20;
1341
14.4k
    }
1342
8.43k
    else {
1343
8.43k
        version_needed = 10;
1344
8.43k
    }
1345
1346
45.4k
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
1347
37.2k
        version_needed = ZIP_MAX(version_needed, attributes->version_needed);
1348
37.2k
    }
1349
1350
45.4k
    if (de->version_needed != version_needed) {
1351
18.6k
        de->version_needed = version_needed;
1352
18.6k
        has_changed = true;
1353
18.6k
    }
1354
1355
45.4k
    version_madeby = 63 | (de->version_madeby & 0xff00);
1356
45.4k
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
1357
0
        version_madeby = (version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
1358
0
    }
1359
45.4k
    if (de->version_madeby != version_madeby) {
1360
0
        de->version_madeby = version_madeby;
1361
0
        has_changed = true;
1362
0
    }
1363
1364
45.4k
    return has_changed;
1365
45.4k
}
1366
1367
1368
/* _zip_dirent_torrent_normalize(de);
1369
   Set values suitable for torrentzip.
1370
*/
1371
1372
0
void zip_dirent_torrentzip_normalize(zip_dirent_t *de) {
1373
0
    de->version_madeby = 0;
1374
0
    de->version_needed = 20; /* 2.0 */
1375
0
    de->bitflags = 2;        /* maximum compression */
1376
0
    de->comp_method = ZIP_CM_DEFLATE;
1377
0
    de->compression_level = TORRENTZIP_COMPRESSION_FLAGS;
1378
0
    de->disk_number = 0;
1379
0
    de->int_attrib = 0;
1380
0
    de->ext_attrib = 0;
1381
1382
    /* last_mod, extra_fields, and comment are normalized in zip_dirent_write() directly */
1383
0
}
1384
1385
0
int zip_dirent_check_consistency(zip_dirent_t *dirent) {
1386
0
    if (dirent->comp_method == ZIP_CM_STORE) {
1387
0
        zip_uint64_t header_size = 0;
1388
0
        switch (dirent->encryption_method) {
1389
0
        case ZIP_EM_NONE:
1390
0
            break;
1391
0
        case ZIP_EM_TRAD_PKWARE:
1392
0
            header_size = 12;
1393
0
            break;
1394
0
        case ZIP_EM_AES_128:
1395
0
            header_size = 20;
1396
0
            break;
1397
0
        case ZIP_EM_AES_192:
1398
0
            header_size = 24;
1399
0
            break;
1400
0
        case ZIP_EM_AES_256:
1401
0
            header_size = 28;
1402
0
            break;
1403
1404
0
        default:
1405
0
            return 0;
1406
0
        }
1407
0
        if (dirent->uncomp_size + header_size < dirent->uncomp_size || dirent->comp_size != dirent->uncomp_size + header_size) {
1408
0
            return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
1409
0
        }
1410
0
    }
1411
0
    return 0;
1412
0
}
1413
1414
122k
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
1415
122k
    if (!de->last_mod_mtime_valid) {
1416
122k
        de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
1417
122k
        de->last_mod_mtime_valid = true;
1418
122k
    }
1419
1420
122k
    return de->last_mod_mtime;
1421
122k
}