Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/archival/libarchive/get_header_tar.c

    r3232 r3621  
    1717typedef uint32_t aliased_uint32_t FIX_ALIASING;
    1818typedef off_t    aliased_off_t    FIX_ALIASING;
    19 
    20 
    21 const char* FAST_FUNC strip_unsafe_prefix(const char *str)
    22 {
    23     const char *cp = str;
    24     while (1) {
    25         char *cp2;
    26         if (*cp == '/') {
    27             cp++;
    28             continue;
    29         }
    30         if (strncmp(cp, "/../"+1, 3) == 0) {
    31             cp += 3;
    32             continue;
    33         }
    34         cp2 = strstr(cp, "/../");
    35         if (!cp2)
    36             break;
    37         cp = cp2 + 4;
    38     }
    39     if (cp != str) {
    40         static smallint warned = 0;
    41         if (!warned) {
    42             warned = 1;
    43             bb_error_msg("removing leading '%.*s' from member names",
    44                 (int)(cp - str), str);
    45         }
    46     }
    47     return cp;
    48 }
    4919
    5020/* NB: _DESTROYS_ str[len] character! */
     
    9161#define GET_OCTAL(a) getOctal((a), sizeof(a))
    9262
     63#define TAR_EXTD (ENABLE_FEATURE_TAR_GNU_EXTENSIONS || ENABLE_FEATURE_TAR_SELINUX)
     64#if !TAR_EXTD
     65#define process_pax_hdr(archive_handle, sz, global) \
     66    process_pax_hdr(archive_handle, sz)
     67#endif
    9368/* "global" is 0 or 1 */
    9469static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global)
    9570{
     71#if !TAR_EXTD
     72    unsigned blk_sz = (sz + 511) & (~511);
     73    seek_by_read(archive_handle->src_fd, blk_sz);
     74#else
     75    unsigned blk_sz = (sz + 511) & (~511);
    9676    char *buf, *p;
    97     unsigned blk_sz;
    98 
    99     blk_sz = (sz + 511) & (~511);
     77
    10078    p = buf = xmalloc(blk_sz + 1);
    10179    xread(archive_handle->src_fd, buf, blk_sz);
     
    11694        p += len;
    11795        sz -= len;
    118         if ((int)sz < 0
     96        if (
     97        /** (int)sz < 0 - not good enough for huge malicious VALUE of 2^32-1 */
     98            (int)(sz|len) < 0 /* this works */
    11999         || len == 0
    120100         || errno != EINVAL
     
    133113        value = end + 1;
    134114
    135 #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
    136         if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) {
     115# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
     116        if (!global && is_prefixed_with(value, "path=")) {
    137117            value += sizeof("path=") - 1;
    138118            free(archive_handle->tar__longname);
     
    140120            continue;
    141121        }
    142 #endif
    143 
    144 #if ENABLE_FEATURE_TAR_SELINUX
     122# endif
     123
     124# if ENABLE_FEATURE_TAR_SELINUX
    145125        /* Scan for SELinux contexts, via "RHT.security.selinux" keyword.
    146126         * This is what Red Hat's patched version of tar uses.
    147127         */
    148 # define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
    149         if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {
     128#  define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
     129        if (is_prefixed_with(value, SELINUX_CONTEXT_KEYWORD"=")) {
    150130            value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
    151131            free(archive_handle->tar__sctx[global]);
     
    153133            continue;
    154134        }
    155 #endif
     135# endif
    156136    }
    157137
    158138    free(buf);
     139#endif
    159140}
    160141
     
    199180     * saw zero block directly before this. */
    200181    if (i == 0) {
    201         xfunc_error_retval = 0;
    202  short_read:
    203         bb_error_msg_and_die("short read");
     182        bb_error_msg("short read");
     183        /* this merely signals end of archive, not exit(1): */
     184        return EXIT_FAILURE;
    204185    }
    205186    if (i != 512) {
    206187        IF_FEATURE_TAR_AUTODETECT(goto autodetect;)
    207         goto short_read;
     188        bb_error_msg_and_die("short read");
    208189    }
    209190
     
    222203            while (full_read(archive_handle->src_fd, &tar, 512) == 512)
    223204                continue;
    224             return EXIT_FAILURE;
     205            return EXIT_FAILURE; /* "end of archive" */
    225206        }
    226207        archive_handle->tar__end = 1;
    227         return EXIT_SUCCESS;
     208        return EXIT_SUCCESS; /* "decoded one header" */
    228209    }
    229210    archive_handle->tar__end = 0;
     
    231212    /* Check header has valid magic, "ustar" is for the proper tar,
    232213     * five NULs are for the old tar format  */
    233     if (strncmp(tar.magic, "ustar", 5) != 0
     214    if (!is_prefixed_with(tar.magic, "ustar")
    234215     && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
    235216         || memcmp(tar.magic, "\0\0\0\0", 5) != 0)
     
    242223        if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0)
    243224            goto err;
    244         if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_detected:*/ 0) != 0)
     225        if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_compressed:*/ 0) != 0)
    245226 err:
    246227            bb_error_msg_and_die("invalid tar magic");
     
    379360        file_header->mode |= S_IFIFO;
    380361        goto size0;
     362    case 'g':   /* pax global header */
     363    case 'x': { /* pax extended header */
     364        if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
     365            goto skip_ext_hdr;
     366        process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
     367        goto again_after_align;
    381368#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
     369/* See http://www.gnu.org/software/tar/manual/html_node/Extensions.html */
    382370    case 'L':
    383371        /* free: paranoia: tar with several consecutive longnames */
     
    399387        /* return get_header_tar(archive_handle); */
    400388        goto again;
    401     case 'D':   /* GNU dump dir */
    402     case 'M':   /* Continuation of multi volume archive */
    403     case 'N':   /* Old GNU for names > 100 characters */
    404     case 'S':   /* Sparse file */
    405     case 'V':   /* Volume header */
    406 #endif
    407     case 'g':   /* pax global header */
    408     case 'x': { /* pax extended header */
    409         if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
    410             goto skip_ext_hdr;
    411         process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
    412         goto again_after_align;
     389/*
     390 *  case 'S':   // Sparse file
     391 * Was seen in the wild. Not supported (yet?).
     392 * See https://www.gnu.org/software/tar/manual/html_section/tar_92.html
     393 * for the format. (An "Old GNU Format" was seen, not PAX formats).
     394 */
     395//  case 'D':   /* GNU dump dir */
     396//  case 'M':   /* Continuation of multi volume archive */
     397//  case 'N':   /* Old GNU for names > 100 characters */
     398//  case 'V':   /* Volume header */
     399#endif
    413400    }
    414401 skip_ext_hdr:
     
    441428    /* Everything up to and including last ".." component is stripped */
    442429    overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name));
     430//TODO: do the same for file_header->link_target?
    443431
    444432    /* Strip trailing '/' in directories */
     
    472460    free(file_header->tar__gname);
    473461#endif
    474     return EXIT_SUCCESS;
     462    return EXIT_SUCCESS; /* "decoded one header" */
    475463}
Note: See TracChangeset for help on using the changeset viewer.