From de35a1cd59302a1cc6d3766fcc053b130ab4efa0 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 17 May 2012 00:53:41 -0400 Subject: rpmoffset: add support for LZMA archives The LZMA format lacks proper magic markings (hence one of the driving forces for the new XZ format), so we have to rework things to deal with this fuzzy matching without throwing false positives. URL: https://bugs.gentoo.org/321439 Reported-by: Peter Volkov Signed-off-by: Mike Frysinger --- rpmoffset.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/rpmoffset.c b/rpmoffset.c index 628af93..bd1f456 100644 --- a/rpmoffset.c +++ b/rpmoffset.c @@ -45,6 +45,16 @@ typedef struct { const size_t len; } magic_t; +/* LZMA is some fuzzy crap */ +int is_magic_lzma(const char *buf) +{ + const unsigned char *ubuf = (const void *)buf; + return (ubuf[0] == 0x5d && ubuf[4] < 0x20) && + (!memcmp(buf + 10, "\x00\x00\x00", 3) || + !memcmp(buf + 5, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8)); +} +#define magic_lzma_len 13 + static const unsigned char magic_gzip[] = { '\037', '\213', '\010' }; static const unsigned char magic_bzip2[] = { 'B', 'Z', 'h' }; static const unsigned char magic_xz[] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 }; @@ -56,12 +66,21 @@ static const magic_t magics[] = { #undef DECLARE_MAGIC_T }; #define MAGIC_SIZE_MIN 3 -#define MAGIC_SIZE_MAX 6 +#define MAGIC_SIZE_MAX 13 + +static int show_magic; + +static int magic_finish(const char *magic, size_t offset) +{ + if (show_magic) + printf("%s ", magic); + printf("%zu\n", offset); + return 0; +} int main(int argc, char *argv[]) { - int show_magic = 0; - size_t i, read_cnt, offset, left; + size_t i, read_cnt, offset, left, lzma_offset; FILE *fp = stdin; char p[BUFSIZ]; @@ -76,6 +95,7 @@ int main(int argc, char *argv[]) } /* fp = fopen(argv[1], "r"); */ + lzma_offset = 0; offset = left = 0; while (1) { read_cnt = fread(p + left, 1, sizeof(p) - left, fp); @@ -89,12 +109,17 @@ int main(int argc, char *argv[]) continue; needle = memmem(p, sizeof(p), magics[i].magic, magics[i].len); - if (needle) { - if (show_magic) - printf("%s ", magics[i].type); - printf("%zu\n", offset + (needle - p)); - return 0; - } + if (needle) + return magic_finish(magics[i].type, offset + (needle - p)); + } + + /* Scan for LZMA magic, but don't return yet ... */ + if (!lzma_offset && read_cnt + left >= magic_lzma_len) { + for (i = 0; i <= read_cnt + left - magic_lzma_len; ++i) + if (is_magic_lzma(p + i)) { + lzma_offset = offset + i; + break; + } } memmove(p, p + left + read_cnt - MAGIC_SIZE_MIN + 1, MAGIC_SIZE_MIN - 1); @@ -106,6 +131,10 @@ int main(int argc, char *argv[]) } } + /* Delay till the end for LZMA archives since it is too fuzzy */ + if (lzma_offset) + return magic_finish("lzma", lzma_offset); + if (ferror(stdin)) perror(argv[0]); -- cgit v1.2.3-65-gdbad