Merge pull request #1001 from rouault/subtile_decoding_stage2
authorEven Rouault <even.rouault@mines-paris.org>
Mon, 21 Aug 2017 11:02:07 +0000 (13:02 +0200)
committerGitHub <noreply@github.com>
Mon, 21 Aug 2017 11:02:07 +0000 (13:02 +0200)
Subtile decoding: only apply IDWT on areas that participate to the window of interest

src/bin/jp2/convert.c
src/bin/jp2/convertbmp.c

index 5459f7d44533e0fccc66a4be5eb7fc01cc7f731c..d7306fd80902732ff30bdc1c089814b23781cc4e 100644 (file)
@@ -1163,6 +1163,7 @@ opj_image_t* pgxtoimage(const char *filename, opj_cparameters_t *parameters)
     opj_image_cmptparm_t cmptparm;  /* maximum of 1 component  */
     opj_image_t * image = NULL;
     int adjustS, ushift, dshift, force8;
+    OPJ_UINT64 expected_file_size;
 
     char endian1, endian2, sign;
     char signtmp[32];
@@ -1185,7 +1186,7 @@ opj_image_t* pgxtoimage(const char *filename, opj_cparameters_t *parameters)
     }
 
     fseek(f, 0, SEEK_SET);
-    if (fscanf(f, "PG%[ \t]%c%c%[ \t+-]%d%[ \t]%d%[ \t]%d", temp, &endian1,
+    if (fscanf(f, "PG%31[ \t]%c%c%31[ \t+-]%d%31[ \t]%d%31[ \t]%d", temp, &endian1,
                &endian2, signtmp, &prec, temp, &w, temp, &h) != 9) {
         fclose(f);
         fprintf(stderr,
@@ -1213,6 +1214,29 @@ opj_image_t* pgxtoimage(const char *filename, opj_cparameters_t *parameters)
         return NULL;
     }
 
+    if (w < 1 || h < 1 || prec < 1 || prec > 31) {
+        fclose(f);
+        fprintf(stderr, "Bad pgx header, please check input file\n");
+        return NULL;
+    }
+
+    expected_file_size =
+        (OPJ_UINT64)w * (OPJ_UINT64)h * (prec > 16 ? 4 : prec > 8 ? 2 : 1);
+    if (expected_file_size > 10000000U) {
+        char ch;
+        long curpos = ftell(f);
+        if (expected_file_size > (OPJ_UINT64)INT_MAX) {
+            expected_file_size = (OPJ_UINT64)INT_MAX;
+        }
+        fseek(f, (long)expected_file_size - 1, SEEK_SET);
+        if (fread(&ch, 1, 1, f) != 1) {
+            fprintf(stderr, "File too short\n");
+            fclose(f);
+            return NULL;
+        }
+        fseek(f, curpos, SEEK_SET);
+    }
+
     /* initialize image component */
 
     cmptparm.x0 = (OPJ_UINT32)parameters->image_offset_x0;
index 2715fdf2411cad1724928ced819d0e1159234f3b..084f70bb75f86ad6ff52bacba10cbe50264b9cdc 100644 (file)
@@ -529,10 +529,19 @@ static OPJ_BOOL bmp_read_rle8_data(FILE* IN, OPJ_UINT8* pData,
     x = y = 0U;
     while (y < height) {
         int c = getc(IN);
+        if (c == EOF) {
+            return OPJ_FALSE;
+        }
 
         if (c) {
-            int j;
-            OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN);
+            int j, c1_int;
+            OPJ_UINT8 c1;
+
+            c1_int = getc(IN);
+            if (c1_int == EOF) {
+                return OPJ_FALSE;
+            }
+            c1 = (OPJ_UINT8)c1_int;
 
             for (j = 0; (j < c) && (x < width) &&
                     ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
@@ -540,6 +549,10 @@ static OPJ_BOOL bmp_read_rle8_data(FILE* IN, OPJ_UINT8* pData,
             }
         } else {
             c = getc(IN);
+            if (c == EOF) {
+                return OPJ_FALSE;
+            }
+
             if (c == 0x00) { /* EOL */
                 x = 0;
                 ++y;
@@ -548,19 +561,34 @@ static OPJ_BOOL bmp_read_rle8_data(FILE* IN, OPJ_UINT8* pData,
                 break;
             } else if (c == 0x02) { /* MOVE by dxdy */
                 c = getc(IN);
+                if (c == EOF) {
+                    return OPJ_FALSE;
+                }
                 x += (OPJ_UINT32)c;
                 c = getc(IN);
+                if (c == EOF) {
+                    return OPJ_FALSE;
+                }
                 y += (OPJ_UINT32)c;
                 pix = pData + y * stride + x;
             } else { /* 03 .. 255 */
                 int j;
                 for (j = 0; (j < c) && (x < width) &&
                         ((OPJ_SIZE_T)pix < (OPJ_SIZE_T)beyond); j++, x++, pix++) {
-                    OPJ_UINT8 c1 = (OPJ_UINT8)getc(IN);
+                    int c1_int;
+                    OPJ_UINT8 c1;
+                    c1_int = getc(IN);
+                    if (c1_int == EOF) {
+                        return OPJ_FALSE;
+                    }
+                    c1 = (OPJ_UINT8)c1_int;
                     *pix = c1;
                 }
                 if ((OPJ_UINT32)c & 1U) { /* skip padding byte */
-                    getc(IN);
+                    c = getc(IN);
+                    if (c == EOF) {
+                        return OPJ_FALSE;
+                    }
                 }
             }
         }