summaryrefslogtreecommitdiff
path: root/ext/repo_deb.c
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:40:57 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:40:57 +0900
commit593cf72349c7de430751446480779582c63902f5 (patch)
treeb153eb538266adc810bbdb82deede384f4192cb0 /ext/repo_deb.c
parentc948f862b552adbe2cdee24096357b887dfbb088 (diff)
downloadlibsolv-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.c166
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;
}