Coverage Report

Created: 2026-08-13 06:54

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