Coverage Report

Created: 2026-08-11 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libzip/lib/zip_dirent.c
Line
Count
Source
1
/*
2
  zip_dirent.c -- read directory entry (local or central), clean dirent
3
  Copyright (C) 1999-2025 Dieter Baron and Thomas Klausner
4
5
  This file is part of libzip, a library to manipulate ZIP archives.
6
  The authors can be contacted at <info@libzip.org>
7
8
  Redistribution and use in source and binary forms, with or without
9
  modification, are permitted provided that the following conditions
10
  are met:
11
  1. Redistributions of source code must retain the above copyright
12
     notice, this list of conditions and the following disclaimer.
13
  2. Redistributions in binary form must reproduce the above copyright
14
     notice, this list of conditions and the following disclaimer in
15
     the documentation and/or other materials provided with the
16
     distribution.
17
  3. The names of the authors may not be used to endorse or promote
18
     products derived from this software without specific prior
19
     written permission.
20
21
  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22
  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29
  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31
  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
*/
33
34
#include "zipint.h"
35
36
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <sys/types.h>
41
#include <time.h>
42
#include <zlib.h>
43
44
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str, bool check_consistency);
45
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
46
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error);
47
48
49
41.3k
void _zip_cdir_free(zip_cdir_t *cd) {
50
41.3k
    zip_uint64_t i;
51
52
41.3k
    if (cd == NULL) {
53
0
        return;
54
0
    }
55
56
9.71M
    for (i = 0; i < cd->nentry; i++) {
57
9.67M
        _zip_entry_finalize(cd->entry + i);
58
9.67M
    }
59
41.3k
    free(cd->entry);
60
41.3k
    _zip_string_free(cd->comment);
61
41.3k
    free(cd);
62
41.3k
}
63
64
65
45.5k
zip_cdir_t *_zip_cdir_new(zip_error_t *error) {
66
45.5k
    zip_cdir_t *cd;
67
68
45.5k
    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
45.5k
    cd->entry = NULL;
74
45.5k
    cd->nentry = cd->nentry_alloc = 0;
75
45.5k
    cd->size = cd->offset = 0;
76
45.5k
    cd->comment = NULL;
77
45.5k
    cd->is_zip64 = false;
78
79
45.5k
    return cd;
80
45.5k
}
81
82
83
5.14k
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
84
5.14k
    zip_uint64_t i;
85
86
5.14k
    if (additional_entries == 0) {
87
190
        return true;
88
190
    }
89
90
4.95k
    if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
91
0
        return false;
92
0
    }
93
94
9.70M
    for (i = cd->nentry; i < cd->nentry_alloc; i++) {
95
9.69M
        _zip_entry_init(cd->entry + i);
96
9.69M
    }
97
98
4.95k
    cd->nentry = cd->nentry_alloc;
99
100
4.95k
    return true;
101
4.95k
}
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
27.8k
void _zip_dirent_finalize(zip_dirent_t *zde) {
233
27.8k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
234
27.8k
        _zip_string_free(zde->filename);
235
27.8k
        zde->filename = NULL;
236
27.8k
    }
237
27.8k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
238
27.8k
        _zip_ef_free(zde->extra_fields);
239
27.8k
        zde->extra_fields = NULL;
240
27.8k
    }
241
27.8k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
242
27.8k
        _zip_string_free(zde->comment);
243
27.8k
        zde->comment = NULL;
244
27.8k
    }
245
27.8k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
246
27.8k
        if (zde->password) {
247
0
            _zip_crypto_clear(zde->password, strlen(zde->password));
248
0
        }
249
27.8k
        free(zde->password);
250
27.8k
        zde->password = NULL;
251
27.8k
    }
252
27.8k
}
253
254
255
19.3M
void _zip_dirent_free(zip_dirent_t *zde) {
256
19.3M
    if (zde == NULL) {
257
19.3M
        return;
258
19.3M
    }
259
260
27.8k
    _zip_dirent_finalize(zde);
261
27.8k
    free(zde);
262
27.8k
}
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
55.5k
void _zip_dirent_init(zip_dirent_t *de) {
314
55.5k
    de->changed = 0;
315
55.5k
    de->local_extra_fields_read = 0;
316
55.5k
    de->cloned = 0;
317
318
55.5k
    de->crc_valid = true;
319
55.5k
    de->last_mod_mtime_valid = false;
320
55.5k
    de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
321
55.5k
    de->version_needed = 10; /* 1.0 */
322
55.5k
    de->bitflags = 0;
323
55.5k
    de->comp_method = ZIP_CM_DEFAULT;
324
55.5k
    de->last_mod.date = 0;
325
55.5k
    de->last_mod.time = 0;
326
55.5k
    de->crc = 0;
327
55.5k
    de->comp_size = 0;
328
55.5k
    de->uncomp_size = 0;
329
55.5k
    de->filename = NULL;
330
55.5k
    de->extra_fields = NULL;
331
55.5k
    de->comment = NULL;
332
55.5k
    de->disk_number = 0;
333
55.5k
    de->int_attrib = 0;
334
55.5k
    de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
335
55.5k
    de->offset = 0;
336
55.5k
    de->compression_level = 0;
337
55.5k
    de->encryption_method = ZIP_EM_NONE;
338
55.5k
    de->password = NULL;
339
55.5k
}
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
27.8k
zip_dirent_t *_zip_dirent_new(void) {
352
27.8k
    zip_dirent_t *de;
353
354
27.8k
    if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL) {
355
0
        return NULL;
356
0
    }
357
358
27.8k
    _zip_dirent_init(de);
359
27.8k
    return de;
360
27.8k
}
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
27.8k
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
27.8k
    zip_uint8_t buf[CDENTRYSIZE];
375
27.8k
    zip_uint32_t size, variable_size;
376
27.8k
    zip_uint16_t filename_len, comment_len, ef_len;
377
27.8k
    zip_string_t *utf8_string;
378
27.8k
    bool is_zip64 = false;
379
380
27.8k
    bool from_buffer = (buffer != NULL);
381
382
27.8k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
383
384
27.8k
    if (buffer) {
385
26.0k
        if (_zip_buffer_left(buffer) < size) {
386
25
            zip_error_set(error, ZIP_ER_NOZIP, 0);
387
25
            return -1;
388
25
        }
389
26.0k
    }
390
1.78k
    else {
391
1.78k
        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
392
3
            return -1;
393
3
        }
394
1.78k
    }
395
396
27.7k
    if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
397
114
        zip_error_set(error, ZIP_ER_NOZIP, 0);
398
114
        if (!from_buffer) {
399
43
            _zip_buffer_free(buffer);
400
43
        }
401
114
        return -1;
402
114
    }
403
404
    /* convert buffercontents to zip_dirent */
405
406
27.6k
    _zip_dirent_init(zde);
407
27.6k
    if (!local) {
408
27.6k
        zde->version_madeby = _zip_buffer_get_16(buffer);
409
27.6k
    }
410
0
    else {
411
0
        zde->version_madeby = 0;
412
0
    }
413
27.6k
    zde->version_needed = _zip_buffer_get_16(buffer);
414
27.6k
    zde->bitflags = _zip_buffer_get_16(buffer);
415
27.6k
    zde->comp_method = _zip_buffer_get_16(buffer);
416
417
    /* convert to time_t */
418
27.6k
    zde->last_mod.time = _zip_buffer_get_16(buffer);
419
27.6k
    zde->last_mod.date = _zip_buffer_get_16(buffer);
420
421
27.6k
    zde->crc = _zip_buffer_get_32(buffer);
422
27.6k
    zde->comp_size = _zip_buffer_get_32(buffer);
423
27.6k
    zde->uncomp_size = _zip_buffer_get_32(buffer);
424
425
27.6k
    filename_len = _zip_buffer_get_16(buffer);
426
27.6k
    ef_len = _zip_buffer_get_16(buffer);
427
428
27.6k
    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
27.6k
    else {
436
27.6k
        comment_len = _zip_buffer_get_16(buffer);
437
27.6k
        zde->disk_number = _zip_buffer_get_16(buffer);
438
27.6k
        zde->int_attrib = _zip_buffer_get_16(buffer);
439
27.6k
        zde->ext_attrib = _zip_buffer_get_32(buffer);
440
27.6k
        zde->offset = _zip_buffer_get_32(buffer);
441
27.6k
    }
442
443
27.6k
    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
27.6k
    if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
452
422
        if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
453
            /* TODO */
454
282
            zde->encryption_method = ZIP_EM_UNKNOWN;
455
282
        }
456
140
        else {
457
140
            zde->encryption_method = ZIP_EM_TRAD_PKWARE;
458
140
        }
459
422
    }
460
27.2k
    else {
461
27.2k
        zde->encryption_method = ZIP_EM_NONE;
462
27.2k
    }
463
464
27.6k
    zde->filename = NULL;
465
27.6k
    zde->extra_fields = NULL;
466
27.6k
    zde->comment = NULL;
467
468
27.6k
    variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
469
470
27.6k
    if (from_buffer) {
471
25.9k
        if (_zip_buffer_left(buffer) < variable_size) {
472
53
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
473
53
            return -1;
474
53
        }
475
25.9k
    }
476
1.73k
    else {
477
1.73k
        _zip_buffer_free(buffer);
478
479
1.73k
        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
480
18
            return -1;
481
18
        }
482
1.73k
    }
483
484
27.6k
    if (filename_len) {
485
27.3k
        zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
486
27.3k
        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
27.3k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
497
25.1k
            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
498
78
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME);
499
78
                if (!from_buffer) {
500
25
                    _zip_buffer_free(buffer);
501
25
                }
502
78
                return -1;
503
78
            }
504
25.1k
        }
505
506
27.2k
        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
27.2k
    }
520
521
27.5k
    if (ef_len) {
522
1.93k
        zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
523
524
1.93k
        if (ef == NULL) {
525
0
            if (!from_buffer) {
526
0
                _zip_buffer_free(buffer);
527
0
            }
528
0
            return -1;
529
0
        }
530
1.93k
        if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
531
197
            free(ef);
532
197
            if (!from_buffer) {
533
30
                _zip_buffer_free(buffer);
534
30
            }
535
197
            return -1;
536
197
        }
537
1.73k
        free(ef);
538
1.73k
        if (local) {
539
0
            zde->local_extra_fields_read = 1;
540
0
        }
541
1.73k
    }
542
543
27.3k
    if (comment_len) {
544
1.34k
        zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
545
1.34k
        if (zde->comment == NULL) {
546
0
            if (!from_buffer) {
547
0
                _zip_buffer_free(buffer);
548
0
            }
549
0
            return -1;
550
0
        }
551
1.34k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
552
913
            if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
553
45
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT);
554
45
                if (!from_buffer) {
555
19
                    _zip_buffer_free(buffer);
556
19
                }
557
45
                return -1;
558
45
            }
559
913
        }
560
1.34k
    }
561
562
27.2k
    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
27.2k
    zde->filename = utf8_string;
570
27.2k
    if (!local) {
571
27.2k
        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
27.2k
        zde->comment = utf8_string;
579
27.2k
    }
580
581
    /* Zip64 */
582
583
27.2k
    if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
584
335
        zip_uint16_t got_len;
585
335
        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
335
        if (ef != NULL) {
587
128
            if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) {
588
128
                if (!from_buffer) {
589
6
                    _zip_buffer_free(buffer);
590
6
                }
591
128
                return -1;
592
128
            }
593
128
        }
594
207
        is_zip64 = true;
595
207
    }
596
597
598
27.1k
    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
27.1k
    if (!from_buffer) {
607
1.64k
        _zip_buffer_free(buffer);
608
1.64k
    }
609
610
27.1k
    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
27.1k
    if (zde->offset > ZIP_INT64_MAX) {
641
0
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
642
0
        return -1;
643
0
    }
644
645
27.1k
    if (!_zip_dirent_process_winzip_aes(zde, error)) {
646
23
        return -1;
647
23
    }
648
649
27.1k
    zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
650
651
27.1k
    return (zip_int64_t)size + (zip_int64_t)variable_size;
652
27.1k
}
653
654
128
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
128
    zip_buffer_t *ef_buffer;
656
657
128
    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
128
    if (zde->uncomp_size == ZIP_UINT32_MAX) {
663
12
        zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
664
12
    }
665
116
    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
128
    if (zde->comp_size == ZIP_UINT32_MAX) {
671
77
        zde->comp_size = _zip_buffer_get_64(ef_buffer);
672
77
    }
673
128
    if (!local) {
674
128
        if (zde->offset == ZIP_UINT32_MAX) {
675
48
            zde->offset = _zip_buffer_get_64(ef_buffer);
676
48
        }
677
128
        if (zde->disk_number == ZIP_UINT16_MAX) {
678
15
            zde->disk_number = _zip_buffer_get_32(ef_buffer);
679
15
        }
680
128
    }
681
682
128
    if (!_zip_buffer_eof(ef_buffer)) {
683
        /* accept additional fields if values match */
684
128
        bool ok = true;
685
128
        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
128
        default:
700
128
            ok = false;
701
128
        }
702
128
        if (!ok) {
703
128
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
704
128
            _zip_buffer_free(ef_buffer);
705
128
            return false;
706
128
        }
707
128
    }
708
0
    _zip_buffer_free(ef_buffer);
709
710
0
    return true;
711
128
}
712
713
714
54.5k
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
54.5k
    zip_uint16_t ef_len;
716
54.5k
    zip_uint32_t ef_crc;
717
54.5k
    zip_buffer_t *buffer;
718
719
54.5k
    const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
720
721
54.5k
    if (ef == NULL || ef_len < 5 || ef[0] != 1) {
722
54.5k
        return str;
723
54.5k
    }
724
725
13
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
726
0
        return str;
727
0
    }
728
729
13
    _zip_buffer_get_8(buffer);
730
13
    ef_crc = _zip_buffer_get_32(buffer);
731
732
13
    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
13
    _zip_buffer_free(buffer);
751
752
13
    return str;
753
13
}
754
755
756
27.1k
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
757
27.1k
    zip_uint16_t ef_len;
758
27.1k
    zip_buffer_t *buffer;
759
27.1k
    const zip_uint8_t *ef;
760
27.1k
    bool crc_valid;
761
27.1k
    zip_uint16_t enc_method;
762
763
764
27.1k
    if (de->comp_method != ZIP_CM_WINZIP_AES) {
765
27.1k
        return true;
766
27.1k
    }
767
768
23
    ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
769
770
23
    if (ef == NULL || ef_len < 7) {
771
23
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
772
23
        return false;
773
23
    }
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
9.54k
zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
838
9.54k
    zip_int32_t size;
839
9.54k
    bool local = (flags & ZIP_EF_LOCAL) != 0;
840
9.54k
    int i;
841
9.54k
    zip_uint8_t b[CDENTRYSIZE];
842
9.54k
    zip_buffer_t *buffer;
843
844
9.54k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
845
846
    /* Central header has fixed fields after size pointers. */
847
9.54k
    if ((buffer = _zip_buffer_new_from_source(src, local ? LENTRYSIZE : 34, b, error)) == NULL) {
848
12
        return -1;
849
12
    }
850
9.53k
    if (_zip_buffer_left(buffer) != (local ? LENTRYSIZE : 34)) {
851
0
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_ENTRY_INVALID);
852
0
        _zip_buffer_free(buffer);
853
0
        return -1;
854
0
    }
855
856
9.53k
    if (memcmp(_zip_buffer_peek(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
857
708
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_ENTRY_INVALID);
858
708
        _zip_buffer_free(buffer);
859
708
        return -1;
860
708
    }
861
862
    /* Skip to size pointers. */
863
8.82k
    _zip_buffer_skip(buffer, local ? 26 : 28);
864
865
26.4k
    for (i = 0; i < (local ? 2 : 3); i++) {
866
17.6k
        size += _zip_buffer_get_16(buffer);
867
17.6k
    }
868
869
8.82k
    _zip_buffer_free(buffer);
870
8.82k
    return size;
871
9.53k
}
872
873
874
/* _zip_dirent_write
875
   Writes zip directory entry.
876
877
   If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
878
   directory entry.  If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
879
880
   Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
881
   returned.
882
*/
883
884
0
int _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
885
0
    zip_dostime_t dostime;
886
0
    zip_encoding_type_t com_enc, name_enc;
887
0
    zip_extra_field_t *ef;
888
0
    zip_extra_field_t *ef64;
889
0
    zip_uint32_t ef_total_size;
890
0
    bool is_zip64;
891
0
    bool is_really_zip64;
892
0
    bool is_winzip_aes;
893
0
    zip_uint8_t buf[CDENTRYSIZE];
894
0
    zip_buffer_t *buffer;
895
896
0
    ef = NULL;
897
898
0
    name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
899
0
    com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
900
901
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)) {
902
0
        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
903
0
    }
904
0
    else {
905
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
906
0
        if (name_enc == ZIP_ENCODING_UTF8_KNOWN) {
907
0
            ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error);
908
0
            if (ef == NULL) {
909
0
                return -1;
910
0
            }
911
0
        }
912
0
        if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) {
913
0
            zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error);
914
0
            if (ef2 == NULL) {
915
0
                _zip_ef_free(ef);
916
0
                return -1;
917
0
            }
918
0
            ef2->next = ef;
919
0
            ef = ef2;
920
0
        }
921
0
    }
922
923
0
    if (de->encryption_method == ZIP_EM_NONE) {
924
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
925
0
    }
926
0
    else {
927
0
        de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
928
0
    }
929
930
0
    is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
931
0
    is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
932
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;
933
934
0
    if (is_zip64) {
935
0
        zip_uint8_t ef_zip64[EFZIP64SIZE];
936
0
        zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
937
0
        if (ef_buffer == NULL) {
938
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
939
0
            _zip_ef_free(ef);
940
0
            return -1;
941
0
        }
942
943
0
        if (flags & ZIP_FL_LOCAL) {
944
0
            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
945
0
                _zip_buffer_put_64(ef_buffer, de->uncomp_size);
946
0
                _zip_buffer_put_64(ef_buffer, de->comp_size);
947
0
            }
948
0
        }
949
0
        else {
950
0
            if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) {
951
0
                if (de->uncomp_size >= ZIP_UINT32_MAX) {
952
0
                    _zip_buffer_put_64(ef_buffer, de->uncomp_size);
953
0
                }
954
0
                if (de->comp_size >= ZIP_UINT32_MAX) {
955
0
                    _zip_buffer_put_64(ef_buffer, de->comp_size);
956
0
                }
957
0
                if (de->offset >= ZIP_UINT32_MAX) {
958
0
                    _zip_buffer_put_64(ef_buffer, de->offset);
959
0
                }
960
0
            }
961
0
        }
962
963
0
        if (!_zip_buffer_ok(ef_buffer)) {
964
0
            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
965
0
            _zip_buffer_free(ef_buffer);
966
0
            _zip_ef_free(ef);
967
0
            return -1;
968
0
        }
969
970
0
        ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH);
971
0
        _zip_buffer_free(ef_buffer);
972
0
        if (ef64 == NULL) {
973
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
974
0
            _zip_ef_free(ef);
975
0
            return -1;
976
0
        }
977
0
        ef64->next = ef;
978
0
        ef = ef64;
979
0
    }
980
981
0
    if (is_winzip_aes) {
982
0
        zip_uint8_t data[EF_WINZIP_AES_SIZE];
983
0
        zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
984
0
        zip_extra_field_t *ef_winzip;
985
986
0
        if (ef_buffer == NULL) {
987
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
988
0
            _zip_ef_free(ef);
989
0
            return -1;
990
0
        }
991
992
0
        _zip_buffer_put_16(ef_buffer, 2);
993
0
        _zip_buffer_put(ef_buffer, "AE", 2);
994
0
        _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
995
0
        _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
996
997
0
        if (!_zip_buffer_ok(ef_buffer)) {
998
0
            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
999
0
            _zip_buffer_free(ef_buffer);
1000
0
            _zip_ef_free(ef);
1001
0
            return -1;
1002
0
        }
1003
1004
0
        ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
1005
0
        _zip_buffer_free(ef_buffer);
1006
0
        if (ef_winzip == NULL) {
1007
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
1008
0
            _zip_ef_free(ef);
1009
0
            return -1;
1010
0
        }
1011
0
        ef_winzip->next = ef;
1012
0
        ef = ef_winzip;
1013
0
    }
1014
1015
0
    if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == 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
1021
0
    _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
1022
1023
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1024
0
        _zip_buffer_put_16(buffer, de->version_madeby);
1025
0
    }
1026
0
    _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
1027
0
    _zip_buffer_put_16(buffer, de->bitflags);
1028
0
    if (is_winzip_aes) {
1029
0
        _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
1030
0
    }
1031
0
    else {
1032
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
1033
0
    }
1034
1035
0
    if (ZIP_WANT_TORRENTZIP(za)) {
1036
0
        dostime.time = 0xbc00;
1037
0
        dostime.date = 0x2198;
1038
0
    }
1039
0
    else {
1040
0
        dostime = de->last_mod;
1041
0
    }
1042
0
    _zip_buffer_put_16(buffer, dostime.time);
1043
0
    _zip_buffer_put_16(buffer, dostime.date);
1044
1045
0
    if (is_winzip_aes && de->uncomp_size < 20) {
1046
0
        _zip_buffer_put_32(buffer, 0);
1047
0
    }
1048
0
    else {
1049
0
        _zip_buffer_put_32(buffer, de->crc);
1050
0
    }
1051
1052
0
    if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
1053
        /* In local headers, if a ZIP64 EF is written, it MUST contain
1054
         * both compressed and uncompressed sizes (even if one of the
1055
         * two is smaller than 0xFFFFFFFF); on the other hand, those
1056
         * may only appear when the corresponding standard entry is
1057
         * 0xFFFFFFFF.  (appnote.txt 4.5.3) */
1058
0
        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1059
0
        _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1060
0
    }
1061
0
    else {
1062
0
        if (de->comp_size < ZIP_UINT32_MAX) {
1063
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
1064
0
        }
1065
0
        else {
1066
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1067
0
        }
1068
0
        if (de->uncomp_size < ZIP_UINT32_MAX) {
1069
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
1070
0
        }
1071
0
        else {
1072
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1073
0
        }
1074
0
    }
1075
1076
0
    _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
1077
0
    ef_total_size = _zip_ef_size(ef, ZIP_EF_BOTH);
1078
0
    if (!ZIP_WANT_TORRENTZIP(za)) {
1079
        /* TODO: check for overflow */
1080
0
        ef_total_size += _zip_ef_size(de->extra_fields, flags);
1081
0
    }
1082
0
    if (ef_total_size > ZIP_UINT16_MAX) {
1083
0
        zip_error_set(&za->error, ZIP_ER_EF_TOO_LARGE, 0);
1084
0
        _zip_buffer_free(buffer);
1085
0
        _zip_ef_free(ef);
1086
0
        return -1;
1087
0
    }
1088
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
1089
1090
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1091
0
        _zip_buffer_put_16(buffer, ZIP_WANT_TORRENTZIP(za) ? 0 : _zip_string_length(de->comment));
1092
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
1093
0
        _zip_buffer_put_16(buffer, de->int_attrib);
1094
0
        _zip_buffer_put_32(buffer, de->ext_attrib);
1095
0
        if (de->offset < ZIP_UINT32_MAX) {
1096
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
1097
0
        }
1098
0
        else {
1099
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1100
0
        }
1101
0
    }
1102
1103
0
    if (!_zip_buffer_ok(buffer)) {
1104
0
        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
1105
0
        _zip_buffer_free(buffer);
1106
0
        _zip_ef_free(ef);
1107
0
        return -1;
1108
0
    }
1109
1110
0
    if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) {
1111
0
        _zip_buffer_free(buffer);
1112
0
        _zip_ef_free(ef);
1113
0
        return -1;
1114
0
    }
1115
1116
0
    _zip_buffer_free(buffer);
1117
1118
0
    if (de->filename) {
1119
0
        if (_zip_string_write(za, de->filename) < 0) {
1120
0
            _zip_ef_free(ef);
1121
0
            return -1;
1122
0
        }
1123
0
    }
1124
1125
0
    if (ef) {
1126
0
        if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
1127
0
            _zip_ef_free(ef);
1128
0
            return -1;
1129
0
        }
1130
0
    }
1131
0
    _zip_ef_free(ef);
1132
0
    if (de->extra_fields && !ZIP_WANT_TORRENTZIP(za)) {
1133
0
        if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
1134
0
            return -1;
1135
0
        }
1136
0
    }
1137
1138
0
    if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) {
1139
0
        if (de->comment) {
1140
0
            if (_zip_string_write(za, de->comment) < 0) {
1141
0
                return -1;
1142
0
            }
1143
0
        }
1144
0
    }
1145
1146
1147
0
    return is_zip64;
1148
0
}
1149
1150
1151
9.18k
time_t _zip_d2u_time(const zip_dostime_t *dtime) {
1152
9.18k
    struct tm tm;
1153
1154
9.18k
    memset(&tm, 0, sizeof(tm));
1155
1156
    /* let mktime decide if DST is in effect */
1157
9.18k
    tm.tm_isdst = -1;
1158
1159
9.18k
    tm.tm_year = ((dtime->date >> 9) & 127) + 1980 - 1900;
1160
9.18k
    tm.tm_mon = ((dtime->date >> 5) & 15) - 1;
1161
9.18k
    tm.tm_mday = dtime->date & 31;
1162
1163
9.18k
    tm.tm_hour = (dtime->time >> 11) & 31;
1164
9.18k
    tm.tm_min = (dtime->time >> 5) & 63;
1165
9.18k
    tm.tm_sec = (dtime->time << 1) & 62;
1166
1167
9.18k
    return mktime(&tm);
1168
9.18k
}
1169
1170
1171
0
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
1172
0
    const zip_uint8_t *raw;
1173
0
    zip_uint32_t len;
1174
0
    zip_buffer_t *buffer;
1175
0
    zip_extra_field_t *ef;
1176
1177
0
    if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
1178
        /* error already set */
1179
0
        return NULL;
1180
0
    }
1181
1182
0
    if (len + 5 > ZIP_UINT16_MAX) {
1183
0
        zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
1184
0
        return NULL;
1185
0
    }
1186
1187
0
    if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) {
1188
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
1189
0
        return NULL;
1190
0
    }
1191
1192
0
    _zip_buffer_put_8(buffer, 1);
1193
0
    _zip_buffer_put_32(buffer, _zip_string_crc32(str));
1194
0
    _zip_buffer_put(buffer, raw, len);
1195
1196
0
    if (!_zip_buffer_ok(buffer)) {
1197
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
1198
0
        _zip_buffer_free(buffer);
1199
0
        return NULL;
1200
0
    }
1201
1202
0
    ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
1203
0
    _zip_buffer_free(buffer);
1204
1205
0
    return ef;
1206
0
}
1207
1208
1209
50.0k
zip_dirent_t *_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
1210
50.0k
    if (error == NULL) {
1211
20.0k
        error = &za->error;
1212
20.0k
    }
1213
1214
50.0k
    if (idx >= za->nentry) {
1215
0
        zip_error_set(error, ZIP_ER_INVAL, 0);
1216
0
        return NULL;
1217
0
    }
1218
1219
50.0k
    if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1220
50.0k
        if (za->entry[idx].orig == NULL) {
1221
0
            zip_error_set(error, ZIP_ER_INVAL, 0);
1222
0
            return NULL;
1223
0
        }
1224
50.0k
        if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) {
1225
0
            zip_error_set(error, ZIP_ER_DELETED, 0);
1226
0
            return NULL;
1227
0
        }
1228
50.0k
        return za->entry[idx].orig;
1229
50.0k
    }
1230
0
    else {
1231
0
        return za->entry[idx].changes;
1232
0
    }
1233
50.0k
}
1234
1235
1236
0
int _zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
1237
0
    struct tm *tpm;
1238
0
    struct tm tm;
1239
0
    tpm = zip_localtime(&intime, &tm);
1240
0
    if (tpm == NULL) {
1241
        /* if localtime fails, return an arbitrary date (1980-01-01 00:00:00) */
1242
0
        dtime->date = (1 << 5) + 1;
1243
0
        dtime->time = 0;
1244
0
        if (ze) {
1245
0
            zip_error_set(ze, ZIP_ER_INVAL, errno);
1246
0
        }
1247
0
        return -1;
1248
0
    }
1249
0
    if (tpm->tm_year < 80) {
1250
0
        tpm->tm_year = 80;
1251
0
    }
1252
1253
0
    dtime->date = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
1254
0
    dtime->time = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
1255
1256
0
    return 0;
1257
0
}
1258
1259
1260
0
bool _zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
1261
0
    zip_uint16_t length;
1262
0
    bool has_changed = false;
1263
0
    zip_uint16_t version_madeby, version_needed;
1264
1265
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
1266
0
        zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
1267
0
        zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
1268
0
        if (de->bitflags != bitflags) {
1269
0
            de->bitflags = bitflags;
1270
0
            has_changed = true;
1271
0
        }
1272
0
    }
1273
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) {
1274
0
        zip_uint16_t int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0);
1275
0
        if (de->int_attrib != int_attrib) {
1276
0
            de->int_attrib = int_attrib;
1277
0
            has_changed = true;
1278
0
        }
1279
0
    }
1280
    /* manually set attributes are preferred over attributes provided by source */
1281
0
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) {
1282
0
        if (de->ext_attrib != attributes->external_file_attributes) {
1283
0
            de->ext_attrib = attributes->external_file_attributes;
1284
0
            has_changed = true;
1285
0
        }
1286
0
    }
1287
1288
0
    if (de->comp_method == ZIP_CM_LZMA) {
1289
0
        version_needed = 63;
1290
0
    }
1291
0
    else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
1292
0
        version_needed = 51;
1293
0
    }
1294
0
    else if (de->comp_method == ZIP_CM_BZIP2) {
1295
0
        version_needed = 46;
1296
0
    }
1297
0
    else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1298
0
        version_needed = 45;
1299
0
    }
1300
0
    else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1301
0
        version_needed = 20;
1302
0
    }
1303
0
    else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') {
1304
0
        version_needed = 20;
1305
0
    }
1306
0
    else {
1307
0
        version_needed = 10;
1308
0
    }
1309
1310
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
1311
0
        version_needed = ZIP_MAX(version_needed, attributes->version_needed);
1312
0
    }
1313
1314
0
    if (de->version_needed != version_needed) {
1315
0
        de->version_needed = version_needed;
1316
0
        has_changed = true;
1317
0
    }
1318
1319
0
    version_madeby = 63 | (de->version_madeby & 0xff00);
1320
0
    if ((de->changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) {
1321
0
        version_madeby = (version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8);
1322
0
    }
1323
0
    if (de->version_madeby != version_madeby) {
1324
0
        de->version_madeby = version_madeby;
1325
0
        has_changed = true;
1326
0
    }
1327
1328
0
    return has_changed;
1329
0
}
1330
1331
1332
/* _zip_dirent_torrent_normalize(de);
1333
   Set values suitable for torrentzip.
1334
*/
1335
1336
0
void zip_dirent_torrentzip_normalize(zip_dirent_t *de) {
1337
0
    de->version_madeby = 0;
1338
0
    de->version_needed = 20; /* 2.0 */
1339
0
    de->bitflags = 2;        /* maximum compression */
1340
0
    de->comp_method = ZIP_CM_DEFLATE;
1341
0
    de->compression_level = TORRENTZIP_COMPRESSION_FLAGS;
1342
0
    de->disk_number = 0;
1343
0
    de->int_attrib = 0;
1344
0
    de->ext_attrib = 0;
1345
1346
    /* last_mod, extra_fields, and comment are normalized in zip_dirent_write() directly */
1347
0
}
1348
1349
0
int zip_dirent_check_consistency(zip_dirent_t *dirent) {
1350
0
    if (dirent->comp_method == ZIP_CM_STORE) {
1351
0
        zip_uint64_t header_size = 0;
1352
0
        switch (dirent->encryption_method) {
1353
0
        case ZIP_EM_NONE:
1354
0
            break;
1355
0
        case ZIP_EM_TRAD_PKWARE:
1356
0
            header_size = 12;
1357
0
            break;
1358
0
        case ZIP_EM_AES_128:
1359
0
            header_size = 20;
1360
0
            break;
1361
0
        case ZIP_EM_AES_192:
1362
0
            header_size = 24;
1363
0
            break;
1364
0
        case ZIP_EM_AES_256:
1365
0
            header_size = 28;
1366
0
            break;
1367
1368
0
        default:
1369
0
            return 0;
1370
0
        }
1371
0
        if (dirent->uncomp_size + header_size < dirent->uncomp_size || dirent->comp_size != dirent->uncomp_size + header_size) {
1372
0
            return ZIP_ER_DETAIL_STORED_SIZE_MISMATCH;
1373
0
        }
1374
0
    }
1375
0
    return 0;
1376
0
}
1377
1378
20.0k
time_t zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
1379
20.0k
    if (!de->last_mod_mtime_valid) {
1380
9.18k
        de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
1381
9.18k
        de->last_mod_mtime_valid = true;
1382
9.18k
    }
1383
1384
20.0k
    return de->last_mod_mtime;
1385
20.0k
}