Coverage Report

Created: 2025-07-11 06:24

/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
33.5k
_zip_cdir_free(zip_cdir_t *cd) {
51
33.5k
    zip_uint64_t i;
52
53
33.5k
    if (cd == NULL) {
54
0
        return;
55
0
    }
56
57
30.1M
    for (i = 0; i < cd->nentry; i++)
58
30.0M
        _zip_entry_finalize(cd->entry + i);
59
33.5k
    free(cd->entry);
60
33.5k
    _zip_string_free(cd->comment);
61
33.5k
    free(cd);
62
33.5k
}
63
64
65
zip_cdir_t *
66
35.4k
_zip_cdir_new(zip_error_t *error) {
67
35.4k
    zip_cdir_t *cd;
68
69
35.4k
    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
35.4k
    cd->entry = NULL;
75
35.4k
    cd->nentry = cd->nentry_alloc = 0;
76
35.4k
    cd->size = cd->offset = 0;
77
35.4k
    cd->comment = NULL;
78
35.4k
    cd->is_zip64 = false;
79
80
35.4k
    return cd;
81
35.4k
}
82
83
84
bool
85
3.10k
_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
86
3.10k
    zip_uint64_t i;
87
88
3.10k
    if (additional_entries == 0) {
89
357
        return true;
90
357
    }
91
92
2.74k
    if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
93
0
        return false;
94
0
    }
95
96
30.1M
    for (i = cd->nentry; i < cd->nentry_alloc; i++) {
97
30.1M
        _zip_entry_init(cd->entry + i);
98
30.1M
    }
99
100
2.74k
    cd->nentry = cd->nentry_alloc;
101
102
2.74k
    return true;
103
2.74k
}
104
105
106
zip_int64_t
107
0
_zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
108
0
    zip_uint64_t offset, size;
109
0
    zip_string_t *comment;
110
0
    zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN];
111
0
    zip_buffer_t *buffer;
112
0
    zip_int64_t off;
113
0
    zip_uint64_t i;
114
0
    zip_uint32_t cdir_crc;
115
116
0
    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
0
    offset = (zip_uint64_t)off;
121
122
0
    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
0
    for (i = 0; i < survivors; i++) {
128
0
        zip_entry_t *entry = za->entry + filelist[i].idx;
129
130
0
        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
0
    }
135
136
0
    za->write_crc = NULL;
137
138
0
    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
0
    size = (zip_uint64_t)off - offset;
143
144
0
    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
0
    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
0
    _zip_buffer_put(buffer, EOCD_MAGIC, 4);
167
0
    _zip_buffer_put_32(buffer, 0);
168
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
169
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
170
0
    _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size);
171
0
    _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset);
172
173
0
    comment = za->comment_changed ? za->comment_changes : za->comment_orig;
174
175
0
    if (ZIP_WANT_TORRENTZIP(za)) {
176
0
        _zip_buffer_put_16(buffer, TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH);
177
0
    }
178
0
    else {
179
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
180
0
    }
181
182
183
0
    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
0
    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
0
    _zip_buffer_free(buffer);
195
196
0
    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
0
    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
0
    return (zip_int64_t)size;
211
0
}
212
213
214
zip_dirent_t *
215
0
_zip_dirent_clone(const zip_dirent_t *sde) {
216
0
    zip_dirent_t *tde;
217
218
0
    if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
219
0
        return NULL;
220
221
0
    if (sde)
222
0
        (void)memcpy_s(tde, sizeof(*tde), sde, sizeof(*sde));
223
0
    else
224
0
        _zip_dirent_init(tde);
225
226
0
    tde->changed = 0;
227
0
    tde->cloned = 1;
228
229
0
    return tde;
230
0
}
231
232
233
void
234
37.9k
_zip_dirent_finalize(zip_dirent_t *zde) {
235
37.9k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
236
37.9k
        _zip_string_free(zde->filename);
237
37.9k
        zde->filename = NULL;
238
37.9k
    }
239
37.9k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
240
37.9k
        _zip_ef_free(zde->extra_fields);
241
37.9k
        zde->extra_fields = NULL;
242
37.9k
    }
243
37.9k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
244
37.9k
        _zip_string_free(zde->comment);
245
37.9k
        zde->comment = NULL;
246
37.9k
    }
247
37.9k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
248
37.9k
        if (zde->password) {
249
0
            _zip_crypto_clear(zde->password, strlen(zde->password));
250
0
        }
251
37.9k
        free(zde->password);
252
37.9k
        zde->password = NULL;
253
37.9k
    }
254
37.9k
}
255
256
257
void
258
60.2M
_zip_dirent_free(zip_dirent_t *zde) {
259
60.2M
    if (zde == NULL)
260
60.2M
        return;
261
262
37.9k
    _zip_dirent_finalize(zde);
263
37.9k
    free(zde);
264
37.9k
}
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
75.6k
_zip_dirent_init(zip_dirent_t *de) {
318
75.6k
    de->changed = 0;
319
75.6k
    de->local_extra_fields_read = 0;
320
75.6k
    de->cloned = 0;
321
322
75.6k
    de->crc_valid = true;
323
75.6k
    de->last_mod_mtime_valid = false;
324
75.6k
    de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
325
75.6k
    de->version_needed = 10; /* 1.0 */
326
75.6k
    de->bitflags = 0;
327
75.6k
    de->comp_method = ZIP_CM_DEFAULT;
328
75.6k
    de->last_mod.date = 0;
329
75.6k
    de->last_mod.time = 0;
330
75.6k
    de->crc = 0;
331
75.6k
    de->comp_size = 0;
332
75.6k
    de->uncomp_size = 0;
333
75.6k
    de->filename = NULL;
334
75.6k
    de->extra_fields = NULL;
335
75.6k
    de->comment = NULL;
336
75.6k
    de->disk_number = 0;
337
75.6k
    de->int_attrib = 0;
338
75.6k
    de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
339
75.6k
    de->offset = 0;
340
75.6k
    de->compression_level = 0;
341
75.6k
    de->encryption_method = ZIP_EM_NONE;
342
75.6k
    de->password = NULL;
343
75.6k
}
344
345
346
bool
347
0
_zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) {
348
0
    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
0
    return false;
352
0
}
353
354
355
zip_dirent_t *
356
37.9k
_zip_dirent_new(void) {
357
37.9k
    zip_dirent_t *de;
358
359
37.9k
    if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL)
360
0
        return NULL;
361
362
37.9k
    _zip_dirent_init(de);
363
37.9k
    return de;
364
37.9k
}
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
37.9k
_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
37.9k
    zip_uint8_t buf[CDENTRYSIZE];
380
37.9k
    zip_uint32_t size, variable_size;
381
37.9k
    zip_uint16_t filename_len, comment_len, ef_len;
382
37.9k
    zip_string_t *utf8_string;
383
37.9k
    bool is_zip64 = false;
384
385
37.9k
    bool from_buffer = (buffer != NULL);
386
387
37.9k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
388
389
37.9k
    if (buffer) {
390
29.0k
        if (_zip_buffer_left(buffer) < size) {
391
109
            zip_error_set(error, ZIP_ER_NOZIP, 0);
392
109
            return -1;
393
109
        }
394
29.0k
    }
395
8.84k
    else {
396
8.84k
        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
397
10
            return -1;
398
10
        }
399
8.84k
    }
400
401
37.8k
    if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
402
75
        zip_error_set(error, ZIP_ER_NOZIP, 0);
403
75
        if (!from_buffer) {
404
22
            _zip_buffer_free(buffer);
405
22
        }
406
75
        return -1;
407
75
    }
408
409
    /* convert buffercontents to zip_dirent */
410
411
37.7k
    _zip_dirent_init(zde);
412
37.7k
    if (!local)
413
37.7k
        zde->version_madeby = _zip_buffer_get_16(buffer);
414
0
    else
415
0
        zde->version_madeby = 0;
416
37.7k
    zde->version_needed = _zip_buffer_get_16(buffer);
417
37.7k
    zde->bitflags = _zip_buffer_get_16(buffer);
418
37.7k
    zde->comp_method = _zip_buffer_get_16(buffer);
419
420
    /* convert to time_t */
421
37.7k
    zde->last_mod.time = _zip_buffer_get_16(buffer);
422
37.7k
    zde->last_mod.date = _zip_buffer_get_16(buffer);
423
424
37.7k
    zde->crc = _zip_buffer_get_32(buffer);
425
37.7k
    zde->comp_size = _zip_buffer_get_32(buffer);
426
37.7k
    zde->uncomp_size = _zip_buffer_get_32(buffer);
427
428
37.7k
    filename_len = _zip_buffer_get_16(buffer);
429
37.7k
    ef_len = _zip_buffer_get_16(buffer);
430
431
37.7k
    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
37.7k
    else {
439
37.7k
        comment_len = _zip_buffer_get_16(buffer);
440
37.7k
        zde->disk_number = _zip_buffer_get_16(buffer);
441
37.7k
        zde->int_attrib = _zip_buffer_get_16(buffer);
442
37.7k
        zde->ext_attrib = _zip_buffer_get_32(buffer);
443
37.7k
        zde->offset = _zip_buffer_get_32(buffer);
444
37.7k
    }
445
446
37.7k
    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
37.7k
    if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
455
12.9k
        if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
456
            /* TODO */
457
4.21k
            zde->encryption_method = ZIP_EM_UNKNOWN;
458
4.21k
        }
459
8.71k
        else {
460
8.71k
            zde->encryption_method = ZIP_EM_TRAD_PKWARE;
461
8.71k
        }
462
12.9k
    }
463
24.8k
    else {
464
24.8k
        zde->encryption_method = ZIP_EM_NONE;
465
24.8k
    }
466
467
37.7k
    zde->filename = NULL;
468
37.7k
    zde->extra_fields = NULL;
469
37.7k
    zde->comment = NULL;
470
471
37.7k
    variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
472
473
37.7k
    if (from_buffer) {
474
28.9k
        if (_zip_buffer_left(buffer) < variable_size) {
475
59
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
476
59
            return -1;
477
59
        }
478
28.9k
    }
479
8.80k
    else {
480
8.80k
        _zip_buffer_free(buffer);
481
482
8.80k
        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
483
8
            return -1;
484
8
        }
485
8.80k
    }
486
487
37.6k
    if (filename_len) {
488
14.2k
        zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
489
14.2k
        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
14.2k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
500
5.29k
            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
501
28
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME);
502
28
                if (!from_buffer) {
503
5
                    _zip_buffer_free(buffer);
504
5
                }
505
28
                return -1;
506
28
            }
507
5.29k
        }
508
14.2k
    }
509
510
37.6k
    if (ef_len) {
511
12.7k
        zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
512
513
12.7k
        if (ef == NULL) {
514
0
            if (!from_buffer) {
515
0
                _zip_buffer_free(buffer);
516
0
            }
517
0
            return -1;
518
0
        }
519
12.7k
        if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
520
103
            free(ef);
521
103
            if (!from_buffer) {
522
14
                _zip_buffer_free(buffer);
523
14
            }
524
103
            return -1;
525
103
        }
526
12.6k
        free(ef);
527
12.6k
        if (local)
528
0
            zde->local_extra_fields_read = 1;
529
12.6k
    }
530
531
37.5k
    if (comment_len) {
532
3.36k
        zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
533
3.36k
        if (zde->comment == NULL) {
534
0
            if (!from_buffer) {
535
0
                _zip_buffer_free(buffer);
536
0
            }
537
0
            return -1;
538
0
        }
539
3.36k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
540
2.61k
            if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
541
19
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT);
542
19
                if (!from_buffer) {
543
3
                    _zip_buffer_free(buffer);
544
3
                }
545
19
                return -1;
546
19
            }
547
2.61k
        }
548
3.36k
    }
549
550
37.5k
    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
37.5k
    zde->filename = utf8_string;
558
37.5k
    if (!local) {
559
37.5k
        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
37.5k
        zde->comment = utf8_string;
567
37.5k
    }
568
569
    /* Zip64 */
570
571
37.5k
    if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
572
4.05k
        zip_uint16_t got_len;
573
4.05k
        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
4.05k
        if (ef != NULL) {
575
2.37k
            if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) {
576
303
                if (!from_buffer) {
577
1
                    _zip_buffer_free(buffer);
578
1
                }
579
303
                return -1;
580
303
            }
581
2.37k
        }
582
3.74k
        is_zip64 = true;
583
3.74k
    }
584
585
586
37.2k
    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
37.2k
    if (!from_buffer) {
595
8.77k
        _zip_buffer_free(buffer);
596
8.77k
    }
597
598
37.2k
    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
37.2k
    if (zde->offset > ZIP_INT64_MAX) {
629
49
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
630
49
        return -1;
631
49
    }
632
633
37.1k
    if (!_zip_dirent_process_winzip_aes(zde, error)) {
634
61
        return -1;
635
61
    }
636
637
37.1k
    zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
638
639
37.1k
    return (zip_int64_t)size + (zip_int64_t)variable_size;
640
37.1k
}
641
642
bool
643
2.37k
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
2.37k
    zip_buffer_t *ef_buffer;
645
646
2.37k
    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
2.37k
    if (zde->uncomp_size == ZIP_UINT32_MAX) {
652
1.43k
        zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
653
1.43k
    }
654
948
    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
2.37k
    if (zde->comp_size == ZIP_UINT32_MAX) {
660
1.30k
        zde->comp_size = _zip_buffer_get_64(ef_buffer);
661
1.30k
    }
662
2.37k
    if (!local) {
663
2.37k
        if (zde->offset == ZIP_UINT32_MAX) {
664
214
            zde->offset = _zip_buffer_get_64(ef_buffer);
665
214
        }
666
2.37k
        if (zde->disk_number == ZIP_UINT16_MAX) {
667
74
            zde->disk_number = _zip_buffer_get_32(ef_buffer);
668
74
        }
669
2.37k
    }
670
671
2.37k
    if (!_zip_buffer_eof(ef_buffer)) {
672
        /* accept additional fields if values match */
673
750
        bool ok = true;
674
750
        switch (got_len) {
675
584
        case 28:
676
584
            _zip_buffer_set_offset(ef_buffer, 24);
677
584
            if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
678
201
                ok = false;
679
201
            }
680
            /* fallthrough */
681
664
        case 24:
682
664
            _zip_buffer_set_offset(ef_buffer, 0);
683
664
            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
215
                ok = false;
685
215
            }
686
664
            break;
687
688
86
        default:
689
86
            ok = false;
690
750
        }
691
750
        if (!ok) {
692
303
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
693
303
            _zip_buffer_free(ef_buffer);
694
303
            return false;
695
303
        }
696
750
    }
697
2.07k
    _zip_buffer_free(ef_buffer);
698
699
2.07k
    return true;
700
2.37k
}
701
702
703
static zip_string_t *
704
75.0k
_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str, bool check_consistency) {
705
75.0k
    zip_uint16_t ef_len;
706
75.0k
    zip_uint32_t ef_crc;
707
75.0k
    zip_buffer_t *buffer;
708
709
75.0k
    const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
710
711
75.0k
    if (ef == NULL || ef_len < 5 || ef[0] != 1) {
712
70.1k
        return str;
713
70.1k
    }
714
715
4.90k
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
716
0
        return str;
717
0
    }
718
719
4.90k
    _zip_buffer_get_8(buffer);
720
4.90k
    ef_crc = _zip_buffer_get_32(buffer);
721
722
4.90k
    if (_zip_string_crc32(str) == ef_crc) {
723
4.03k
        zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
724
4.03k
        zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
725
726
4.03k
        if (ef_str != NULL) {
727
1.85k
            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
1.85k
            _zip_string_free(str);
736
1.85k
            str = ef_str;
737
1.85k
        }
738
4.03k
    }
739
740
4.90k
    _zip_buffer_free(buffer);
741
742
4.90k
    return str;
743
4.90k
}
744
745
746
static bool
747
37.1k
_zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
748
37.1k
    zip_uint16_t ef_len;
749
37.1k
    zip_buffer_t *buffer;
750
37.1k
    const zip_uint8_t *ef;
751
37.1k
    bool crc_valid;
752
37.1k
    zip_uint16_t enc_method;
753
754
755
37.1k
    if (de->comp_method != ZIP_CM_WINZIP_AES) {
756
36.1k
        return true;
757
36.1k
    }
758
759
1.04k
    ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
760
761
1.04k
    if (ef == NULL || ef_len < 7) {
762
8
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
763
8
        return false;
764
8
    }
765
766
1.03k
    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.03k
    crc_valid = true;
774
1.03k
    switch (_zip_buffer_get_16(buffer)) {
775
222
    case 1:
776
222
        break;
777
778
802
    case 2:
779
802
        crc_valid = false;
780
        /* TODO: When checking consistency, check that crc is 0. */
781
802
        break;
782
783
10
    default:
784
10
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
785
10
        _zip_buffer_free(buffer);
786
10
        return false;
787
1.03k
    }
788
789
    /* vendor */
790
1.02k
    if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
791
28
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
792
28
        _zip_buffer_free(buffer);
793
28
        return false;
794
28
    }
795
796
    /* mode */
797
996
    switch (_zip_buffer_get_8(buffer)) {
798
377
    case 1:
799
377
        enc_method = ZIP_EM_AES_128;
800
377
        break;
801
52
    case 2:
802
52
        enc_method = ZIP_EM_AES_192;
803
52
        break;
804
560
    case 3:
805
560
        enc_method = ZIP_EM_AES_256;
806
560
        break;
807
7
    default:
808
7
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
809
7
        _zip_buffer_free(buffer);
810
7
        return false;
811
996
    }
812
813
989
    if (ef_len != 7) {
814
8
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
815
8
        _zip_buffer_free(buffer);
816
8
        return false;
817
8
    }
818
819
981
    de->crc_valid = crc_valid;
820
981
    de->encryption_method = enc_method;
821
981
    de->comp_method = _zip_buffer_get_16(buffer);
822
823
981
    _zip_buffer_free(buffer);
824
981
    return true;
825
989
}
826
827
828
zip_int32_t
829
15.5k
_zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
830
15.5k
    zip_int32_t size;
831
15.5k
    bool local = (flags & ZIP_EF_LOCAL) != 0;
832
15.5k
    int i;
833
15.5k
    zip_uint8_t b[6];
834
15.5k
    zip_buffer_t *buffer;
835
836
15.5k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
837
838
15.5k
    if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
839
296
        zip_error_set_from_source(error, src);
840
296
        return -1;
841
296
    }
842
843
15.3k
    if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
844
212
        return -1;
845
212
    }
846
847
45.2k
    for (i = 0; i < (local ? 2 : 3); i++) {
848
30.1k
        size += _zip_buffer_get_16(buffer);
849
30.1k
    }
850
851
15.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
15.0k
    _zip_buffer_free(buffer);
858
15.0k
    return size;
859
15.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
0
_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
874
0
    zip_dostime_t dostime;
875
0
    zip_encoding_type_t com_enc, name_enc;
876
0
    zip_extra_field_t *ef;
877
0
    zip_extra_field_t *ef64;
878
0
    zip_uint32_t ef_total_size;
879
0
    bool is_zip64;
880
0
    bool is_really_zip64;
881
0
    bool is_winzip_aes;
882
0
    zip_uint8_t buf[CDENTRYSIZE];
883
0
    zip_buffer_t *buffer;
884
885
0
    ef = NULL;
886
887
0
    name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
888
0
    com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
889
890
0
    if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN))
891
0
        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
892
0
    else {
893
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
894
0
        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
0
        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
0
    }
909
910
0
    if (de->encryption_method == ZIP_EM_NONE) {
911
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
912
0
    }
913
0
    else {
914
0
        de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
915
0
    }
916
917
0
    is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
918
0
    is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
919
0
    is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256;
920
921
0
    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
0
    if (is_winzip_aes) {
964
0
        zip_uint8_t data[EF_WINZIP_AES_SIZE];
965
0
        zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
966
0
        zip_extra_field_t *ef_winzip;
967
968
0
        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
0
        _zip_buffer_put_16(ef_buffer, 2);
975
0
        _zip_buffer_put(ef_buffer, "AE", 2);
976
0
        _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
977
0
        _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
978
979
0
        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
0
        ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
987
0
        _zip_buffer_free(ef_buffer);
988
0
        ef_winzip->next = ef;
989
0
        ef = ef_winzip;
990
0
    }
991
992
0
    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
0
    _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
999
1000
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1001
0
        _zip_buffer_put_16(buffer, de->version_madeby);
1002
0
    }
1003
0
    _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
1004
0
    _zip_buffer_put_16(buffer, de->bitflags);
1005
0
    if (is_winzip_aes) {
1006
0
        _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
1007
0
    }
1008
0
    else {
1009
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
1010
0
    }
1011
1012
0
    if (ZIP_WANT_TORRENTZIP(za)) {
1013
0
        dostime.time = 0xbc00;
1014
0
        dostime.date = 0x2198;
1015
0
    }
1016
0
    else {
1017
0
        dostime = de->last_mod;
1018
0
    }
1019
0
    _zip_buffer_put_16(buffer, dostime.time);
1020
0
    _zip_buffer_put_16(buffer, dostime.date);
1021
1022
0
    if (is_winzip_aes && de->uncomp_size < 20) {
1023
0
        _zip_buffer_put_32(buffer, 0);
1024
0
    }
1025
0
    else {
1026
0
        _zip_buffer_put_32(buffer, de->crc);
1027
0
    }
1028
1029
0
    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
0
    else {
1039
0
        if (de->comp_size < ZIP_UINT32_MAX) {
1040
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
1041
0
        }
1042
0
        else {
1043
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1044
0
        }
1045
0
        if (de->uncomp_size < ZIP_UINT32_MAX) {
1046
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
1047
0
        }
1048
0
        else {
1049
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1050
0
        }
1051
0
    }
1052
1053
0
    _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
1054
0
    ef_total_size = (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
1055
0
    if (!ZIP_WANT_TORRENTZIP(za)) {
1056
        /* TODO: check for overflow */
1057
0
        ef_total_size += (zip_uint32_t)_zip_ef_size(de->extra_fields, flags);
1058
0
    }
1059
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
1060
1061
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1062
0
        _zip_buffer_put_16(buffer, ZIP_WANT_TORRENTZIP(za) ? 0 : _zip_string_length(de->comment));
1063
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
1064
0
        _zip_buffer_put_16(buffer, de->int_attrib);
1065
0
        _zip_buffer_put_32(buffer, de->ext_attrib);
1066
0
        if (de->offset < ZIP_UINT32_MAX)
1067
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
1068
0
        else
1069
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1070
0
    }
1071
1072
0
    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
0
    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
0
    _zip_buffer_free(buffer);
1086
1087
0
    if (de->filename) {
1088
0
        if (_zip_string_write(za, de->filename) < 0) {
1089
0
            _zip_ef_free(ef);
1090
0
            return -1;
1091
0
        }
1092
0
    }
1093
1094
0
    if (ef) {
1095
0
        if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
1096
0
            _zip_ef_free(ef);
1097
0
            return -1;
1098
0
        }
1099
0
    }
1100
0
    _zip_ef_free(ef);
1101
0
    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
0
    if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) {
1108
0
        if (de->comment) {
1109
0
            if (_zip_string_write(za, de->comment) < 0) {
1110
0
                return -1;
1111
0
            }
1112
0
        }
1113
0
    }
1114
1115
1116
0
    return is_zip64;
1117
0
}
1118
1119
1120
time_t
1121
25.2k
_zip_d2u_time(const zip_dostime_t *dtime) {
1122
25.2k
    struct tm tm;
1123
1124
25.2k
    memset(&tm, 0, sizeof(tm));
1125
1126
    /* let mktime decide if DST is in effect */
1127
25.2k
    tm.tm_isdst = -1;
1128
1129
25.2k
    tm.tm_year = ((dtime->date >> 9) & 127) + 1980 - 1900;
1130
25.2k
    tm.tm_mon = ((dtime->date >> 5) & 15) - 1;
1131
25.2k
    tm.tm_mday = dtime->date & 31;
1132
1133
25.2k
    tm.tm_hour = (dtime->time >> 11) & 31;
1134
25.2k
    tm.tm_min = (dtime->time >> 5) & 63;
1135
25.2k
    tm.tm_sec = (dtime->time << 1) & 62;
1136
1137
25.2k
    return mktime(&tm);
1138
25.2k
}
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
75.5k
_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
1182
75.5k
    if (error == NULL)
1183
25.2k
        error = &za->error;
1184
1185
75.5k
    if (idx >= za->nentry) {
1186
0
        zip_error_set(error, ZIP_ER_INVAL, 0);
1187
0
        return NULL;
1188
0
    }
1189
1190
75.5k
    if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1191
75.5k
        if (za->entry[idx].orig == NULL) {
1192
0
            zip_error_set(error, ZIP_ER_INVAL, 0);
1193
0
            return NULL;
1194
0
        }
1195
75.5k
        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
75.5k
        return za->entry[idx].orig;
1200
75.5k
    }
1201
0
    else
1202
0
        return za->entry[idx].changes;
1203
75.5k
}
1204
1205
1206
int
1207
0
_zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
1208
0
    struct tm *tpm;
1209
0
    struct tm tm;
1210
0
    tpm = zip_localtime(&intime, &tm);
1211
0
    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
0
    if (tpm->tm_year < 80) {
1221
0
        tpm->tm_year = 80;
1222
0
    }
1223
1224
0
    dtime->date = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
1225
0
    dtime->time = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
1226
1227
0
    return 0;
1228
0
}
1229
1230
1231
bool
1232
0
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
1233
0
    zip_uint16_t length;
1234
0
    bool has_changed = false;
1235
1236
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
1237
0
        zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
1238
0
        zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
1239
0
        if (de->bitflags != bitflags) {
1240
0
            de->bitflags = bitflags;
1241
0
            has_changed = true;
1242
0
        }
1243
0
    }
1244
0
    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
0
    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
0
    zip_uint16_t version_needed;
1260
0
    if (de->comp_method == ZIP_CM_LZMA) {
1261
0
        version_needed = 63;
1262
0
    }
1263
0
    else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
1264
0
        version_needed = 51;
1265
0
    }
1266
0
    else if (de->comp_method == ZIP_CM_BZIP2) {
1267
0
        version_needed = 46;
1268
0
    }
1269
0
    else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1270
0
        version_needed = 45;
1271
0
    }
1272
0
    else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1273
0
        version_needed = 20;
1274
0
    }
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
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
1283
0
        version_needed = ZIP_MAX(version_needed, attributes->version_needed);
1284
0
    }
1285
1286
0
    if (de->version_needed != version_needed) {
1287
0
        de->version_needed = version_needed;
1288
0
        has_changed = true;
1289
0
    }
1290
1291
0
    zip_int16_t version_madeby = 63 | (de->version_madeby & 0xff00);
1292
0
    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
0
    if (de->version_madeby != version_madeby) {
1296
0
        de->version_madeby = version_madeby;
1297
0
        has_changed = true;
1298
0
    }
1299
1300
0
    return has_changed;
1301
0
}
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
25.2k
zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
1354
25.2k
    if (!de->last_mod_mtime_valid) {
1355
25.2k
        de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
1356
25.2k
        de->last_mod_mtime_valid = true;
1357
25.2k
    }
1358
1359
25.2k
    return de->last_mod_mtime;
1360
25.2k
}