Coverage Report

Created: 2025-07-12 06:27

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