Coverage Report

Created: 2026-07-30 07:17

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