Coverage Report

Created: 2025-11-16 06:38

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
33.1k
_zip_cdir_free(zip_cdir_t *cd) {
51
33.1k
    zip_uint64_t i;
52
53
33.1k
    if (cd == NULL) {
54
0
        return;
55
0
    }
56
57
35.3M
    for (i = 0; i < cd->nentry; i++)
58
35.2M
        _zip_entry_finalize(cd->entry + i);
59
33.1k
    free(cd->entry);
60
33.1k
    _zip_string_free(cd->comment);
61
33.1k
    free(cd);
62
33.1k
}
63
64
65
zip_cdir_t *
66
35.2k
_zip_cdir_new(zip_error_t *error) {
67
35.2k
    zip_cdir_t *cd;
68
69
35.2k
    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.2k
    cd->entry = NULL;
75
35.2k
    cd->nentry = cd->nentry_alloc = 0;
76
35.2k
    cd->size = cd->offset = 0;
77
35.2k
    cd->comment = NULL;
78
35.2k
    cd->is_zip64 = false;
79
80
35.2k
    return cd;
81
35.2k
}
82
83
84
bool
85
3.39k
_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) {
86
3.39k
    zip_uint64_t i;
87
88
3.39k
    if (additional_entries == 0) {
89
331
        return true;
90
331
    }
91
92
3.05k
    if (!ZIP_REALLOC(cd->entry, cd->nentry_alloc, additional_entries, error)) {
93
0
        return false;
94
0
    }
95
96
35.2M
    for (i = cd->nentry; i < cd->nentry_alloc; i++) {
97
35.2M
        _zip_entry_init(cd->entry + i);
98
35.2M
    }
99
100
3.05k
    cd->nentry = cd->nentry_alloc;
101
102
3.05k
    return true;
103
3.05k
}
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
39.4k
_zip_dirent_finalize(zip_dirent_t *zde) {
235
39.4k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
236
39.4k
        _zip_string_free(zde->filename);
237
39.4k
        zde->filename = NULL;
238
39.4k
    }
239
39.4k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) {
240
39.4k
        _zip_ef_free(zde->extra_fields);
241
39.4k
        zde->extra_fields = NULL;
242
39.4k
    }
243
39.4k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) {
244
39.4k
        _zip_string_free(zde->comment);
245
39.4k
        zde->comment = NULL;
246
39.4k
    }
247
39.4k
    if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) {
248
39.4k
        if (zde->password) {
249
0
            _zip_crypto_clear(zde->password, strlen(zde->password));
250
0
        }
251
39.4k
        free(zde->password);
252
39.4k
        zde->password = NULL;
253
39.4k
    }
254
39.4k
}
255
256
257
void
258
70.5M
_zip_dirent_free(zip_dirent_t *zde) {
259
70.5M
    if (zde == NULL)
260
70.5M
        return;
261
262
39.4k
    _zip_dirent_finalize(zde);
263
39.4k
    free(zde);
264
39.4k
}
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
78.6k
_zip_dirent_init(zip_dirent_t *de) {
318
78.6k
    de->changed = 0;
319
78.6k
    de->local_extra_fields_read = 0;
320
78.6k
    de->cloned = 0;
321
322
78.6k
    de->crc_valid = true;
323
78.6k
    de->last_mod_mtime_valid = false;
324
78.6k
    de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8);
325
78.6k
    de->version_needed = 10; /* 1.0 */
326
78.6k
    de->bitflags = 0;
327
78.6k
    de->comp_method = ZIP_CM_DEFAULT;
328
78.6k
    de->last_mod.date = 0;
329
78.6k
    de->last_mod.time = 0;
330
78.6k
    de->crc = 0;
331
78.6k
    de->comp_size = 0;
332
78.6k
    de->uncomp_size = 0;
333
78.6k
    de->filename = NULL;
334
78.6k
    de->extra_fields = NULL;
335
78.6k
    de->comment = NULL;
336
78.6k
    de->disk_number = 0;
337
78.6k
    de->int_attrib = 0;
338
78.6k
    de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT;
339
78.6k
    de->offset = 0;
340
78.6k
    de->compression_level = 0;
341
78.6k
    de->encryption_method = ZIP_EM_NONE;
342
78.6k
    de->password = NULL;
343
78.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
39.4k
_zip_dirent_new(void) {
357
39.4k
    zip_dirent_t *de;
358
359
39.4k
    if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL)
360
0
        return NULL;
361
362
39.4k
    _zip_dirent_init(de);
363
39.4k
    return de;
364
39.4k
}
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
39.4k
_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
39.4k
    zip_uint8_t buf[CDENTRYSIZE];
380
39.4k
    zip_uint32_t size, variable_size;
381
39.4k
    zip_uint16_t filename_len, comment_len, ef_len;
382
39.4k
    zip_string_t *utf8_string;
383
39.4k
    bool is_zip64 = false;
384
385
39.4k
    bool from_buffer = (buffer != NULL);
386
387
39.4k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
388
389
39.4k
    if (buffer) {
390
31.2k
        if (_zip_buffer_left(buffer) < size) {
391
110
            zip_error_set(error, ZIP_ER_NOZIP, 0);
392
110
            return -1;
393
110
        }
394
31.2k
    }
395
8.15k
    else {
396
8.15k
        if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) {
397
11
            return -1;
398
11
        }
399
8.15k
    }
400
401
39.3k
    if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
402
95
        zip_error_set(error, ZIP_ER_NOZIP, 0);
403
95
        if (!from_buffer) {
404
24
            _zip_buffer_free(buffer);
405
24
        }
406
95
        return -1;
407
95
    }
408
409
    /* convert buffercontents to zip_dirent */
410
411
39.2k
    _zip_dirent_init(zde);
412
39.2k
    if (!local)
413
39.2k
        zde->version_madeby = _zip_buffer_get_16(buffer);
414
0
    else
415
0
        zde->version_madeby = 0;
416
39.2k
    zde->version_needed = _zip_buffer_get_16(buffer);
417
39.2k
    zde->bitflags = _zip_buffer_get_16(buffer);
418
39.2k
    zde->comp_method = _zip_buffer_get_16(buffer);
419
420
    /* convert to time_t */
421
39.2k
    zde->last_mod.time = _zip_buffer_get_16(buffer);
422
39.2k
    zde->last_mod.date = _zip_buffer_get_16(buffer);
423
424
39.2k
    zde->crc = _zip_buffer_get_32(buffer);
425
39.2k
    zde->comp_size = _zip_buffer_get_32(buffer);
426
39.2k
    zde->uncomp_size = _zip_buffer_get_32(buffer);
427
428
39.2k
    filename_len = _zip_buffer_get_16(buffer);
429
39.2k
    ef_len = _zip_buffer_get_16(buffer);
430
431
39.2k
    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
39.2k
    else {
439
39.2k
        comment_len = _zip_buffer_get_16(buffer);
440
39.2k
        zde->disk_number = _zip_buffer_get_16(buffer);
441
39.2k
        zde->int_attrib = _zip_buffer_get_16(buffer);
442
39.2k
        zde->ext_attrib = _zip_buffer_get_32(buffer);
443
39.2k
        zde->offset = _zip_buffer_get_32(buffer);
444
39.2k
    }
445
446
39.2k
    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
39.2k
    if (zde->bitflags & ZIP_GPBF_ENCRYPTED) {
455
14.8k
        if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) {
456
            /* TODO */
457
4.86k
            zde->encryption_method = ZIP_EM_UNKNOWN;
458
4.86k
        }
459
9.95k
        else {
460
9.95k
            zde->encryption_method = ZIP_EM_TRAD_PKWARE;
461
9.95k
        }
462
14.8k
    }
463
24.4k
    else {
464
24.4k
        zde->encryption_method = ZIP_EM_NONE;
465
24.4k
    }
466
467
39.2k
    zde->filename = NULL;
468
39.2k
    zde->extra_fields = NULL;
469
39.2k
    zde->comment = NULL;
470
471
39.2k
    variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len;
472
473
39.2k
    if (from_buffer) {
474
31.1k
        if (_zip_buffer_left(buffer) < variable_size) {
475
60
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW);
476
60
            return -1;
477
60
        }
478
31.1k
    }
479
8.11k
    else {
480
8.11k
        _zip_buffer_free(buffer);
481
482
8.11k
        if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
483
19
            return -1;
484
19
        }
485
8.11k
    }
486
487
39.1k
    if (filename_len) {
488
14.9k
        zde->filename = _zip_read_string(buffer, src, filename_len, 1, error);
489
14.9k
        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.9k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
500
6.42k
            if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
501
22
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME);
502
22
                if (!from_buffer) {
503
5
                    _zip_buffer_free(buffer);
504
5
                }
505
22
                return -1;
506
22
            }
507
6.42k
        }
508
509
14.9k
        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
14.9k
    }
523
524
39.1k
    if (ef_len) {
525
12.3k
        zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error);
526
527
12.3k
        if (ef == NULL) {
528
0
            if (!from_buffer) {
529
0
                _zip_buffer_free(buffer);
530
0
            }
531
0
            return -1;
532
0
        }
533
12.3k
        if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
534
132
            free(ef);
535
132
            if (!from_buffer) {
536
21
                _zip_buffer_free(buffer);
537
21
            }
538
132
            return -1;
539
132
        }
540
12.2k
        free(ef);
541
12.2k
        if (local)
542
0
            zde->local_extra_fields_read = 1;
543
12.2k
    }
544
545
38.9k
    if (comment_len) {
546
4.15k
        zde->comment = _zip_read_string(buffer, src, comment_len, 0, error);
547
4.15k
        if (zde->comment == NULL) {
548
0
            if (!from_buffer) {
549
0
                _zip_buffer_free(buffer);
550
0
            }
551
0
            return -1;
552
0
        }
553
4.15k
        if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) {
554
3.33k
            if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) {
555
20
                zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT);
556
20
                if (!from_buffer) {
557
2
                    _zip_buffer_free(buffer);
558
2
                }
559
20
                return -1;
560
20
            }
561
3.33k
        }
562
4.15k
    }
563
564
38.9k
    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
38.9k
    zde->filename = utf8_string;
572
38.9k
    if (!local) {
573
38.9k
        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
38.9k
        zde->comment = utf8_string;
581
38.9k
    }
582
583
    /* Zip64 */
584
585
38.9k
    if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
586
3.92k
        zip_uint16_t got_len;
587
3.92k
        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
3.92k
        if (ef != NULL) {
589
2.78k
            if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) {
590
353
                if (!from_buffer) {
591
3
                    _zip_buffer_free(buffer);
592
3
                }
593
353
                return -1;
594
353
            }
595
2.78k
        }
596
3.57k
        is_zip64 = true;
597
3.57k
    }
598
599
600
38.6k
    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
38.6k
    if (!from_buffer) {
609
8.06k
        _zip_buffer_free(buffer);
610
8.06k
    }
611
612
38.6k
    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
38.6k
    if (zde->offset > ZIP_INT64_MAX) {
643
68
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
644
68
        return -1;
645
68
    }
646
647
38.5k
    if (!_zip_dirent_process_winzip_aes(zde, error)) {
648
55
        return -1;
649
55
    }
650
651
38.5k
    zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
652
653
38.5k
    return (zip_int64_t)size + (zip_int64_t)variable_size;
654
38.5k
}
655
656
bool
657
2.78k
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
2.78k
    zip_buffer_t *ef_buffer;
659
660
2.78k
    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
2.78k
    if (zde->uncomp_size == ZIP_UINT32_MAX) {
666
1.75k
        zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
667
1.75k
    }
668
1.02k
    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
2.78k
    if (zde->comp_size == ZIP_UINT32_MAX) {
674
1.64k
        zde->comp_size = _zip_buffer_get_64(ef_buffer);
675
1.64k
    }
676
2.78k
    if (!local) {
677
2.78k
        if (zde->offset == ZIP_UINT32_MAX) {
678
401
            zde->offset = _zip_buffer_get_64(ef_buffer);
679
401
        }
680
2.78k
        if (zde->disk_number == ZIP_UINT16_MAX) {
681
235
            zde->disk_number = _zip_buffer_get_32(ef_buffer);
682
235
        }
683
2.78k
    }
684
685
2.78k
    if (!_zip_buffer_eof(ef_buffer)) {
686
        /* accept additional fields if values match */
687
1.04k
        bool ok = true;
688
1.04k
        switch (got_len) {
689
719
        case 28:
690
719
            _zip_buffer_set_offset(ef_buffer, 24);
691
719
            if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) {
692
276
                ok = false;
693
276
            }
694
            /* fallthrough */
695
976
        case 24:
696
976
            _zip_buffer_set_offset(ef_buffer, 0);
697
976
            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
289
                ok = false;
699
289
            }
700
976
            break;
701
702
64
        default:
703
64
            ok = false;
704
1.04k
        }
705
1.04k
        if (!ok) {
706
353
            zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF);
707
353
            _zip_buffer_free(ef_buffer);
708
353
            return false;
709
353
        }
710
1.04k
    }
711
2.43k
    _zip_buffer_free(ef_buffer);
712
713
2.43k
    return true;
714
2.78k
}
715
716
717
static zip_string_t *
718
77.9k
_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str, bool check_consistency) {
719
77.9k
    zip_uint16_t ef_len;
720
77.9k
    zip_uint32_t ef_crc;
721
77.9k
    zip_buffer_t *buffer;
722
723
77.9k
    const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
724
725
77.9k
    if (ef == NULL || ef_len < 5 || ef[0] != 1) {
726
72.3k
        return str;
727
72.3k
    }
728
729
5.57k
    if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
730
0
        return str;
731
0
    }
732
733
5.57k
    _zip_buffer_get_8(buffer);
734
5.57k
    ef_crc = _zip_buffer_get_32(buffer);
735
736
5.57k
    if (_zip_string_crc32(str) == ef_crc) {
737
4.50k
        zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer);
738
4.50k
        zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL);
739
740
4.50k
        if (ef_str != NULL) {
741
2.45k
            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
2.45k
            _zip_string_free(str);
750
2.45k
            str = ef_str;
751
2.45k
        }
752
4.50k
    }
753
754
5.57k
    _zip_buffer_free(buffer);
755
756
5.57k
    return str;
757
5.57k
}
758
759
760
static bool
761
38.5k
_zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
762
38.5k
    zip_uint16_t ef_len;
763
38.5k
    zip_buffer_t *buffer;
764
38.5k
    const zip_uint8_t *ef;
765
38.5k
    bool crc_valid;
766
38.5k
    zip_uint16_t enc_method;
767
768
769
38.5k
    if (de->comp_method != ZIP_CM_WINZIP_AES) {
770
37.7k
        return true;
771
37.7k
    }
772
773
796
    ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
774
775
796
    if (ef == NULL || ef_len < 7) {
776
13
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
777
13
        return false;
778
13
    }
779
780
783
    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
783
    crc_valid = true;
788
783
    switch (_zip_buffer_get_16(buffer)) {
789
214
    case 1:
790
214
        break;
791
792
563
    case 2:
793
563
        crc_valid = false;
794
        /* TODO: When checking consistency, check that crc is 0. */
795
563
        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
783
    }
802
803
    /* vendor */
804
777
    if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) {
805
24
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
806
24
        _zip_buffer_free(buffer);
807
24
        return false;
808
24
    }
809
810
    /* mode */
811
753
    switch (_zip_buffer_get_8(buffer)) {
812
379
    case 1:
813
379
        enc_method = ZIP_EM_AES_128;
814
379
        break;
815
110
    case 2:
816
110
        enc_method = ZIP_EM_AES_192;
817
110
        break;
818
257
    case 3:
819
257
        enc_method = ZIP_EM_AES_256;
820
257
        break;
821
7
    default:
822
7
        zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
823
7
        _zip_buffer_free(buffer);
824
7
        return false;
825
753
    }
826
827
746
    if (ef_len != 7) {
828
5
        zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
829
5
        _zip_buffer_free(buffer);
830
5
        return false;
831
5
    }
832
833
741
    de->crc_valid = crc_valid;
834
741
    de->encryption_method = enc_method;
835
741
    de->comp_method = _zip_buffer_get_16(buffer);
836
837
741
    _zip_buffer_free(buffer);
838
741
    return true;
839
746
}
840
841
842
zip_int32_t
843
16.0k
_zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
844
16.0k
    zip_int32_t size;
845
16.0k
    bool local = (flags & ZIP_EF_LOCAL) != 0;
846
16.0k
    int i;
847
16.0k
    zip_uint8_t b[6];
848
16.0k
    zip_buffer_t *buffer;
849
850
16.0k
    size = local ? LENTRYSIZE : CDENTRYSIZE;
851
852
16.0k
    if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
853
303
        zip_error_set_from_source(error, src);
854
303
        return -1;
855
303
    }
856
857
15.7k
    if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
858
299
        return -1;
859
299
    }
860
861
46.2k
    for (i = 0; i < (local ? 2 : 3); i++) {
862
30.8k
        size += _zip_buffer_get_16(buffer);
863
30.8k
    }
864
865
15.4k
    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
15.4k
    _zip_buffer_free(buffer);
872
15.4k
    return size;
873
15.4k
}
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
0
_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
888
0
    zip_dostime_t dostime;
889
0
    zip_encoding_type_t com_enc, name_enc;
890
0
    zip_extra_field_t *ef;
891
0
    zip_extra_field_t *ef64;
892
0
    zip_uint32_t ef_total_size;
893
0
    bool is_zip64;
894
0
    bool is_really_zip64;
895
0
    bool is_winzip_aes;
896
0
    zip_uint8_t buf[CDENTRYSIZE];
897
0
    zip_buffer_t *buffer;
898
899
0
    ef = NULL;
900
901
0
    name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
902
0
    com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
903
904
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))
905
0
        de->bitflags |= ZIP_GPBF_ENCODING_UTF_8;
906
0
    else {
907
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8;
908
0
        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
0
        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
0
    }
923
924
0
    if (de->encryption_method == ZIP_EM_NONE) {
925
0
        de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
926
0
    }
927
0
    else {
928
0
        de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
929
0
    }
930
931
0
    is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
932
0
    is_zip64 = (flags & (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL | ZIP_FL_FORCE_ZIP64) || is_really_zip64;
933
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;
934
935
0
    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
0
    if (is_winzip_aes) {
978
0
        zip_uint8_t data[EF_WINZIP_AES_SIZE];
979
0
        zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data));
980
0
        zip_extra_field_t *ef_winzip;
981
982
0
        if (ef_buffer == NULL) {
983
0
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
984
0
            _zip_ef_free(ef);
985
0
            return -1;
986
0
        }
987
988
0
        _zip_buffer_put_16(ef_buffer, 2);
989
0
        _zip_buffer_put(ef_buffer, "AE", 2);
990
0
        _zip_buffer_put_8(ef_buffer, (zip_uint8_t)(de->encryption_method & 0xff));
991
0
        _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method);
992
993
0
        if (!_zip_buffer_ok(ef_buffer)) {
994
0
            zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
995
0
            _zip_buffer_free(ef_buffer);
996
0
            _zip_ef_free(ef);
997
0
            return -1;
998
0
        }
999
1000
0
        ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH);
1001
0
        _zip_buffer_free(ef_buffer);
1002
0
        ef_winzip->next = ef;
1003
0
        ef = ef_winzip;
1004
0
    }
1005
1006
0
    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
0
    _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
1013
1014
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1015
0
        _zip_buffer_put_16(buffer, de->version_madeby);
1016
0
    }
1017
0
    _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed));
1018
0
    _zip_buffer_put_16(buffer, de->bitflags);
1019
0
    if (is_winzip_aes) {
1020
0
        _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
1021
0
    }
1022
0
    else {
1023
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)ZIP_CM_ACTUAL(de->comp_method));
1024
0
    }
1025
1026
0
    if (ZIP_WANT_TORRENTZIP(za)) {
1027
0
        dostime.time = 0xbc00;
1028
0
        dostime.date = 0x2198;
1029
0
    }
1030
0
    else {
1031
0
        dostime = de->last_mod;
1032
0
    }
1033
0
    _zip_buffer_put_16(buffer, dostime.time);
1034
0
    _zip_buffer_put_16(buffer, dostime.date);
1035
1036
0
    if (is_winzip_aes && de->uncomp_size < 20) {
1037
0
        _zip_buffer_put_32(buffer, 0);
1038
0
    }
1039
0
    else {
1040
0
        _zip_buffer_put_32(buffer, de->crc);
1041
0
    }
1042
1043
0
    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
0
    else {
1053
0
        if (de->comp_size < ZIP_UINT32_MAX) {
1054
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
1055
0
        }
1056
0
        else {
1057
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1058
0
        }
1059
0
        if (de->uncomp_size < ZIP_UINT32_MAX) {
1060
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
1061
0
        }
1062
0
        else {
1063
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1064
0
        }
1065
0
    }
1066
1067
0
    _zip_buffer_put_16(buffer, _zip_string_length(de->filename));
1068
0
    ef_total_size = (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
1069
0
    if (!ZIP_WANT_TORRENTZIP(za)) {
1070
        /* TODO: check for overflow */
1071
0
        ef_total_size += (zip_uint32_t)_zip_ef_size(de->extra_fields, flags);
1072
0
    }
1073
0
    _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
1074
1075
0
    if ((flags & ZIP_FL_LOCAL) == 0) {
1076
0
        _zip_buffer_put_16(buffer, ZIP_WANT_TORRENTZIP(za) ? 0 : _zip_string_length(de->comment));
1077
0
        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
1078
0
        _zip_buffer_put_16(buffer, de->int_attrib);
1079
0
        _zip_buffer_put_32(buffer, de->ext_attrib);
1080
0
        if (de->offset < ZIP_UINT32_MAX)
1081
0
            _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset);
1082
0
        else
1083
0
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
1084
0
    }
1085
1086
0
    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
0
    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
0
    _zip_buffer_free(buffer);
1100
1101
0
    if (de->filename) {
1102
0
        if (_zip_string_write(za, de->filename) < 0) {
1103
0
            _zip_ef_free(ef);
1104
0
            return -1;
1105
0
        }
1106
0
    }
1107
1108
0
    if (ef) {
1109
0
        if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
1110
0
            _zip_ef_free(ef);
1111
0
            return -1;
1112
0
        }
1113
0
    }
1114
0
    _zip_ef_free(ef);
1115
0
    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
0
    if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) {
1122
0
        if (de->comment) {
1123
0
            if (_zip_string_write(za, de->comment) < 0) {
1124
0
                return -1;
1125
0
            }
1126
0
        }
1127
0
    }
1128
1129
1130
0
    return is_zip64;
1131
0
}
1132
1133
1134
time_t
1135
25.6k
_zip_d2u_time(const zip_dostime_t *dtime) {
1136
25.6k
    struct tm tm;
1137
1138
25.6k
    memset(&tm, 0, sizeof(tm));
1139
1140
    /* let mktime decide if DST is in effect */
1141
25.6k
    tm.tm_isdst = -1;
1142
1143
25.6k
    tm.tm_year = ((dtime->date >> 9) & 127) + 1980 - 1900;
1144
25.6k
    tm.tm_mon = ((dtime->date >> 5) & 15) - 1;
1145
25.6k
    tm.tm_mday = dtime->date & 31;
1146
1147
25.6k
    tm.tm_hour = (dtime->time >> 11) & 31;
1148
25.6k
    tm.tm_min = (dtime->time >> 5) & 63;
1149
25.6k
    tm.tm_sec = (dtime->time << 1) & 62;
1150
1151
25.6k
    return mktime(&tm);
1152
25.6k
}
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
76.7k
_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
1196
76.7k
    if (error == NULL)
1197
25.6k
        error = &za->error;
1198
1199
76.7k
    if (idx >= za->nentry) {
1200
0
        zip_error_set(error, ZIP_ER_INVAL, 0);
1201
0
        return NULL;
1202
0
    }
1203
1204
76.7k
    if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) {
1205
76.7k
        if (za->entry[idx].orig == NULL) {
1206
0
            zip_error_set(error, ZIP_ER_INVAL, 0);
1207
0
            return NULL;
1208
0
        }
1209
76.7k
        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
76.7k
        return za->entry[idx].orig;
1214
76.7k
    }
1215
0
    else
1216
0
        return za->entry[idx].changes;
1217
76.7k
}
1218
1219
1220
int
1221
0
_zip_u2d_time(time_t intime, zip_dostime_t *dtime, zip_error_t *ze) {
1222
0
    struct tm *tpm;
1223
0
    struct tm tm;
1224
0
    tpm = zip_localtime(&intime, &tm);
1225
0
    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
0
    if (tpm->tm_year < 80) {
1235
0
        tpm->tm_year = 80;
1236
0
    }
1237
1238
0
    dtime->date = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
1239
0
    dtime->time = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
1240
1241
0
    return 0;
1242
0
}
1243
1244
1245
bool
1246
0
_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64) {
1247
0
    zip_uint16_t length;
1248
0
    bool has_changed = false;
1249
1250
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) {
1251
0
        zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
1252
0
        zip_uint16_t bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask);
1253
0
        if (de->bitflags != bitflags) {
1254
0
            de->bitflags = bitflags;
1255
0
            has_changed = true;
1256
0
        }
1257
0
    }
1258
0
    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
0
    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
0
    zip_uint16_t version_needed;
1274
0
    if (de->comp_method == ZIP_CM_LZMA) {
1275
0
        version_needed = 63;
1276
0
    }
1277
0
    else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) {
1278
0
        version_needed = 51;
1279
0
    }
1280
0
    else if (de->comp_method == ZIP_CM_BZIP2) {
1281
0
        version_needed = 46;
1282
0
    }
1283
0
    else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
1284
0
        version_needed = 45;
1285
0
    }
1286
0
    else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
1287
0
        version_needed = 20;
1288
0
    }
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
0
    if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
1297
0
        version_needed = ZIP_MAX(version_needed, attributes->version_needed);
1298
0
    }
1299
1300
0
    if (de->version_needed != version_needed) {
1301
0
        de->version_needed = version_needed;
1302
0
        has_changed = true;
1303
0
    }
1304
1305
0
    zip_int16_t version_madeby = 63 | (de->version_madeby & 0xff00);
1306
0
    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
0
    if (de->version_madeby != version_madeby) {
1310
0
        de->version_madeby = version_madeby;
1311
0
        has_changed = true;
1312
0
    }
1313
1314
0
    return has_changed;
1315
0
}
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
25.6k
zip_dirent_get_last_mod_mtime(zip_dirent_t *de) {
1368
25.6k
    if (!de->last_mod_mtime_valid) {
1369
25.6k
        de->last_mod_mtime = _zip_d2u_time(&de->last_mod);
1370
25.6k
        de->last_mod_mtime_valid = true;
1371
25.6k
    }
1372
1373
25.6k
    return de->last_mod_mtime;
1374
25.6k
}