Coverage Report

Created: 2025-11-24 06:37

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