8983f758cbb50bf88a09d991c183daf33b468f56
[platform/upstream/libzip.git] / lib / zip_extra_field.c
1 /*
2   zip_extra_field.c -- manipulate extra fields
3   Copyright (C) 2012-2021 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 <libzip@nih.at>
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 <stdlib.h>
35 #include <string.h>
36
37 #include "zipint.h"
38
39
40 zip_extra_field_t *
41 _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
42     zip_extra_field_t *head, *prev, *def;
43
44     head = prev = NULL;
45
46     while (ef) {
47         if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
48             zip_error_set(error, ZIP_ER_MEMORY, 0);
49             _zip_ef_free(head);
50             return NULL;
51         }
52
53         if (head == NULL)
54             head = def;
55         if (prev)
56             prev->next = def;
57         prev = def;
58
59         ef = ef->next;
60     }
61
62     return head;
63 }
64
65
66 zip_extra_field_t *
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;
69     int i;
70
71     i = 0;
72     head = ef;
73     prev = NULL;
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) {
79                     if (prev)
80                         prev->next = ef->next;
81                     else
82                         head = ef->next;
83                     ef->next = NULL;
84                     _zip_ef_free(ef);
85
86                     if (id_idx == ZIP_EXTRA_FIELD_ALL)
87                         continue;
88                 }
89             }
90
91             i++;
92             if (i > id_idx)
93                 break;
94         }
95         prev = ef;
96     }
97
98     return head;
99 }
100
101
102 void
103 _zip_ef_free(zip_extra_field_t *ef) {
104     zip_extra_field_t *ef2;
105
106     while (ef) {
107         ef2 = ef->next;
108         free(ef->data);
109         free(ef);
110         ef = ef2;
111     }
112 }
113
114
115 const zip_uint8_t *
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'};
118
119     int i;
120
121     i = 0;
122     for (; ef; ef = ef->next) {
123         if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
124             if (i < id_idx) {
125                 i++;
126                 continue;
127             }
128
129             if (lenp)
130                 *lenp = ef->size;
131             if (ef->size > 0)
132                 return ef->data;
133             else
134                 return empty;
135         }
136     }
137
138     zip_error_set(error, ZIP_ER_NOENT, 0);
139     return NULL;
140 }
141
142
143 zip_extra_field_t *
144 _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
145     zip_extra_field_t *ef2, *tt, *tail;
146     int duplicate;
147
148     if (to == NULL)
149         return from;
150
151     for (tail = to; tail->next; tail = tail->next)
152         ;
153
154     for (; from; from = ef2) {
155         ef2 = from->next;
156
157         duplicate = 0;
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);
161                 duplicate = 1;
162                 break;
163             }
164         }
165
166         from->next = NULL;
167         if (duplicate)
168             _zip_ef_free(from);
169         else
170             tail = tail->next = from;
171     }
172
173     return to;
174 }
175
176
177 zip_extra_field_t *
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;
180
181     if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
182         return NULL;
183
184     ef->next = NULL;
185     ef->flags = flags;
186     ef->id = id;
187     ef->size = size;
188     if (size > 0) {
189         if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
190             free(ef);
191             return NULL;
192         }
193     }
194     else
195         ef->data = NULL;
196
197     return ef;
198 }
199
200
201 bool
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;
205
206     if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
207         zip_error_set(error, ZIP_ER_MEMORY, 0);
208         return false;
209     }
210
211     ef_head = ef = NULL;
212
213     while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
214         zip_uint16_t fid, flen;
215         zip_uint8_t *ef_data;
216
217         fid = _zip_buffer_get_16(buffer);
218         flen = _zip_buffer_get_16(buffer);
219         ef_data = _zip_buffer_get(buffer, flen);
220
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);
225             return false;
226         }
227
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);
232             return false;
233         }
234
235         if (ef_head) {
236             ef->next = ef2;
237             ef = ef2;
238         }
239         else
240             ef_head = ef = ef2;
241     }
242
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);
253             return false;
254         }
255     }
256
257     _zip_buffer_free(buffer);
258
259     if (ef_head_p) {
260         *ef_head_p = ef_head;
261     }
262     else {
263         _zip_ef_free(ef_head);
264     }
265
266     return true;
267 }
268
269
270 zip_extra_field_t *
271 _zip_ef_remove_internal(zip_extra_field_t *ef) {
272     zip_extra_field_t *ef_head;
273     zip_extra_field_t *prev, *next;
274
275     ef_head = ef;
276     prev = NULL;
277
278     while (ef) {
279         if (ZIP_EF_IS_INTERNAL(ef->id)) {
280             next = ef->next;
281             if (ef_head == ef)
282                 ef_head = next;
283             ef->next = NULL;
284             _zip_ef_free(ef);
285             if (prev)
286                 prev->next = next;
287             ef = next;
288         }
289         else {
290             prev = ef;
291             ef = ef->next;
292         }
293     }
294
295     return ef_head;
296 }
297
298
299 zip_uint16_t
300 _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
301     zip_uint16_t size;
302
303     size = 0;
304     for (; ef; ef = ef->next) {
305         if (ef->flags & flags & ZIP_EF_BOTH)
306             size = (zip_uint16_t)(size + 4 + ef->size);
307     }
308
309     return size;
310 }
311
312
313 int
314 _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
315     zip_uint8_t b[4];
316     zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
317
318     if (buffer == NULL) {
319         return -1;
320     }
321
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);
330                 return -1;
331             }
332             if (_zip_write(za, b, 4) < 0) {
333                 _zip_buffer_free(buffer);
334                 return -1;
335             }
336             if (ef->size > 0) {
337                 if (_zip_write(za, ef->data, ef->size) < 0) {
338                     _zip_buffer_free(buffer);
339                     return -1;
340                 }
341             }
342         }
343     }
344
345     _zip_buffer_free(buffer);
346     return 0;
347 }
348
349
350 int
351 _zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
352     zip_entry_t *e;
353     unsigned char b[4];
354     zip_buffer_t *buffer;
355     zip_uint16_t fname_len, ef_len;
356
357     if (idx >= za->nentry) {
358         zip_error_set(&za->error, ZIP_ER_INVAL, 0);
359         return -1;
360     }
361
362     e = za->entry + idx;
363
364     if (e->orig == NULL || e->orig->local_extra_fields_read)
365         return 0;
366
367     if (e->orig->offset + 26 > ZIP_INT64_MAX) {
368         zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
369         return -1;
370     }
371
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);
374         return -1;
375     }
376
377     if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
378         return -1;
379     }
380
381     fname_len = _zip_buffer_get_16(buffer);
382     ef_len = _zip_buffer_get_16(buffer);
383
384     if (!_zip_buffer_eof(buffer)) {
385         _zip_buffer_free(buffer);
386         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
387         return -1;
388     }
389
390     _zip_buffer_free(buffer);
391
392     if (ef_len > 0) {
393         zip_extra_field_t *ef;
394         zip_uint8_t *ef_raw;
395
396         if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
397             zip_error_set(&za->error, ZIP_ER_SEEK, errno);
398             return -1;
399         }
400
401         ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
402
403         if (ef_raw == NULL)
404             return -1;
405
406         if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
407             free(ef_raw);
408             return -1;
409         }
410         free(ef_raw);
411
412         if (ef) {
413             ef = _zip_ef_remove_internal(ef);
414             e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
415         }
416     }
417
418     e->orig->local_extra_fields_read = 1;
419
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;
423     }
424
425     return 0;
426 }