2 zip_extra_field.c -- manipulate extra fields
3 Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
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
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
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.
41 _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
42 zip_extra_field_t *head, *prev, *def;
47 if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
48 zip_error_set(error, ZIP_ER_MEMORY, 0);
67 _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) {
68 zip_extra_field_t *head, *prev;
74 for (; ef; ef = (prev ? prev->next : head)) {
75 if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
76 if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
77 ef->flags &= ~(flags & ZIP_EF_BOTH);
78 if ((ef->flags & ZIP_EF_BOTH) == 0) {
80 prev->next = ef->next;
86 if (id_idx == ZIP_EXTRA_FIELD_ALL)
103 _zip_ef_free(zip_extra_field_t *ef) {
104 zip_extra_field_t *ef2;
116 _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error) {
117 static const zip_uint8_t empty[1] = {'\0'};
122 for (; ef; ef = ef->next) {
123 if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
138 zip_error_set(error, ZIP_ER_NOENT, 0);
144 _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
145 zip_extra_field_t *ef2, *tt, *tail;
151 for (tail = to; tail->next; tail = tail->next)
154 for (; from; from = ef2) {
158 for (tt = to; tt; tt = tt->next) {
159 if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
160 tt->flags |= (from->flags & ZIP_EF_BOTH);
170 tail = tail->next = from;
178 _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) {
179 zip_extra_field_t *ef;
181 if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
189 if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
202 _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) {
203 zip_buffer_t *buffer;
204 zip_extra_field_t *ef, *ef2, *ef_head;
206 if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
207 zip_error_set(error, ZIP_ER_MEMORY, 0);
213 while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
214 zip_uint16_t fid, flen;
215 zip_uint8_t *ef_data;
217 fid = _zip_buffer_get_16(buffer);
218 flen = _zip_buffer_get_16(buffer);
219 ef_data = _zip_buffer_get(buffer, flen);
221 if (ef_data == NULL) {
222 zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_EF_LENGTH);
223 _zip_buffer_free(buffer);
224 _zip_ef_free(ef_head);
228 if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
229 zip_error_set(error, ZIP_ER_MEMORY, 0);
230 _zip_buffer_free(buffer);
231 _zip_ef_free(ef_head);
243 if (!_zip_buffer_eof(buffer)) {
244 /* Android APK files align stored file data with padding in extra fields; ignore. */
245 /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
246 size_t glen = _zip_buffer_left(buffer);
247 zip_uint8_t *garbage;
248 garbage = _zip_buffer_get(buffer, glen);
249 if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
250 zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE);
251 _zip_buffer_free(buffer);
252 _zip_ef_free(ef_head);
257 _zip_buffer_free(buffer);
260 *ef_head_p = ef_head;
263 _zip_ef_free(ef_head);
271 _zip_ef_remove_internal(zip_extra_field_t *ef) {
272 zip_extra_field_t *ef_head;
273 zip_extra_field_t *prev, *next;
279 if (ZIP_EF_IS_INTERNAL(ef->id)) {
300 _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
304 for (; ef; ef = ef->next) {
305 if (ef->flags & flags & ZIP_EF_BOTH)
306 size = (zip_uint16_t)(size + 4 + ef->size);
314 _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
316 zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
318 if (buffer == NULL) {
322 for (; ef; ef = ef->next) {
323 if (ef->flags & flags & ZIP_EF_BOTH) {
324 _zip_buffer_set_offset(buffer, 0);
325 _zip_buffer_put_16(buffer, ef->id);
326 _zip_buffer_put_16(buffer, ef->size);
327 if (!_zip_buffer_ok(buffer)) {
328 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
329 _zip_buffer_free(buffer);
332 if (_zip_write(za, b, 4) < 0) {
333 _zip_buffer_free(buffer);
337 if (_zip_write(za, ef->data, ef->size) < 0) {
338 _zip_buffer_free(buffer);
345 _zip_buffer_free(buffer);
351 _zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
354 zip_buffer_t *buffer;
355 zip_uint16_t fname_len, ef_len;
357 if (idx >= za->nentry) {
358 zip_error_set(&za->error, ZIP_ER_INVAL, 0);
364 if (e->orig == NULL || e->orig->local_extra_fields_read)
367 if (e->orig->offset + 26 > ZIP_INT64_MAX) {
368 zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
372 if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) {
373 _zip_error_set_from_source(&za->error, za->src);
377 if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
381 fname_len = _zip_buffer_get_16(buffer);
382 ef_len = _zip_buffer_get_16(buffer);
384 if (!_zip_buffer_eof(buffer)) {
385 _zip_buffer_free(buffer);
386 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
390 _zip_buffer_free(buffer);
393 zip_extra_field_t *ef;
396 if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
397 zip_error_set(&za->error, ZIP_ER_SEEK, errno);
401 ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
406 if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
413 ef = _zip_ef_remove_internal(ef);
414 e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
418 e->orig->local_extra_fields_read = 1;
420 if (e->changes && e->changes->local_extra_fields_read == 0) {
421 e->changes->extra_fields = e->orig->extra_fields;
422 e->changes->local_extra_fields_read = 1;