Coverage Report

Created: 2026-11-12 06:52

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
110k
void _zip_cdir_free(zip_cdir_t *cd) {
50
110k
    zip_uint64_t i;
51
52
110k
    if (cd == NULL) {
53
0
        return;
54
0
    }
55
56
111M
    for (i = 0; i < cd->nentry; i++) {
57
111M
        _zip_entry_finalize(cd->entry + i);
58
111M
    }
59
110k
    free(cd->entry);
60
110k
    _zip_string_free(cd->comment);
61
110k
    free(cd);
62
110k
}
63
64
65
119k
zip_cdir_t *_zip_cdir_new(zip_error_t *error) {
66
119k
    zip_cdir_t *cd;
67
68
119k
    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
119k
    cd->entry = NULL;
74
119k
    cd->nentry = cd->nentry_alloc = 0;
75
119k
    cd->size = cd->offset = 0;
76
119k
    cd->comment = NULL;
77
119k
    cd->is_zip64 = false;
78
79
119k
    return cd;
80
119k
}
81
82
83
14.1k
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
84
14.1k
    zip_uint64_t i;
85
86
14.1k
    if (additional_entries == 0) {
87
2.04k
        return true;
88
2.04k
    }
89
90
12.0k
    if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
91
0
        return false;
92
0
    }
93
94
111M
    for (i = cd->nentry; i < cd->nentry_alloc; i++) {
95
111M
        _zip_entry_init(cd->entry + i);
96
111M
    }
97
98
12.0k
    cd->nentry = cd->nentry_alloc;
99
100
12.0k
    return true;
101
12.0k
}
102
103
104
5.18k
zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
105
5.18k
    zip_uint64_t offset, size;
106
5.18k
    zip_string_t *comment;
107
5.18k
    zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
108
5.18k
    zip_buffer_t *buffer;
109
5.18k
    zip_int64_t off;
110
5.18k
    zip_uint64_t i;
111
5.18k
    zip_uint32_t cdir_crc;
112
113
5.18k
    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.18k
    offset = (zip_uint64_t)off;
118
119
5.18k
    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
27.6k
    for (i = 0; i < survivors; i++) {
125
22.5k
        zip_entry_t *entry = za->entry + filelist[i].idx;
126
127
22.5k
        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.5k
    }
132
133
5.18k
    za->write_crc = NULL;
134
135
5.18k
    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.18k
    size = (zip_uint64_t)off - offset;
140
141
5.18k
    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.18k
    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.18k
    _zip_buffer_put(buffer, EOCD_MAGIC, 4);
164
5.18k
    _zip_buffer_put_32(buffer, 0);
165
5.18k
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
166
5.18k
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
167
5.18k
    _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
168
5.18k
    _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset);
169
170
5.18k
    comment = za->comment_changed ? za->comment_changes : za->comment_orig;
171
172
5.18k
    if (ZIP_WANT_TORRENTZIP(za)) {
173
0
        _zip_buffer_put_16(buffer, TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH);
174
0
    }
175
5.18k
    else {
176
5.18k
        _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
177
5.18k
    }
178
179
180
5.18k
    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.18k
    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.18k
    _zip_buffer_free(buffer);
192
193
5.18k
    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.18k
    else if (comment != NULL) {
202
499
        if (_zip_write(za, comment->raw, comment->length) < 0) {
203
0
            return -1;
204
0
        }
205
499
    }
206
207
5.18k
    return (zip_int64_t)size;
208
5.18k
}
209
210
211
22.8k
zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *sde) {
212
22.8k
    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
22.8k
    if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL) {
220
0
        return NULL;
221
0
    }
222
223
22.8k
    if (sde) {
224
0
        (void)memcpy_s(tde, sizeof(*tde), sde, sizeof(*sde));
225
0
    }
226
22.8k
    else {
227
22.8k
        _zip_dirent_init(tde);
228
22.8k
    }
229
230
22.8k
    tde->changed = 0;
231
22.8k
    tde->cloned = 1;
232
233
22.8k
    return tde;
234
22.8k
}
235
236
237
334k
void _zip_dirent_finalize(zip_dirent_t *zde) {
238
334k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
239
334k
        _zip_string_free(zde->filename);
240
334k
        zde->filename = NULL;
241
334k
    }
242
334k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
243
334k
        _zip_extra_fields_fini(&zde->extra_fields);
244
334k
    }
245
334k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
246
314k
        _zip_string_free(zde->comment);
247
314k
        zde->comment = NULL;
248
314k
    }
249
334k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
250
328k
        if (zde->password) {
251
16.2k
            _zip_crypto_clear(zde->password, strlen(zde->password));
252
16.2k
        }
253
328k
        free(zde->password);
254
328k
        zde->password = NULL;
255
328k
    }
256
334k
}
257
258
259
222M
void _zip_dirent_free(zip_dirent_t *zde) {
260
222M
    if (zde == NULL) {
261
222M
        return;
262
222M
    }
263
264
334k
    _zip_dirent_finalize(zde);
265
334k
    free(zde);
266
334k
}
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
645k
void _zip_dirent_init(zip_dirent_t *de) {
318
645k
    de->changed = 0;
319
645k
    de->local_extra_fields_read = 0;
320
645k
    de->cloned = 0;
321
322
645k
    de->crc_valid = true;
323
645k
    de->last_mod_mtime_valid = false;
324
645k
    de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
325
645k
    de->version_needed = 10; /* 1.0 */
326
645k
    de->bitflags = 0;
327
645k
    de->comp_method = ZIP_CM_DEFAULT;
328
645k
    de->last_mod.date = 0;
329
645k
    de->last_mod.time = 0;
330
645k
    de->crc = 0;
331
645k
    de->comp_size = 0;
332
645k
    de->uncomp_size = 0;
333
645k
    de->filename = NULL;
334
645k
    _zip_extra_fields_init(&de->extra_fields);
335
645k
    de->comment = NULL;
336
645k
    de->disk_number = 0;
337
645k
    de->int_attrib = 0;
338
645k
    de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
339
645k
    de->offset = 0;
340
645k
    de->compression_level = 0;
341
645k
    de->encryption_method = ZIP_EM_NONE;
342
645k
    de->password = NULL;
343
645k
}
344
345
346
93.0k
bool _zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) {
347
93.0k
    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
93.0k
    return false;
352
93.0k
}
353
354
355
311k
zip_dirent_t *_zip_dirent_new(void) {
356
311k
    zip_dirent_t *de;
357
358
311k
    if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL) {
359
0
        return NULL;
360
0
    }
361
362
311k
    _zip_dirent_init(de);
363
311k
    return de;
364
311k
}
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
311k
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
311k
    zip_uint8_t buf[CDENTRYSIZE];
379
311k
    zip_uint32_t size, variable_size;
380
311k
    zip_uint16_t filename_len, comment_len, ef_len;
381
311k
    zip_string_t *utf8_string;
382
311k
    zip_extra_field_t **efp;
383
384
311k
    bool from_buffer = (buffer != NULL);
385
386
311k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
387
388
311k
    if (buffer) {
389
148k
        if (_zip_buffer_left(buffer) < size) {
390
385
            zip_error_set(error, ZIP_ER_NOZIP, 0);
391
385
            return -1;
392
385
        }
393
148k
    }
394
163k
    else {
395
163k
        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
396
35
            return -1;
397
35
        }
398
163k
    }
399
400
311k
    if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
401
315
        zip_error_set(error, ZIP_ER_NOZIP, 0);
402
315
        if (!from_buffer) {
403
110
            _zip_buffer_free(buffer);
404
110
        }
405
315
        return -1;
406
315
    }
407
408
    /* convert buffercontents to zip_dirent */
409
410
311k
    _zip_dirent_init(zde);
411
311k
    if (!local) {
412
311k
        zde->version_madeby = _zip_buffer_get_16(buffer);
413
311k
    }
414
0
    else {
415
0
        zde->version_madeby = 0;
416
0
    }
417
311k
    zde->version_needed = _zip_buffer_get_16(buffer);
418
311k
    zde->bitflags = _zip_buffer_get_16(buffer);
419
311k
    zde->comp_method = _zip_buffer_get_16(buffer);
420
421
    /* convert to time_t */
422
311k
    zde->last_mod.time = _zip_buffer_get_16(buffer);
423
311k
    zde->last_mod.date = _zip_buffer_get_16(buffer);
424
425
311k
    zde->crc = _zip_buffer_get_32(buffer);
426
311k
    zde->comp_size = _zip_buffer_get_32(buffer);
427
311k
    zde->uncomp_size = _zip_buffer_get_32(buffer);
428
429
311k
    filename_len = _zip_buffer_get_16(buffer);
430
311k
    ef_len = _zip_buffer_get_16(buffer);
431
432
311k
    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
311k
    else {
440
311k
        comment_len = _zip_buffer_get_16(buffer);
441
311k
        zde->disk_number = _zip_buffer_get_16(buffer);
442
311k
        zde->int_attrib = _zip_buffer_get_16(buffer);
443
311k
        zde->ext_attrib = _zip_buffer_get_32(buffer);
444
311k
        zde->offset = _zip_buffer_get_32(buffer);
445
311k
    }
446
447
311k
    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
311k
    if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
456
58.2k
        if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
457
            /* TODO */
458
26.7k
            zde->encryption_method = ZIP_EM_UNKNOWN;
459
26.7k
        }
460
31.5k
        else {
461
31.5k
            zde->encryption_method = ZIP_EM_TRAD_PKWARE;
462
31.5k
        }
463
58.2k
    }
464
252k
    else {
465
252k
        zde->encryption_method = ZIP_EM_NONE;
466
252k
    }
467
468
311k
    zde->filename = NULL;
469
311k
    _zip_extra_fields_init(&zde->extra_fields);
470
311k
    zde->comment = NULL;
471
472
311k
    variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
473
474
311k
    if (from_buffer) {
475
148k
        if (_zip_buffer_left(buffer) < variable_size) {
476
220
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
477
220
            return -1;
478
220
        }
479
148k
    }
480
162k
    else {
481
162k
        _zip_buffer_free(buffer);
482
483
162k
        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
484
68
            return -1;
485
68
        }
486
162k
    }
487
488
310k
    if (filename_len) {
489
173k
        zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
490
173k
        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
173k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
501
13.7k
            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
502
84
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME);
503
84
                if (!from_buffer) {
504
22
                    _zip_buffer_free(buffer);
505
22
                }
506
84
                return -1;
507
84
            }
508
13.7k
        }
509
173k
    }
510
511
310k
    if (ef_len) {
512
84.3k
        zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
513
514
84.3k
        if (ef == NULL) {
515
0
            if (!from_buffer) {
516
0
                _zip_buffer_free(buffer);
517
0
            }
518
0
            return -1;
519
0
        }
520
84.3k
        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
362
            free(ef);
522
362
            if (!from_buffer) {
523
59
                _zip_buffer_free(buffer);
524
59
            }
525
362
            return -1;
526
362
        }
527
84.0k
        free(ef);
528
84.0k
        if (local) {
529
0
            zde->local_extra_fields_read = 1;
530
0
        }
531
84.0k
    }
532
533
310k
    if (comment_len) {
534
16.1k
        zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
535
16.1k
        if (zde->comment == NULL) {
536
0
            if (!from_buffer) {
537
0
                _zip_buffer_free(buffer);
538
0
            }
539
0
            return -1;
540
0
        }
541
16.1k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
542
6.02k
            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
14
                    _zip_buffer_free(buffer);
546
14
                }
547
64
                return -1;
548
64
            }
549
6.02k
        }
550
16.1k
    }
551
552
310k
    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
310k
    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
310k
    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
310k
    if (!local) {
578
310k
        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
310k
        zde->comment = utf8_string;
586
310k
    }
587
588
    /* Zip64 */
589
590
310k
    if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
591
22.4k
        zip_uint16_t got_len;
592
22.4k
        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
22.4k
        if (ef != NULL) {
594
7.73k
            if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) {
595
1.49k
                if (!from_buffer) {
596
13
                    _zip_buffer_free(buffer);
597
13
                }
598
1.49k
                return -1;
599
1.49k
            }
600
7.73k
        }
601
14.7k
        else if (is_zip64) {
602
4
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_MISSING_ZIP64_EF);
603
4
            if (!from_buffer) {
604
2
                _zip_buffer_free(buffer);
605
2
            }
606
4
            return -1;
607
4
        }
608
22.4k
    }
609
610
611
308k
    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
308k
    if (!from_buffer) {
620
162k
        _zip_buffer_free(buffer);
621
162k
    }
622
623
308k
    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
308k
    if (zde->offset > ZIP_INT64_MAX) {
656
273
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
657
273
        return -1;
658
273
    }
659
660
308k
    if (!_zip_dirent_process_winzip_aes(zde, error)) {
661
195
        return -1;
662
195
    }
663
664
308k
    efp = local ? &zde->extra_fields.local : &zde->extra_fields.central;
665
308k
    *efp = _zip_ef_remove_internal(*efp);
666
667
308k
    return (zip_int64_t)size + (zip_int64_t)variable_size;
668
308k
}
669
670
7.73k
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.73k
    zip_buffer_t *ef_buffer;
672
673
7.73k
    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.73k
    if (zde->uncomp_size == ZIP_UINT32_MAX) {
679
4.65k
        zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
680
4.65k
    }
681
3.08k
    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.73k
    if (zde->comp_size == ZIP_UINT32_MAX) {
687
4.46k
        zde->comp_size = _zip_buffer_get_64(ef_buffer);
688
4.46k
    }
689
3.27k
    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.73k
    if (!local) {
695
7.73k
        if (zde->offset == ZIP_UINT32_MAX) {
696
2.51k
            zde->offset = _zip_buffer_get_64(ef_buffer);
697
2.51k
        }
698
7.73k
        if (zde->disk_number == ZIP_UINT16_MAX) {
699
898
            zde->disk_number = _zip_buffer_get_32(ef_buffer);
700
898
        }
701
7.73k
    }
702
703
7.73k
    if (!_zip_buffer_eof(ef_buffer)) {
704
        /* accept additional fields if values match */
705
3.12k
        bool ok = true;
706
3.12k
        switch (got_len) {
707
2.18k
        case 28:
708
2.18k
            _zip_buffer_set_offset(ef_buffer, 24);
709
2.18k
            if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
710
1.08k
                ok = false;
711
1.08k
            }
712
            /* fallthrough */
713
2.77k
        case 24:
714
2.77k
            _zip_buffer_set_offset(ef_buffer, 0);
715
2.77k
            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.15k
                ok = false;
717
1.15k
            }
718
2.77k
            break;
719
720
347
        default:
721
347
            ok = false;
722
3.12k
        }
723
3.12k
        if (!ok) {
724
1.49k
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
725
1.49k
            _zip_buffer_free(ef_buffer);
726
1.49k
            return false;
727
1.49k
        }
728
3.12k
    }
729
6.24k
    _zip_buffer_free(ef_buffer);
730
731
6.24k
    return true;
732
7.73k
}
733
734
735
620k
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
620k
    zip_uint16_t ef_len;
737
620k
    zip_uint32_t ef_crc;
738
620k
    zip_buffer_t *buffer;
739
740
620k
    const zip_uint8_t *ef = _zip_extra_fields_get_by_id(&de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
741
742
620k
    if (ef == NULL || ef_len < 5 || ef[0] != 1) {
743
598k
        return str;
744
598k
    }
745
746
22.5k
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
747
0
        return str;
748
0
    }
749
750
22.5k
    _zip_buffer_get_8(buffer);
751
22.5k
    ef_crc = _zip_buffer_get_32(buffer);
752
753
22.5k
    if (_zip_string_crc32(str) == ef_crc) {
754
18.8k
        zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
755
18.8k
        zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
756
757
18.8k
        if (ef_str != NULL) {
758
4.80k
            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
4.80k
            _zip_string_free(str);
767
4.80k
            str = ef_str;
768
4.80k
        }
769
18.8k
    }
770
771
22.5k
    _zip_buffer_free(buffer);
772
773
22.5k
    return str;
774
22.5k
}
775
776
777
308k
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
778
308k
    zip_uint16_t ef_len;
779
308k
    zip_buffer_t *buffer;
780
308k
    const zip_uint8_t *ef;
781
308k
    bool crc_valid;
782
308k
    zip_uint16_t enc_method;
783
784
785
308k
    if (de->comp_method != ZIP_CM_WINZIP_AES) {
786
296k
        return true;
787
296k
    }
788
789
11.6k
    ef = _zip_extra_fields_get_by_id(&de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
790
791
11.6k
    if (ef == NULL || ef_len < 7) {
792
50
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
793
50
        return false;
794
50
    }
795
796
11.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
11.6k
    crc_valid = true;
804
11.6k
    switch (_zip_buffer_get_16(buffer)) {
805
8.35k
    case 1:
806
8.35k
        break;
807
808
3.24k
    case 2:
809
3.24k
        crc_valid = false;
810
        /* TODO: When checking consistency, check that crc is 0. */
811
3.24k
        break;
812
813
9
    default:
814
9
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
815
9
        _zip_buffer_free(buffer);
816
9
        return false;
817
11.6k
    }
818
819
    /* vendor */
820
11.6k
    if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
821
101
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
822
101
        _zip_buffer_free(buffer);
823
101
        return false;
824
101
    }
825
826
    /* mode */
827
11.5k
    switch (_zip_buffer_get_8(buffer)) {
828
3.40k
    case 1:
829
3.40k
        enc_method = ZIP_EM_AES_128;
830
3.40k
        break;
831
84
    case 2:
832
84
        enc_method = ZIP_EM_AES_192;
833
84
        break;
834
7.99k
    case 3:
835
7.99k
        enc_method = ZIP_EM_AES_256;
836
7.99k
        break;
837
24
    default:
838
24
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
839
24
        _zip_buffer_free(buffer);
840
24
        return false;
841
11.5k
    }
842
843
11.4k
    if (ef_len != 7) {
844
11
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
845
11
        _zip_buffer_free(buffer);
846
11
        return false;
847
11
    }
848
849
11.4k
    de->crc_valid = crc_valid;
850
11.4k
    de->encryption_method = enc_method;
851
11.4k
    de->comp_method = _zip_buffer_get_16(buffer);
852
853
11.4k
    _zip_buffer_free(buffer);
854
11.4k
    return true;
855
11.4k
}
856
857
858
55.6k
zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
859
55.6k
    zip_int32_t size;
860
55.6k
    bool local = (flags & ZIP_EF_LOCAL) != 0;
861
55.6k
    int i;
862
55.6k
    zip_uint8_t b[CDENTRYSIZE];
863
55.6k
    zip_buffer_t *buffer;
864
865
55.6k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
866
867
    /* Central header has fixed fields after size pointers. */
868
55.6k
    if ((buffer = _zip_buffer_new_from_source(src, local ? LENTRYSIZE : 34, b, error)) == NULL) {
869
93
        return -1;
870
93
    }
871
55.5k
    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
55.5k
    if (memcmp(_zip_buffer_peek(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
878
23.0k
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_ENTRY_INVALID);
879
23.0k
        _zip_buffer_free(buffer);
880
23.0k
        return -1;
881
23.0k
    }
882
883
    /* Skip to size pointers. */
884
32.4k
    _zip_buffer_skip(buffer, local ? 26 : 28);
885
886
97.3k
    for (i = 0; i < (local ? 2 : 3); i++) {
887
64.9k
        size += _zip_buffer_get_16(buffer);
888
64.9k
    }
889
890
32.4k
    _zip_buffer_free(buffer);
891
32.4k
    return size;
892
55.5k
}
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
66.7k
int _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
906
66.7k
    zip_dostime_t dostime;
907
66.7k
    zip_encoding_type_t com_enc, name_enc;
908
66.7k
    zip_extra_field_t *ef;
909
66.7k
    zip_extra_field_t *ef64;
910
66.7k
    zip_int32_t ef_size, de_ef_size;
911
66.7k
    bool is_zip64;
912
66.7k
    bool is_really_zip64;
913
66.7k
    zip_uint16_t winzip_aes_version;
914
66.7k
    zip_uint8_t buf[CDENTRYSIZE];
915
66.7k
    zip_buffer_t *buffer;
916
917
66.7k
    ef = NULL;
918
919
66.7k
    name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
920
66.7k
    com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
921
922
66.7k
    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.06k
        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
924
1.06k
    }
925
65.6k
    else {
926
65.6k
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
927
65.6k
        if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
928
228
            ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
929
228
            if (ef == NULL) {
930
0
                return -1;
931
0
            }
932
228
        }
933
65.6k
        if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
934
109
            zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
935
109
            if (ef2 == NULL) {
936
0
                _zip_ef_free(ef);
937
0
                return -1;
938
0
            }
939
109
            ef2->next = ef;
940
109
            ef = ef2;
941
109
        }
942
65.6k
    }
943
944
66.7k
    if (de->encryption_method == ZIP_EM_NONE) {
945
32.9k
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
946
32.9k
    }
947
33.7k
    else {
948
33.7k
        de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
949
33.7k
    }
950
951
66.7k
    is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
952
66.7k
    is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
953
66.7k
    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
27.9k
        if (de->uncomp_size < 20) {
956
7.34k
            winzip_aes_version = 2;
957
7.34k
        }
958
20.6k
        else {
959
20.6k
            winzip_aes_version = 1;
960
20.6k
        }
961
27.9k
    }
962
38.7k
    else {
963
38.7k
        winzip_aes_version = 0;
964
38.7k
    }
965
966
66.7k
    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
66.7k
    if (winzip_aes_version > 0) {
1014
27.9k
        zip_uint8_t data[EF_WINZIP_AES_SIZE];
1015
27.9k
        zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
1016
27.9k
        zip_extra_field_t *ef_winzip;
1017
1018
27.9k
        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
27.9k
        _zip_buffer_put_16(ef_buffer, winzip_aes_version);
1025
27.9k
        _zip_buffer_put(ef_buffer, "AE", 2);
1026
27.9k
        _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
1027
27.9k
        _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
1028
1029
27.9k
        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
27.9k
        ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data);
1037
27.9k
        _zip_buffer_free(ef_buffer);
1038
27.9k
        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
27.9k
        ef_winzip->next = ef;
1044
27.9k
        ef = ef_winzip;
1045
27.9k
    }
1046
1047
66.7k
    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
66.7k
    _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
1054
1055
66.7k
    if ((flags & ZIP_FL_LOCAL) == 0) {
1056
22.5k
        _zip_buffer_put_16(buffer, de->version_madeby);
1057
22.5k
    }
1058
66.7k
    _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
1059
66.7k
    _zip_buffer_put_16(buffer, de->bitflags);
1060
66.7k
    if (winzip_aes_version > 0) {
1061
27.9k
        _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
1062
27.9k
    }
1063
38.7k
    else {
1064
38.7k
        _zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
1065
38.7k
    }
1066
1067
66.7k
    if (ZIP_WANT_TORRENTZIP(za)) {
1068
0
        dostime.time = 0xbc00;
1069
0
        dostime.date = 0x2198;
1070
0
    }
1071
66.7k
    else {
1072
66.7k
        dostime = de->last_mod;
1073
66.7k
    }
1074
66.7k
    _zip_buffer_put_16(buffer, dostime.time);
1075
66.7k
    _zip_buffer_put_16(buffer, dostime.date);
1076
1077
66.7k
    if (winzip_aes_version == 2) {
1078
7.34k
        _zip_buffer_put_32(buffer, 0);
1079
7.34k
    }
1080
59.3k
    else {
1081
59.3k
        _zip_buffer_put_32(buffer, de->crc);
1082
59.3k
    }
1083
1084
66.7k
    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
66.7k
    else {
1094
66.7k
        if (de->comp_size < ZIP_UINT32_MAX) {
1095
66.7k
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
1096
66.7k
        }
1097
0
        else {
1098
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1099
0
        }
1100
66.7k
        if (de->uncomp_size < ZIP_UINT32_MAX) {
1101
66.7k
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
1102
66.7k
        }
1103
0
        else {
1104
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1105
0
        }
1106
66.7k
    }
1107
1108
66.7k
    _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
1109
1110
66.7k
    ef_size = _zip_ef_size(ef);
1111
66.7k
    if (!ZIP_WANT_TORRENTZIP(za)) {
1112
66.7k
        de_ef_size = _zip_ef_size((flags & ZIP_FL_LOCAL) ? de->extra_fields.local : de->extra_fields.central);
1113
66.7k
    }
1114
0
    else {
1115
0
        de_ef_size = 0;
1116
0
    }
1117
66.7k
    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
66.7k
    _zip_buffer_put_16(buffer, (zip_uint16_t)(ef_size + de_ef_size));
1124
1125
66.7k
    if ((flags & ZIP_FL_LOCAL) == 0) {
1126
22.5k
        _zip_buffer_put_16(buffer, ZIP_WANT_TORRENTZIP(za) ? 0 : _zip_string_length(de->comment));
1127
22.5k
        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
1128
22.5k
        _zip_buffer_put_16(buffer, de->int_attrib);
1129
22.5k
        _zip_buffer_put_32(buffer, de->ext_attrib);
1130
22.5k
        if (de->offset < ZIP_UINT32_MAX) {
1131
22.5k
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
1132
22.5k
        }
1133
0
        else {
1134
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1135
0
        }
1136
22.5k
    }
1137
1138
66.7k
    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
66.7k
    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
66.7k
    _zip_buffer_free(buffer);
1152
1153
66.7k
    if (de->filename) {
1154
66.7k
        if (_zip_string_write(za, de->filename) < 0) {
1155
0
            _zip_ef_free(ef);
1156
0
            return -1;
1157
0
        }
1158
66.7k
    }
1159
1160
66.7k
    if (ef) {
1161
28.2k
        if (_zip_ef_write(za, ef) < 0) {
1162
0
            _zip_ef_free(ef);
1163
0
            return -1;
1164
0
        }
1165
28.2k
    }
1166
66.7k
    _zip_ef_free(ef);
1167
66.7k
    ef = (flags & ZIP_FL_LOCAL) ? de->extra_fields.local : de->extra_fields.central;
1168
66.7k
    if (ef && !ZIP_WANT_TORRENTZIP(za)) {
1169
1.14k
        if (_zip_ef_write(za, ef) < 0) {
1170
0
            return -1;
1171
0
        }
1172
1.14k
    }
1173
1174
66.7k
    if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) {
1175
22.5k
        if (de->comment) {
1176
3.06k
            if (_zip_string_write(za, de->comment) < 0) {
1177
0
                return -1;
1178
0
            }
1179
3.06k
        }
1180
22.5k
    }
1181
1182
1183
66.7k
    return is_zip64;
1184
66.7k
}
1185
1186
1187
152k
time_t _zip_d2u_time(const zip_dostime_t *dtime) {
1188
152k
    struct tm tm;
1189
1190
152k
    memset(&tm, 0, sizeof(tm));
1191
1192
    /* let mktime decide if DST is in effect */
1193
152k
    tm.tm_isdst = -1;
1194
1195
152k
    tm.tm_year = ((dtime->date >> 9) & 127) + 1980 - 1900;
1196
152k
    tm.tm_mon = ((dtime->date >> 5) & 15) - 1;
1197
152k
    tm.tm_mday = dtime->date & 31;
1198
1199
152k
    tm.tm_hour = (dtime->time >> 11) & 31;
1200
152k
    tm.tm_min = (dtime->time >> 5) & 63;
1201
152k
    tm.tm_sec = (dtime->time << 1) & 62;
1202
1203
152k
    return mktime(&tm);
1204
152k
}
1205
1206
1207
337
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
1208
337
    const zip_uint8_t *raw;
1209
337
    zip_uint32_t len;
1210
337
    zip_buffer_t *buffer;
1211
337
    zip_extra_field_t *ef;
1212
1213
337
    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
337
    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
337
    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
337
    _zip_buffer_put_8(buffer, 1);
1229
337
    _zip_buffer_put_32(buffer, _zip_string_crc32(str));
1230
337
    _zip_buffer_put(buffer, raw, len);
1231
1232
337
    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
337
    ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer));
1239
337
    _zip_buffer_free(buffer);
1240
1241
337
    return ef;
1242
337
}
1243
1244
1245
1.33M
zip_dirent_t *_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
1246
1.33M
    if (error == NULL) {
1247
296k
        error = &za->error;
1248
296k
    }
1249
1250
1.33M
    if (idx >= za->nentry) {
1251
0
        zip_error_set(error, ZIP_ER_INVAL, 0);
1252
0
        return NULL;
1253
0
    }
1254
1255
1.33M
    if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1256
1.26M
        if (za->entry[idx].orig == NULL) {
1257
414
            zip_error_set(error, ZIP_ER_INVAL, 0);
1258
414
            return NULL;
1259
414
        }
1260
1.26M
        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
1.26M
        return za->entry[idx].orig;
1265
1.26M
    }
1266
62.0k
    else {
1267
62.0k
        return za->entry[idx].changes;
1268
62.0k
    }
1269
1.33M
}
1270
1271
1272
24.4k
int _zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
1273
24.4k
    struct tm *tpm;
1274
24.4k
    struct tm tm;
1275
24.4k
    tpm = zip_localtime(&intime, &tm);
1276
24.4k
    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.4k
    if (tpm->tm_year < 80) {
1286
        /* earliest time in DOS format: 1980-01-01 00:00:00 */
1287
0
        dtime->date = (1 << 5) + 1;
1288
0
        dtime->time = 0;
1289
0
        return 0;
1290
0
    }
1291
24.4k
    if (tpm->tm_year > 207) {
1292
        /* latest time in DOS format: 2107-12-31 23:59:58 */
1293
0
        dtime->date = (127 << 9) + (12 << 5) + 31;
1294
0
        dtime->time = (23 << 11) + (59 << 5) + 29;
1295
0
        return 0;
1296
0
    }
1297
1298
24.4k
    dtime->date = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
1299
24.4k
    dtime->time = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
1300
1301
24.4k
    return 0;
1302
24.4k
}
1303
1304
1305
45.0k
bool _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
1306
45.0k
    zip_uint16_t length;
1307
45.0k
    bool has_changed = false;
1308
45.0k
    zip_uint16_t version_madeby, version_needed;
1309
1310
45.0k
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
1311
23.2k
        zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
1312
23.2k
        zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
1313
23.2k
        if (de->bitflags != bitflags) {
1314
16.0k
            de->bitflags = bitflags;
1315
16.0k
            has_changed = true;
1316
16.0k
        }
1317
23.2k
    }
1318
45.0k
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
1319
0
        zip_uint16_t int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
1320
0
        if (de->int_attrib != int_attrib) {
1321
0
            de->int_attrib = int_attrib;
1322
0
            has_changed = true;
1323
0
        }
1324
0
    }
1325
    /* manually set attributes are preferred over attributes provided by source */
1326
45.0k
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
1327
0
        if (de->ext_attrib != attributes->external_file_attributes) {
1328
0
            de->ext_attrib = attributes->external_file_attributes;
1329
0
            has_changed = true;
1330
0
        }
1331
0
    }
1332
1333
45.0k
    if (de->comp_method == ZIP_CM_LZMA) {
1334
0
        version_needed = 63;
1335
0
    }
1336
45.0k
    else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
1337
18.6k
        version_needed = 51;
1338
18.6k
    }
1339
26.3k
    else if (de->comp_method == ZIP_CM_BZIP2) {
1340
0
        version_needed = 46;
1341
0
    }
1342
26.3k
    else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1343
0
        version_needed = 45;
1344
0
    }
1345
26.3k
    else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1346
5.04k
        version_needed = 20;
1347
5.04k
    }
1348
21.3k
    else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
1349
12.8k
        version_needed = 20;
1350
12.8k
    }
1351
8.41k
    else {
1352
8.41k
        version_needed = 10;
1353
8.41k
    }
1354
1355
45.0k
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
1356
36.7k
        version_needed = ZIP_MAX(version_needed, attributes->version_needed);
1357
36.7k
    }
1358
1359
45.0k
    if (de->version_needed != version_needed) {
1360
18.3k
        de->version_needed = version_needed;
1361
18.3k
        has_changed = true;
1362
18.3k
    }
1363
1364
45.0k
    version_madeby = 63 | (de->version_madeby & 0xff00);
1365
45.0k
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
1366
0
        version_madeby = (version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
1367
0
    }
1368
45.0k
    if (de->version_madeby != version_madeby) {
1369
0
        de->version_madeby = version_madeby;
1370
0
        has_changed = true;
1371
0
    }
1372
1373
45.0k
    return has_changed;
1374
45.0k
}
1375
1376
1377
/* _zip_dirent_torrent_normalize(de);
1378
   Set values suitable for torrentzip.
1379
*/
1380
1381
0
void zip_dirent_torrentzip_normalize(zip_dirent_t *de) {
1382
0
    de->version_madeby = 0;
1383
0
    de->version_needed = 20; /* 2.0 */
1384
0
    de->bitflags = 2;        /* maximum compression */
1385
0
    de->comp_method = ZIP_CM_DEFLATE;
1386
0
    de->compression_level = TORRENTZIP_COMPRESSION_FLAGS;
1387
0
    de->disk_number = 0;
1388
0
    de->int_attrib = 0;
1389
0
    de->ext_attrib = 0;
1390
1391
    /* last_mod, extra_fields, and comment are normalized in zip_dirent_write() directly */
1392
0
}
1393
1394
0
int zip_dirent_check_consistency(zip_dirent_t *dirent) {
1395
    /* libzip doesn't support multi-disk archives, so disk_number must be 0. */
1396
0
    if (dirent->disk_number != 0) {
1397
0
        return ZIP_ER_DETAIL_INVALID_DISK_NUMBER;
1398
0
    }
1399
0
    if (dirent->comp_method == ZIP_CM_STORE) {
1400
0
        zip_uint64_t header_size = 0;
1401
0
        switch (dirent->encryption_method) {
1402
0
        case ZIP_EM_NONE:
1403
0
            break;
1404
0
        case ZIP_EM_TRAD_PKWARE:
1405
0
            header_size = 12;
1406
0
            break;
1407
0
        case ZIP_EM_AES_128:
1408
0
            header_size = 20;
1409
0
            break;
1410
0
        case ZIP_EM_AES_192:
1411
0
            header_size = 24;
1412
0
            break;
1413
0
        case ZIP_EM_AES_256:
1414
0
            header_size = 28;
1415
0
            break;
1416
1417
0
        default:
1418
0
            return 0;
1419
0
        }
1420
0
        if (dirent->uncomp_size + header_size < dirent->uncomp_size || dirent->comp_size != dirent->uncomp_size + header_size) {
1421
0
            return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
1422
0
        }
1423
0
    }
1424
0
    return 0;
1425
0
}
1426
1427
152k
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
1428
152k
    if (!de->last_mod_mtime_valid) {
1429
152k
        de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
1430
152k
        de->last_mod_mtime_valid = true;
1431
152k
    }
1432
1433
152k
    return de->last_mod_mtime;
1434
152k
}