diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2018-11-30 12:40:57 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2018-11-30 12:40:57 +0900 |
commit | 593cf72349c7de430751446480779582c63902f5 (patch) | |
tree | b153eb538266adc810bbdb82deede384f4192cb0 /ext/repo_deb.c | |
parent | c948f862b552adbe2cdee24096357b887dfbb088 (diff) | |
download | libsolv-593cf72349c7de430751446480779582c63902f5.tar.gz libsolv-593cf72349c7de430751446480779582c63902f5.tar.bz2 libsolv-593cf72349c7de430751446480779582c63902f5.zip |
Imported Upstream version 0.6.30upstream/0.6.30
Change-Id: I534bdf20ed04de7ba12fa6f3eabbc9bc7164de6e
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'ext/repo_deb.c')
-rw-r--r-- | ext/repo_deb.c | 166 |
1 files changed, 120 insertions, 46 deletions
diff --git a/ext/repo_deb.c b/ext/repo_deb.c index 812f3d9..277e65a 100644 --- a/ext/repo_deb.c +++ b/ext/repo_deb.c @@ -12,6 +12,7 @@ #include <string.h> #include <unistd.h> #include <zlib.h> +#include <lzma.h> #include <errno.h> #include "pool.h" @@ -22,11 +23,37 @@ #include "repo_deb.h" static unsigned char * -decompress(unsigned char *in, int inl, int *outlp) +decompress_gz(unsigned char *in, int inl, int *outlp, int maxoutl) { z_stream strm; int outl, ret; - unsigned char *out; + unsigned char *bp, *out; + + /* first skip the gz header */ + if (inl <= 10 || in[0] != 0x1f || in[1] != 0x8b) + return 0; + if (in[2] != 8 || (in[3] & 0xe0) != 0) + return 0; + bp = in + 4; + bp += 6; /* skip time, xflags and OS code */ + if (in[3] & 0x04) + { + /* skip extra field */ + int l = bp + 2 >= in + inl ? 0 : (bp[0] | bp[1] << 8); + bp += l + 2; + } + if (in[3] & 0x08) /* orig filename */ + while (bp < in + inl && *bp++) + ; + if (in[3] & 0x10) /* file comment */ + while (bp < in + inl && *bp++) + ; + if (in[3] & 0x02) /* header crc */ + bp += 2; + if (bp >= in + inl) + return 0; + inl -= bp - in; + in = bp; memset(&strm, 0, sizeof(strm)); strm.next_in = in; @@ -46,6 +73,12 @@ decompress(unsigned char *in, int inl, int *outlp) if (strm.avail_out == 0) { outl += 4096; + if (outl >= maxoutl) + { + inflateEnd(&strm); + free(out); + return 0; + } out = solv_realloc(out, outl + 4096); strm.next_out = out + outl; strm.avail_out = 4096; @@ -55,6 +88,7 @@ decompress(unsigned char *in, int inl, int *outlp) break; if (ret != Z_OK) { + inflateEnd(&strm); free(out); return 0; } @@ -65,6 +99,58 @@ decompress(unsigned char *in, int inl, int *outlp) return out; } +static unsigned char * +decompress_xz(unsigned char *in, int inl, int *outlp, int maxoutl) +{ + static lzma_stream stream_init = LZMA_STREAM_INIT; + lzma_stream strm; + int outl, ret; + unsigned char *out; + + strm = stream_init; + strm.next_in = in; + strm.avail_in = inl; + out = solv_malloc(4096); + strm.next_out = out; + strm.avail_out = 4096; + outl = 0; + ret = lzma_auto_decoder(&strm, 100 << 20, 0); + if (ret != LZMA_OK) + { + free(out); + return 0; + } + for (;;) + { + if (strm.avail_out == 0) + { + outl += 4096; + if (outl >= maxoutl) + { + lzma_end(&strm); + free(out); + return 0; + } + out = solv_realloc(out, outl + 4096); + strm.next_out = out + outl; + strm.avail_out = 4096; + } + ret = lzma_code(&strm, LZMA_RUN); + if (ret == LZMA_STREAM_END) + break; + if (ret != LZMA_OK) + { + lzma_end(&strm); + free(out); + return 0; + } + } + outl += 4096 - strm.avail_out; + lzma_end(&strm); + *outlp = outl; + return out; +} + static Id parseonedep(Pool *pool, char *p) { @@ -447,6 +533,10 @@ repo_add_debdb(Repo *repo, int flags) return 0; } +#define CONTROL_COMP_NONE 0 +#define CONTROL_COMP_GZIP 1 +#define CONTROL_COMP_XZ 2 + Id repo_add_deb(Repo *repo, const char *deb, int flags) { @@ -454,6 +544,7 @@ repo_add_deb(Repo *repo, const char *deb, int flags) Repodata *data; unsigned char buf[4096], *bp; int l, l2, vlen, clen, ctarlen; + int control_comp; unsigned char *ctgz; unsigned char pkgid[16]; unsigned char *ctar; @@ -495,16 +586,23 @@ repo_add_deb(Repo *repo, const char *deb, int flags) fclose(fp); return 0; } - if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) != 0 && strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz/ ", 16) != 0) + control_comp = 0; + if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz/ ", 16)) + control_comp = CONTROL_COMP_GZIP; + else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar.xz ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar.xz/ ", 16)) + control_comp = CONTROL_COMP_XZ; + else if (!strncmp((char *)buf + 8 + 60 + vlen, "control.tar ", 16) || !strncmp((char *)buf + 8 + 60 + vlen, "control.tar/ ", 16)) + control_comp = CONTROL_COMP_NONE; + else { - pool_error(pool, -1, "%s: control.tar.gz is not second entry", deb); + pool_error(pool, -1, "%s: control.tar is not second entry", deb); fclose(fp); return 0; } clen = atoi((char *)buf + 8 + 60 + vlen + 48); if (clen <= 0 || clen >= 0x100000) { - pool_error(pool, -1, "%s: control.tar.gz has illegal size", deb); + pool_error(pool, -1, "%s: control.tar has illegal size", deb); fclose(fp); return 0; } @@ -534,55 +632,25 @@ repo_add_deb(Repo *repo, const char *deb, int flags) solv_chksum_free(chk, pkgid); gotpkgid = 1; } - if (ctgz[0] != 0x1f || ctgz[1] != 0x8b) - { - pool_error(pool, -1, "%s: control.tar.gz is not gzipped", deb); - solv_free(ctgz); - return 0; - } - if (ctgz[2] != 8 || (ctgz[3] & 0xe0) != 0) - { - pool_error(pool, -1, "%s: control.tar.gz is compressed in a strange way", deb); - solv_free(ctgz); - return 0; - } - bp = ctgz + 4; - bp += 6; /* skip time, xflags and OS code */ - if (ctgz[3] & 0x04) - { - /* skip extra field */ - l = bp[0] | bp[1] << 8; - bp += l + 2; - if (bp >= ctgz + clen) - { - pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb); - solv_free(ctgz); - return 0; - } - } - if (ctgz[3] & 0x08) /* orig filename */ - while (*bp) - bp++; - if (ctgz[3] & 0x10) /* file comment */ - while (*bp) - bp++; - if (ctgz[3] & 0x02) /* header crc */ - bp += 2; - if (bp >= ctgz + clen) + ctar = 0; + if (control_comp == CONTROL_COMP_GZIP) + ctar = decompress_gz(ctgz, clen, &ctarlen, 0x1000000); + else if (control_comp == CONTROL_COMP_XZ) + ctar = decompress_xz(ctgz, clen, &ctarlen, 0x1000000); + else { - pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb); - solv_free(ctgz); - return 0; + ctarlen = clen; + ctar = solv_memdup(ctgz, clen); } - ctar = decompress(bp, ctgz + clen - bp, &ctarlen); solv_free(ctgz); if (!ctar) { - pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb); + pool_error(pool, -1, "%s: control.tar is corrupt", deb); return 0; } bp = ctar; l = ctarlen; + l2 = 0; while (l > 512) { int j; @@ -590,6 +658,12 @@ repo_add_deb(Repo *repo, const char *deb, int flags) for (j = 124; j < 124 + 12; j++) if (bp[j] >= '0' && bp[j] <= '7') l2 = l2 * 8 + (bp[j] - '0'); + if (l2 < 0 || l2 > l) + { + l2 = 0; + break; + } + bp[124] = 0; if (!strcmp((char *)bp, "./control") || !strcmp((char *)bp, "control")) break; l2 = 512 + ((l2 + 511) & ~511); @@ -598,7 +672,7 @@ repo_add_deb(Repo *repo, const char *deb, int flags) } if (l <= 512 || l - 512 - l2 <= 0 || l2 <= 0) { - pool_error(pool, -1, "%s: control.tar.gz contains no control file", deb); + pool_error(pool, -1, "%s: control.tar contains no control file", deb); free(ctar); return 0; } |