Rizin
unix-like reverse engineering framework and cli tools
zip_extra_field.c File Reference
#include <stdlib.h>
#include <string.h>
#include "zipint.h"

Go to the source code of this file.

Functions

zip_extra_field_t_zip_ef_clone (const zip_extra_field_t *ef, zip_error_t *error)
 
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)
 
void _zip_ef_free (zip_extra_field_t *ef)
 
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)
 
zip_extra_field_t_zip_ef_merge (zip_extra_field_t *to, zip_extra_field_t *from)
 
zip_extra_field_t_zip_ef_new (zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, 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_extra_field_t_zip_ef_remove_internal (zip_extra_field_t *ef)
 
zip_uint16_t _zip_ef_size (const zip_extra_field_t *ef, zip_flags_t flags)
 
int _zip_ef_write (zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags)
 
int _zip_read_local_ef (zip_t *za, zip_uint64_t idx)
 

Function Documentation

◆ _zip_ef_clone()

zip_extra_field_t* _zip_ef_clone ( const zip_extra_field_t ef,
zip_error_t error 
)

Definition at line 41 of file zip_extra_field.c.

41  {
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 }
#define NULL
Definition: cris-opc.c:27
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_ER_MEMORY
Definition: zip.h:119
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
zip_extra_field_t * next
Definition: zipint.h:368
void error(const char *msg)
Definition: untgz.c:593
zip_extra_field_t * _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags)
void _zip_ef_free(zip_extra_field_t *ef)
int def(FILE *source, FILE *dest, int level)
Definition: zpipe.c:36

References _zip_ef_free(), _zip_ef_new(), ef::data, def(), error(), ef::flags, test-lz4-versions::head, ef::id, zip_extra_field::next, NULL, ef::size, ZIP_ER_MEMORY, and zip_error_set().

Referenced by _zip_file_extra_field_prepare_for_change().

◆ _zip_ef_delete_by_id()

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 
)

Definition at line 67 of file zip_extra_field.c.

67  {
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 }
#define ef(frag,...)
lzma_index ** i
Definition: index.h:629
#define ZIP_EXTRA_FIELD_ALL
Definition: zip.h:99
int id
Definition: op.c:540
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define ZIP_EF_BOTH
Definition: zipint.h:245

References _zip_ef_free(), ef, flags, ef::flags, test-lz4-versions::head, i, id, ef::id, zip_extra_field::next, NULL, ZIP_EF_BOTH, and ZIP_EXTRA_FIELD_ALL.

Referenced by zip_file_extra_field_delete(), and zip_file_extra_field_delete_by_id().

◆ _zip_ef_free()

void _zip_ef_free ( zip_extra_field_t ef)

Definition at line 103 of file zip_extra_field.c.

103  {
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 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References ef::data, and free().

Referenced by _zip_dirent_finalize(), _zip_dirent_write(), _zip_ef_clone(), _zip_ef_delete_by_id(), _zip_ef_merge(), _zip_ef_parse(), _zip_ef_remove_internal(), and zip_file_extra_field_set().

◆ _zip_ef_get_by_id()

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 
)

Definition at line 116 of file zip_extra_field.c.

116  {
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 }
#define ZIP_ER_NOENT
Definition: zip.h:114
uint8_t zip_uint8_t
Definition: zipconf.h:33

References ef::data, ef, error(), flags, ef::flags, i, ef::id, NULL, ef::size, ZIP_EF_BOTH, ZIP_ER_NOENT, and zip_error_set().

Referenced by _zip_dirent_process_ef_utf_8(), _zip_dirent_process_winzip_aes(), _zip_dirent_read(), and zip_file_extra_field_get_by_id().

◆ _zip_ef_merge()

zip_extra_field_t* _zip_ef_merge ( zip_extra_field_t to,
zip_extra_field_t from 
)

Definition at line 144 of file zip_extra_field.c.

144  {
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 }
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
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_uint16_t id
Definition: zipint.h:370

References _zip_ef_free(), zip_extra_field::data, zip_extra_field::flags, from, zip_extra_field::id, zip_extra_field::next, NULL, zip_extra_field::size, to, and ZIP_EF_BOTH.

Referenced by _zip_checkcons(), and _zip_read_local_ef().

◆ _zip_ef_new()

zip_extra_field_t* _zip_ef_new ( zip_uint16_t  id,
zip_uint16_t  size,
const zip_uint8_t data,
zip_flags_t  flags 
)

Definition at line 178 of file zip_extra_field.c.

178  {
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 }
voidpf void uLong size
Definition: ioapi.h:138
void * malloc(size_t size)
Definition: malloc.c:123
void * _zip_memdup(const void *mem, size_t len, zip_error_t *error)
Definition: zip_memdup.c:41

References _zip_memdup(), ef::data, ef, flags, ef::flags, free(), id, ef::id, malloc(), NULL, and ef::size.

Referenced by _zip_dirent_write(), _zip_ef_clone(), _zip_ef_parse(), _zip_ef_utf8(), and zip_file_extra_field_set().

◆ _zip_ef_parse()

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 
)

Definition at line 202 of file zip_extra_field.c.

202  {
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 }
size_t len
Definition: 6502dis.c:15
struct buffer buffer
#define ZIP_ER_INCONS
Definition: zip.h:126
Definition: buffer.h:15
zip_uint64_t _zip_buffer_left(zip_buffer_t *buffer)
Definition: zip_buffer.c:128
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
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
zip_uint8_t * _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length)
Definition: zip_buffer.c:66
uint16_t zip_uint16_t
Definition: zipconf.h:35
#define ZIP_ER_DETAIL_INVALID_EF_LENGTH
Definition: zipint.h:231
#define ZIP_ER_DETAIL_EF_TRAILING_GARBAGE
Definition: zipint.h:230

References _zip_buffer_eof(), _zip_buffer_free(), _zip_buffer_get(), _zip_buffer_get_16(), _zip_buffer_left(), _zip_buffer_new(), _zip_buffer_ok(), _zip_ef_free(), _zip_ef_new(), ef, error(), flags, len, NULL, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE, ZIP_ER_DETAIL_INVALID_EF_LENGTH, ZIP_ER_INCONS, ZIP_ER_MEMORY, and zip_error_set().

Referenced by _zip_dirent_read(), and _zip_read_local_ef().

◆ _zip_ef_remove_internal()

zip_extra_field_t* _zip_ef_remove_internal ( zip_extra_field_t ef)

Definition at line 271 of file zip_extra_field.c.

271  {
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 }
#define ZIP_EF_IS_INTERNAL(id)
Definition: zipint.h:90

References _zip_ef_free(), ef, ef::id, zip_extra_field::next, NULL, and ZIP_EF_IS_INTERNAL.

Referenced by _zip_dirent_read(), and _zip_read_local_ef().

◆ _zip_ef_size()

zip_uint16_t _zip_ef_size ( const zip_extra_field_t ef,
zip_flags_t  flags 
)

Definition at line 300 of file zip_extra_field.c.

300  {
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 }

References ef, flags, ef::flags, ef::size, and ZIP_EF_BOTH.

Referenced by _zip_dirent_write(), and zip_file_extra_field_set().

◆ _zip_ef_write()

int _zip_ef_write ( zip_t za,
const zip_extra_field_t ef,
zip_flags_t  flags 
)

Definition at line 314 of file zip_extra_field.c.

314  {
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 }
#define ZIP_ER_INTERNAL
Definition: zip.h:125
#define b(i)
Definition: sha256.c:42
zip_error_t error
Definition: zipint.h:281
int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i)
Definition: zip_buffer.c:230
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset)
Definition: zip_buffer.c:297
int _zip_write(zip_t *za, const void *data, zip_uint64_t length)
Definition: zip_io_util.c:121
zip_t * za
Definition: ziptool.c:79

References _zip_buffer_free(), _zip_buffer_new(), _zip_buffer_ok(), _zip_buffer_put_16(), _zip_buffer_set_offset(), _zip_write(), b, ef::data, ef, zip::error, flags, ef::flags, ef::id, NULL, ef::size, za, ZIP_EF_BOTH, ZIP_ER_INTERNAL, and zip_error_set().

Referenced by _zip_dirent_write().

◆ _zip_read_local_ef()

int _zip_read_local_ef ( zip_t za,
zip_uint64_t  idx 
)

Definition at line 351 of file zip_extra_field.c.

351  {
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 }
#define e(frag)
#define ZIP_ER_SEEK
Definition: zip.h:109
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int)
#define ZIP_ER_INVAL
Definition: zip.h:123
int idx
Definition: setup.py:197
#define EFBIG
Definition: sftypes.h:137
Definition: zipint.h:408
zip_source_t * src
Definition: zipint.h:279
zip_entry_t * entry
Definition: zipint.h:294
zip_uint64_t nentry
Definition: zipint.h:292
#define SEEK_SET
Definition: zip.c:88
#define SEEK_CUR
Definition: zip.c:80
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
void _zip_error_set_from_source(zip_error_t *err, zip_source_t *src)
Definition: zip_error.c:135
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_extra_field_t * _zip_ef_remove_internal(zip_extra_field_t *ef)
zip_extra_field_t * _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from)
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
#define ZIP_INT64_MAX
Definition: zipconf.h:54
int64_t zip_int64_t
Definition: zipconf.h:38
#define ZIP_EF_LOCAL
Definition: zipint.h:243

References _zip_buffer_eof(), _zip_buffer_free(), _zip_buffer_get_16(), _zip_buffer_new_from_source(), _zip_ef_merge(), _zip_ef_parse(), _zip_ef_remove_internal(), _zip_error_set_from_source(), _zip_read_data(), b, e, ef, EFBIG, zip::entry, zip::error, free(), setup::idx, zip::nentry, NULL, SEEK_CUR, SEEK_SET, zip::src, za, ZIP_EF_LOCAL, ZIP_ER_INTERNAL, ZIP_ER_INVAL, ZIP_ER_SEEK, zip_error_set(), ZIP_INT64_MAX, and zip_source_seek().

Referenced by _zip_file_extra_field_prepare_for_change(), zip_close(), zip_file_extra_field_get(), zip_file_extra_field_get_by_id(), zip_file_extra_fields_count(), and zip_file_extra_fields_count_by_id().