From 393fd790b03708585f64b6646c28a09fed44b610 Mon Sep 17 00:00:00 2001 From: Moinak Ghosh Date: Sun, 8 Dec 2013 23:24:06 +0530 Subject: [PATCH] Add more robust checks for Jpeg and packJPG format files in filter routine. Use case-insensitive checks for extension names. Enable more features based on compression level, when archiving. --- archive/pc_arc_filter.c | 25 ++++++++++++++++++------- archive/pc_archive.c | 10 ++++++++-- archive/pjpg_helper.cpp | 3 +++ pcompress.c | 8 ++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/archive/pc_arc_filter.c b/archive/pc_arc_filter.c index 3236f80..c691f75 100644 --- a/archive/pc_arc_filter.c +++ b/archive/pc_arc_filter.c @@ -44,6 +44,8 @@ #define PACKJPG_DEF_BUFSIZ (512 * 1024) #define JPG_SIZE_LIMIT (8 * 1024 * 1024) +#define PJG_APPVERSION1 (25) +#define PJG_APPVERSION2 (25) struct packjpg_filter_data { uchar_t *in_buff; @@ -126,9 +128,12 @@ write_archive_data(struct archive *aw, uchar_t *out_buf, size_t len, int block_s return (tot); } -/* - * Helper routine to bridge to packJPG C++ lib, without changing packJPG itself. - */ +int +pjg_version_supported(char ver) +{ + return (ver >= PJG_APPVERSION1 && ver <= PJG_APPVERSION2); +} + ssize_t packjpg_filter(struct filter_info *fi, void *filter_private) { @@ -150,9 +155,14 @@ packjpg_filter(struct filter_info *fi, void *filter_private) } /* - * We are trying to compress and this is not a jpeg. Skip. + * We are trying to compress and this is not a proper jpeg. Skip. */ - if (mapbuf[0] != 0xFF && mapbuf[1] != 0xD8) { + if (mapbuf[0] != 0xFF || mapbuf[1] != 0xD8) { + munmap(mapbuf, len); + return (FILTER_RETURN_SKIP); + } + if (strncmp((char *)&mapbuf[6], "Exif", 4) != 0 && + strncmp((char *)&mapbuf[6], "JFIF", 4) != 0) { munmap(mapbuf, len); return (FILTER_RETURN_SKIP); } @@ -187,9 +197,10 @@ packjpg_filter(struct filter_info *fi, void *filter_private) /* * We are trying to decompress and this is not a packJPG file. - * Write the raw data and skip. + * Write the raw data and skip. Third byte in PackJPG file is + * version number. We also check if it is supported. */ - if (mapbuf[0] != 'J' && mapbuf[1] != 'S') { + if (mapbuf[0] != 'J' || mapbuf[1] != 'S' || !pjg_version_supported(mapbuf[2])) { return (write_archive_data(fi->target_arc, pjdat->in_buff, len, fi->block_size)); } diff --git a/archive/pc_archive.c b/archive/pc_archive.c index b8c0133..7f97841 100644 --- a/archive/pc_archive.c +++ b/archive/pc_archive.c @@ -1393,13 +1393,15 @@ detect_type_by_ext(const char *path, int pathlen) ub4 slot; int i, len; uint64_t extnum; + char extl[8]; for (i = pathlen-1; i > 0 && path[i] != '.' && path[i] != PATHSEP_CHAR; i--); if (i == 0 || path[i] != '.') goto out; // If extension not found give up len = pathlen - i - 1; - if (len == 0) goto out; // If extension is empty give up + if (len == 0 || len > 8) goto out; // If extension is empty give up ext = &path[i+1]; - slot = phash(ext, len); + for (i = 0; i < len; i++) extl[i] = tolower(ext[i]); + slot = phash(extl, len); if (slot >= PHASHNKEYS) goto out; // Extension maps outside hash table range, give up extnum = 0; @@ -1454,6 +1456,10 @@ out: /* * Detect a few file types from looking at magic signatures. + * NOTE: Jpeg files must be detected via '.jpg' or '.jpeg' (case-insensitive) + * extensions. Do not add Jpeg header detection here. it will break + * context based PackJPG processing. Jpeg files not have proper + * extension must not be processed via PackJPG. */ static int detect_type_by_data(uchar_t *buf, size_t len) diff --git a/archive/pjpg_helper.cpp b/archive/pjpg_helper.cpp index e7fc996..b82c32d 100644 --- a/archive/pjpg_helper.cpp +++ b/archive/pjpg_helper.cpp @@ -65,6 +65,9 @@ typedef unsigned char uchar_t; #define POLAROID_LE 0x64696f72616c6f50 +/* + * Helper routine to bridge to packJPG C++ lib, without changing packJPG itself. + */ size_t packjpg_filter_process(uchar_t *in_buf, size_t len, uchar_t **out_buf) { diff --git a/pcompress.c b/pcompress.c index 2237fb5..d36f906 100644 --- a/pcompress.c +++ b/pcompress.c @@ -3230,6 +3230,14 @@ init_pc_context(pc_ctx_t *pctx, int argc, char *argv[]) if (pctx->level > 8) pctx->dispack_preprocess = 1; if (pctx->level > 4) pctx->enable_delta2_encode = 1; if (pctx->level > 9) pctx->lzp_preprocess = 1; + if (pctx->level > 3) { + pctx->enable_rabin_global = 1; + pctx->enable_rabin_scan = 1; + pctx->enable_rabin_split = 1; + pctx->rab_blk_size = 2; + if (pctx->level > 4) pctx->rab_blk_size = 1; + if (pctx->level > 8) pctx->rab_blk_size = 0; + } } if (pctx->lzp_preprocess || pctx->enable_delta2_encode || pctx->dispack_preprocess) { pctx->preprocess_mode = 1;