Rizin
unix-like reverse engineering framework and cli tools
zip_extra_field.c
Go to the documentation of this file.
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 <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 <stdlib.h>
35 #include <string.h>
36 
37 #include "zipint.h"
38 
39 
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) {
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 
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;
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
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 *
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 
139  return NULL;
140 }
141 
142 
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)
169  else
170  tail = tail->next = from;
171  }
172 
173  return to;
174 }
175 
176 
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
204  zip_extra_field_t *ef, *ef2, *ef_head;
205 
206  if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
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) {
224  _zip_ef_free(ef_head);
225  return false;
226  }
227 
228  if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
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) {
252  _zip_ef_free(ef_head);
253  return false;
254  }
255  }
256 
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 
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 
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
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) {
327  if (!_zip_buffer_ok(buffer)) {
330  return -1;
331  }
332  if (_zip_write(za, b, 4) < 0) {
334  return -1;
335  }
336  if (ef->size > 0) {
337  if (_zip_write(za, ef->data, ef->size) < 0) {
339  return -1;
340  }
341  }
342  }
343  }
344 
346  return 0;
347 }
348 
349 
350 int
352  zip_entry_t *e;
353  unsigned char b[4];
355  zip_uint16_t fname_len, ef_len;
356 
357  if (idx >= za->nentry) {
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) {
369  return -1;
370  }
371 
372  if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) {
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)) {
387  return -1;
388  }
389 
391 
392  if (ef_len > 0) {
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) {
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 }
size_t len
Definition: 6502dis.c:15
#define ef(frag,...)
#define e(frag)
lzma_index ** i
Definition: index.h:629
struct buffer buffer
#define NULL
Definition: cris-opc.c:27
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
#define ZIP_ER_INTERNAL
Definition: zip.h:125
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_EXTRA_FIELD_ALL
Definition: zip.h:99
#define ZIP_ER_SEEK
Definition: zip.h:109
#define ZIP_ER_MEMORY
Definition: zip.h:119
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int)
#define ZIP_ER_NOENT
Definition: zip.h:114
#define ZIP_ER_INVAL
Definition: zip.h:123
zip_uint32_t zip_flags_t
Definition: zip.h:347
#define ZIP_ER_INCONS
Definition: zip.h:126
void * malloc(size_t size)
Definition: malloc.c:123
int idx
Definition: setup.py:197
int id
Definition: op.c:540
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define EFBIG
Definition: sftypes.h:137
#define b(i)
Definition: sha256.c:42
Definition: buffer.h:15
Definition: zipcmp.c:69
zip_uint16_t size
Definition: zipcmp.c:73
zip_uint16_t id
Definition: zipcmp.c:72
const zip_uint8_t * data
Definition: zipcmp.c:74
zip_uint16_t flags
Definition: zipcmp.c:71
Definition: zipint.h:408
Definition: zip.h:284
zip_uint8_t * data
Definition: zipint.h:372
zip_uint16_t size
Definition: zipint.h:371
zip_flags_t flags
Definition: zipint.h:369
zip_extra_field_t * next
Definition: zipint.h:368
zip_uint16_t id
Definition: zipint.h:370
Definition: zipint.h:278
zip_error_t error
Definition: zipint.h:281
zip_source_t * src
Definition: zipint.h:279
zip_entry_t * entry
Definition: zipint.h:294
zip_uint64_t nentry
Definition: zipint.h:292
void error(const char *msg)
Definition: untgz.c:593
#define SEEK_SET
Definition: zip.c:88
#define SEEK_CUR
Definition: zip.c:80
zip_uint64_t _zip_buffer_left(zip_buffer_t *buffer)
Definition: zip_buffer.c:128
int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i)
Definition: zip_buffer.c:230
zip_buffer_t * _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size)
Definition: zip_buffer.c:146
void _zip_buffer_free(zip_buffer_t *buffer)
Definition: zip_buffer.c:46
zip_buffer_t * _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error)
Definition: zip_buffer.c:174
bool _zip_buffer_ok(zip_buffer_t *buffer)
Definition: zip_buffer.c:198
zip_uint16_t _zip_buffer_get_16(zip_buffer_t *buffer)
Definition: zip_buffer.c:80
bool _zip_buffer_eof(zip_buffer_t *buffer)
Definition: zip_buffer.c:60
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset)
Definition: zip_buffer.c:297
zip_uint8_t * _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length)
Definition: zip_buffer.c:66
void _zip_error_set_from_source(zip_error_t *err, zip_source_t *src)
Definition: zip_error.c:135
zip_extra_field_t * _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags)
bool _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)
zip_uint16_t _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags)
int _zip_read_local_ef(zip_t *za, zip_uint64_t idx)
zip_extra_field_t * _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error)
zip_extra_field_t * _zip_ef_remove_internal(zip_extra_field_t *ef)
zip_extra_field_t * _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags)
zip_extra_field_t * _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from)
int _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags)
const zip_uint8_t * _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)
void _zip_ef_free(zip_extra_field_t *ef)
zip_uint8_t * _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error)
Definition: zip_io_util.c:63
int _zip_write(zip_t *za, const void *data, zip_uint64_t length)
Definition: zip_io_util.c:121
void * _zip_memdup(const void *mem, size_t len, zip_error_t *error)
Definition: zip_memdup.c:41
uint64_t zip_uint64_t
Definition: zipconf.h:39
uint8_t zip_uint8_t
Definition: zipconf.h:33
uint16_t zip_uint16_t
Definition: zipconf.h:35
#define ZIP_INT64_MAX
Definition: zipconf.h:54
int64_t zip_int64_t
Definition: zipconf.h:38
#define ZIP_EF_BOTH
Definition: zipint.h:245
#define ZIP_EF_LOCAL
Definition: zipint.h:243
#define ZIP_EF_IS_INTERNAL(id)
Definition: zipint.h:90
#define ZIP_ER_DETAIL_INVALID_EF_LENGTH
Definition: zipint.h:231
#define ZIP_ER_DETAIL_EF_TRAILING_GARBAGE
Definition: zipint.h:230
zip_t * za
Definition: ziptool.c:79
int def(FILE *source, FILE *dest, int level)
Definition: zpipe.c:36