"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/libzip/zip_extra_field.c" (10 Oct 2018, 9795 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zip_extra_field.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.21_Source_vs_1.22_Source.

    1 /*
    2   zip_extra_field.c -- manipulate extra fields
    3   Copyright (C) 2012-2017 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, 0);
  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, 0);
  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 }