Browse code

fuzz - 12168 - Fix for 1 byte out of bounds read in PDF parser. Fix includes a check to ensure that it is safe to index -1 from the start of an object a well as additional checks to invalidate some negative integer values.

Micah Snyder authored on 2019/01/23 04:15:46
Showing 1 changed files
... ...
@@ -299,6 +299,7 @@ int pdf_findobj_in_objstm(struct pdf_struct *pdf, struct objstm_struct *objstm,
299 299
     cl_error_t status = CL_EPARSE;
300 300
     struct pdf_obj *obj = NULL;
301 301
     unsigned long objid = 0, objsize = 0, objoff = 0;
302
+    long temp_long         = 0;
302 303
     const char *index = NULL;
303 304
     size_t bytes_remaining = 0;
304 305
 
... ...
@@ -323,12 +324,17 @@ int pdf_findobj_in_objstm(struct pdf_struct *pdf, struct objstm_struct *objstm,
323 323
     obj->objstm = objstm;
324 324
 
325 325
     /* objstm->current_pair points directly to the obj id */
326
-    if (CL_SUCCESS != cli_strntoul_wrap(index, bytes_remaining, 0, 10, &objid)) {
326
+    if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) {
327 327
         /* Failed to find objid */
328 328
         cli_dbgmsg("pdf_findobj_in_objstm: Failed to find objid for obj in object stream\n");
329 329
         status = CL_EPARSE;
330 330
         goto done;
331
+    } else if (temp_long < 0) {
332
+        cli_dbgmsg("pdf_findobj_in_objstm: Encountered invalid negative objid (%ld).\n", temp_long);
333
+        status = CL_EPARSE;
334
+        goto done;
331 335
     }
336
+    objid = (unsigned long)temp_long;
332 337
 
333 338
     /* Find the obj offset that appears just after the obj id*/
334 339
     while ((index < objstm->streambuf + objstm->streambuf_len) && isdigit(*index)) {
... ...
@@ -338,12 +344,17 @@ int pdf_findobj_in_objstm(struct pdf_struct *pdf, struct objstm_struct *objstm,
338 338
     index = findNextNonWS(index, objstm->streambuf + objstm->first);
339 339
     bytes_remaining = objstm->streambuf + objstm->streambuf_len - index;
340 340
 
341
-    if (CL_SUCCESS != cli_strntoul_wrap(index, bytes_remaining, 0, 10, &objoff)) {
341
+    if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) {
342 342
         /* Failed to find obj offset */
343 343
         cli_dbgmsg("pdf_findobj_in_objstm: Failed to find obj offset for obj in object stream\n");
344 344
         status = CL_EPARSE;
345 345
         goto done;
346
+    } else if (temp_long < 0) {
347
+        cli_dbgmsg("pdf_findobj_in_objstm: Encountered invalid negative obj offset (%ld).\n", temp_long);
348
+        status = CL_EPARSE;
349
+        goto done;
346 350
     }
351
+    objoff = (unsigned long)temp_long;
347 352
 
348 353
     if ((size_t)objstm->first + (size_t)objoff > objstm->streambuf_len) {
349 354
         /* Alleged obj location is further than the length of the stream */
... ...
@@ -382,12 +393,17 @@ int pdf_findobj_in_objstm(struct pdf_struct *pdf, struct objstm_struct *objstm,
382 382
         index = objstm->streambuf + objstm->current_pair;
383 383
         bytes_remaining = objstm->streambuf + objstm->streambuf_len - index;
384 384
 
385
-        if (CL_SUCCESS != cli_strntoul_wrap(index, bytes_remaining, 0, 10, &next_objid)) {
385
+        if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) {
386 386
             /* Failed to find objid for next obj */
387 387
             cli_dbgmsg("pdf_findobj_in_objstm: Failed to find next objid for obj in object stream though there should be {%u} more.\n", objstm->n - objstm->nobjs_found);
388 388
             status = CL_EPARSE;
389 389
             goto done;
390
+        } else if (temp_long < 0) {
391
+            cli_dbgmsg("pdf_findobj_in_objstm: Encountered invalid negative objid (%ld).\n", temp_long);
392
+            status = CL_EPARSE;
393
+            goto done;
390 394
         }
395
+        next_objid = (unsigned long)temp_long;
391 396
 
392 397
         /* Find the obj offset that appears just after the obj id*/
393 398
         while ((index < objstm->streambuf + objstm->streambuf_len) && isdigit(*index)) {
... ...
@@ -397,13 +413,19 @@ int pdf_findobj_in_objstm(struct pdf_struct *pdf, struct objstm_struct *objstm,
397 397
         index = findNextNonWS(index, objstm->streambuf + objstm->first);
398 398
         bytes_remaining = objstm->streambuf + objstm->streambuf_len - index;
399 399
 
400
-        if (CL_SUCCESS != cli_strntoul_wrap(index, bytes_remaining, 0, 10, &next_objoff)) {
400
+        if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) {
401 401
             /* Failed to find obj offset for next obj */
402 402
             cli_dbgmsg("pdf_findobj_in_objstm: Failed to find next obj offset for obj in object stream though there should be {%u} more.\n", objstm->n - objstm->nobjs_found);
403 403
             status = CL_EPARSE;
404 404
             goto done;
405
+        } else if (temp_long < 0) {
406
+            cli_dbgmsg("pdf_findobj_in_objstm: Encountered invalid negative obj offset (%ld).\n", temp_long);
407
+            status = CL_EPARSE;
408
+            goto done;
405 409
         }
406
-        else if (next_objoff <= objoff) {
410
+        next_objoff = (unsigned long)temp_long;
411
+
412
+        if (next_objoff <= objoff) {
407 413
             /* Failed to find obj offset for next obj */
408 414
             cli_dbgmsg("pdf_findobj_in_objstm: Found next obj offset for obj in object stream but it's less than or equal to the current one!\n");
409 415
             status = CL_EPARSE;
... ...
@@ -481,6 +503,7 @@ cl_error_t pdf_findobj(struct pdf_struct *pdf)
481 481
     struct pdf_obj *obj = NULL;
482 482
     off_t bytesleft;
483 483
     unsigned long genid, objid;
484
+    long temp_long;
484 485
 
485 486
     pdf->nobjs++;
486 487
     pdf->objs = cli_realloc2(pdf->objs, sizeof(struct pdf_obj*) * pdf->nobjs);
... ...
@@ -539,20 +562,26 @@ cl_error_t pdf_findobj(struct pdf_struct *pdf)
539 539
     while (q > start && isdigit(*q))
540 540
         q--;
541 541
 
542
-    if (CL_SUCCESS != cli_strntoul_wrap(q, (size_t)(bytesleft + (q2-q)), 0, 10, &genid)) {
542
+    if (CL_SUCCESS != cli_strntol_wrap(q, (size_t)(bytesleft + (q2 - q)), 0, 10, &temp_long)) {
543 543
         cli_dbgmsg("pdf_findobj: Failed to parse object genid (# objects found: %u)\n", pdf->nobjs);
544 544
         /* Failed to parse, probably not a real object.  Skip past the "obj" thing, and continue. */
545 545
         pdf->offset = q2 + 4 - pdf->map;
546 546
         status = CL_EPARSE;
547 547
         goto done;
548
+    } else if (temp_long < 0) {
549
+        cli_dbgmsg("pdf_findobj: Encountered invalid negative obj genid (%ld).\n", temp_long);
550
+        pdf->offset = q2 + 4 - pdf->map;
551
+        status      = CL_EPARSE;
552
+        goto done;
548 553
     }
554
+    genid = (unsigned long)temp_long;
549 555
 
550 556
     /* Find the object id (objid) that appers before the genid */
551 557
     q = findNextNonWSBack(q-1,start);
552 558
     while (q > start && isdigit(*q))
553 559
         q--;
554 560
 
555
-    if (CL_SUCCESS != cli_strntoul_wrap(q, (size_t)(bytesleft + (q2-q)), 0, 10, &objid)) {
561
+    if (CL_SUCCESS != cli_strntol_wrap(q, (size_t)(bytesleft + (q2 - q)), 0, 10, &temp_long)) {
556 562
         /*
557 563
          * PDFs with multiple revisions will have %%EOF before the end of the file, 
558 564
          * followed by the next revision of the PDF.  If this is the case, we can 
... ...
@@ -581,15 +610,27 @@ cl_error_t pdf_findobj(struct pdf_struct *pdf)
581 581
             goto done;
582 582
         }
583 583
         /* Try again, with offset slightly adjusted */
584
-        if (CL_SUCCESS != cli_strntoul_wrap(q, (size_t)(bytesleft + (q2-q)), 0, 10, &objid)) {
584
+        if (CL_SUCCESS != cli_strntol_wrap(q, (size_t)(bytesleft + (q2 - q)), 0, 10, &temp_long)) {
585 585
             cli_dbgmsg("pdf_findobj: Failed to parse object objid (# objects found: %u)\n", pdf->nobjs);
586 586
             /* Still failed... Probably not a real object.  Skip past the "obj" thing, and continue. */
587 587
             pdf->offset = q2 + 4 - pdf->map;
588 588
             status = CL_EPARSE;
589 589
             goto done;
590
+        } else if (temp_long < 0) {
591
+            cli_dbgmsg("pdf_findobj: Encountered invalid negative objid (%ld).\n", temp_long);
592
+            pdf->offset = q2 + 4 - pdf->map;
593
+            status      = CL_EPARSE;
594
+            goto done;
590 595
         }
596
+
591 597
         cli_dbgmsg("pdf_findobj: There appears to be an additional revision. Continuing to parse...\n");
598
+    } else if (temp_long < 0) {
599
+        cli_dbgmsg("pdf_findobj: Encountered invalid negative objid (%ld).\n", temp_long);
600
+        pdf->offset = q2 + 4 - pdf->map;
601
+        status      = CL_EPARSE;
602
+        goto done;
592 603
     }
604
+    objid = (unsigned long)temp_long;
593 605
 
594 606
     /*
595 607
      * Ok so we have the objid, genid, and "obj" string.
... ...
@@ -845,7 +886,7 @@ static size_t find_length(struct pdf_struct *pdf, struct pdf_obj *obj, const cha
845 845
     size_t length = 0;
846 846
     const char *obj_start = dict_start;
847 847
     size_t bytes_remaining = dict_len;
848
-    unsigned long length_ul = 0;
848
+    long temp_long         = 0;
849 849
     const char *index;
850 850
 
851 851
     if (bytes_remaining < 8) {
... ...
@@ -881,11 +922,14 @@ static size_t find_length(struct pdf_struct *pdf, struct pdf_obj *obj, const cha
881 881
     
882 882
     /* Read the value.  This could either be the direct length value,
883 883
        or the object id of the indirect object that has the length */
884
-    if (CL_SUCCESS != cli_strntoul_wrap(index, bytes_remaining, 0, 10, &length_ul)) {
885
-        cli_dbgmsg("find_length: failed to parse object length\n");
884
+    if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) {
885
+        cli_dbgmsg("find_length: failed to parse object length or objid\n");
886
+        return 0;
887
+    } else if (temp_long < 0) {
888
+        cli_dbgmsg("find_length: Encountered invalid negative object length or objid (%ld).\n", temp_long);
886 889
         return 0;
887 890
     }
888
-    length = length_ul; /* length or maybe object id */
891
+    length = (size_t)temp_long; /* length or maybe object id */
889 892
 
890 893
     /* 
891 894
      * Keep parsing, skipping past the first integer that might have been what we wanted. 
... ...
@@ -903,10 +947,14 @@ static size_t find_length(struct pdf_struct *pdf, struct pdf_obj *obj, const cha
903 903
         index++;
904 904
         bytes_remaining--;
905 905
 
906
-        if (CL_SUCCESS != cli_strntoul_wrap(index, bytes_remaining, 0, 10, &genid)) {
906
+        if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) {
907 907
             cli_dbgmsg("find_length: failed to parse object genid\n");
908 908
             return 0;
909
+        } else if (temp_long < 0) {
910
+            cli_dbgmsg("find_length: Encountered invalid negative object genid (%ld).\n", temp_long);
911
+            return 0;
909 912
         }
913
+        genid = (unsigned long)temp_long;
910 914
 
911 915
         while((bytes_remaining > 0) && isdigit(*index)) {
912 916
             index++;
... ...
@@ -949,11 +997,15 @@ static size_t find_length(struct pdf_struct *pdf, struct pdf_obj *obj, const cha
949 949
             }
950 950
             bytes_remaining -= index - indirect_obj_start;
951 951
 
952
-            /* Found the value, so lets parse it as an unsigned long */
953
-            if (CL_SUCCESS != cli_strntoul_wrap(index, bytes_remaining, 0, 10, &length)) {
952
+            /* Found the value, so lets parse it as a long, but prohibit negative lengths. */
953
+            if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) {
954 954
                 cli_dbgmsg("find_length: failed to parse object length from indirect object\n");
955 955
                 return 0;
956
+            } else if (temp_long < 0) {
957
+                cli_dbgmsg("find_length: Encountered invalid negative obj length (%ld).\n", temp_long);
958
+                return 0;
956 959
             }
960
+            length = (size_t)temp_long;
957 961
         }
958 962
     }
959 963
 
... ...
@@ -1983,6 +2035,7 @@ static void pdf_parse_encrypt(struct pdf_struct *pdf, const char *enc, int len)
1983 1983
     const char *q, *q2;
1984 1984
     unsigned long objid;
1985 1985
     unsigned long genid;
1986
+    long temp_long;
1986 1987
 
1987 1988
     if (len >= 16 && !strncmp(enc, "/EncryptMetadata", 16)) {
1988 1989
         q = cli_memstr(enc+16, len-16, "/Encrypt", 8);
... ...
@@ -2001,10 +2054,15 @@ static void pdf_parse_encrypt(struct pdf_struct *pdf, const char *enc, int len)
2001 2001
     len -= q2 - q;
2002 2002
     q = q2;
2003 2003
 
2004
-    if (CL_SUCCESS != cli_strntoul_wrap(q2, (size_t)len, 0, 10, &objid)) {
2004
+    if (CL_SUCCESS != cli_strntol_wrap(q2, (size_t)len, 0, 10, &temp_long)) {
2005 2005
         cli_dbgmsg("pdf_parse_encrypt: Found Encrypt dictionary but failed to parse objid\n");
2006 2006
         return;
2007
+    } else if (temp_long < 0) {
2008
+        cli_dbgmsg("pdf_parse_encrypt: Encountered invalid negative objid (%ld).\n", temp_long);
2009
+        return;
2007 2010
     }
2011
+    objid = (unsigned long)temp_long;
2012
+
2008 2013
     objid = objid << 8;
2009 2014
     q2 = pdf_nextobject(q, len);
2010 2015
     if (!q2 || !isdigit(*q2))
... ...
@@ -2012,10 +2070,15 @@ static void pdf_parse_encrypt(struct pdf_struct *pdf, const char *enc, int len)
2012 2012
     len -= q2 - q;
2013 2013
     q = q2;
2014 2014
 
2015
-    if (CL_SUCCESS != cli_strntoul_wrap(q2, (size_t)len, 0, 10, &genid)) {
2015
+    if (CL_SUCCESS != cli_strntol_wrap(q2, (size_t)len, 0, 10, &temp_long)) {
2016 2016
         cli_dbgmsg("pdf_parse_encrypt: Found Encrypt dictionary but failed to parse genid\n");
2017 2017
         return;
2018
+    } else if (temp_long < 0) {
2019
+        cli_dbgmsg("pdf_parse_encrypt: Encountered invalid negative genid (%ld).\n", temp_long);
2020
+        return;
2018 2021
     }
2022
+    genid = (unsigned long)temp_long;
2023
+
2019 2024
     objid |= genid & 0xff; 
2020 2025
     q2 = pdf_nextobject(q, len);
2021 2026
     if (!q2 || *q2 != 'R')
... ...
@@ -2061,6 +2124,11 @@ void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
2061 2061
     json_object *pdfobj=NULL, *jsonobj=NULL;
2062 2062
 #endif
2063 2063
 
2064
+    if (NULL == pdf || NULL == obj) {
2065
+        cli_warnmsg("pdf_parseobj: invalid arguments\n");
2066
+        return;
2067
+    }
2068
+
2064 2069
     if (obj->objstm) {
2065 2070
         if ((size_t)obj->start > obj->objstm->streambuf_len) {
2066 2071
             cli_dbgmsg("pdf_parseobj: %u %u obj: obj start (%u) is greater than size of object stream (%zu).\n",
... ...
@@ -2112,7 +2180,23 @@ void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
2112 2112
             return;
2113 2113
         }
2114 2114
 
2115
+        /*
2116
+         * Opening `<` for object's dictionary may be back 1 character,
2117
+         * provided q is not at the start of the buffer (it shouldn't be).
2118
+         */
2119
+        if (obj->objstm) {
2120
+            if (obj->objstm->streambuf == q) {
2121
+                q3 = memchr(q, '<', nextobj - q);
2122
+            } else {
2115 2123
         q3 = memchr(q-1, '<', nextobj-q+1);
2124
+            }
2125
+        } else {
2126
+            if (pdf->map == q) {
2127
+                q3 = memchr(q, '<', nextobj - q);
2128
+            } else {
2129
+                q3 = memchr(q - 1, '<', nextobj - q + 1);
2130
+            }
2131
+        }
2116 2132
         nextobj++;
2117 2133
         bytesleft--;
2118 2134
         q = nextobj;
... ...
@@ -2297,13 +2381,19 @@ void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
2297 2297
                 const char * q2_old = NULL;
2298 2298
                 unsigned long objid;
2299 2299
                 unsigned long genid;
2300
+                long temp_long;
2300 2301
 
2301 2302
                 dict_remaining -= (off_t)(q2 - q);
2302 2303
 
2303
-                if (CL_SUCCESS != cli_strntoul_wrap(q2, (size_t)dict_remaining, 0, 10, &objid)) {
2304
+                if (CL_SUCCESS != cli_strntol_wrap(q2, (size_t)dict_remaining, 0, 10, &temp_long)) {
2304 2305
                     cli_dbgmsg("pdf_parseobj: failed to parse object objid\n");
2305 2306
                     return;
2307
+                } else if (temp_long < 0) {
2308
+                    cli_dbgmsg("pdf_parseobj: Encountered invalid negative genid (%ld).\n", temp_long);
2309
+                    return;
2306 2310
                 }
2311
+                objid = (unsigned long)temp_long;
2312
+
2307 2313
                 objid = objid << 8;
2308 2314
 
2309 2315
                 while (isdigit(*q2))
... ...
@@ -2313,10 +2403,15 @@ void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj)
2313 2313
                 q2 = pdf_nextobject(q2, dict_remaining);
2314 2314
                 if (q2 && isdigit(*q2)) {
2315 2315
                     dict_remaining -= (off_t)(q2 - q2_old);
2316
-                    if (CL_SUCCESS != cli_strntoul_wrap(q2, (size_t)dict_remaining, 0, 10, &genid)) {
2316
+                    if (CL_SUCCESS != cli_strntol_wrap(q2, (size_t)dict_remaining, 0, 10, &temp_long)) {
2317 2317
                         cli_dbgmsg("pdf_parseobj: failed to parse object genid\n");
2318 2318
                         return;
2319
+                    } else if (temp_long < 0) {
2320
+                        cli_dbgmsg("pdf_parseobj: Encountered invalid negative genid (%ld).\n", temp_long);
2321
+                        return;
2319 2322
                     }
2323
+                    genid = (unsigned long)temp_long;
2324
+
2320 2325
                     objid |= genid & 0xff;
2321 2326
 
2322 2327
                     q2 = pdf_nextobject(q2, dict_remaining);
... ...
@@ -3045,6 +3140,11 @@ cl_error_t pdf_find_and_parse_objs_in_objstm(struct pdf_struct *pdf, struct objs
3045 3045
 
3046 3046
     struct pdf_obj* obj = NULL;
3047 3047
 
3048
+    if ((NULL == objstm) || (NULL == objstm->streambuf)) {
3049
+        status = CL_EARG;
3050
+        goto done;
3051
+    }
3052
+
3048 3053
     char* current_pair = objstm->streambuf;
3049 3054
     char* current_obj = objstm->streambuf + objstm->first;
3050 3055
 
... ...
@@ -3242,6 +3342,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
3242 3242
     off_t versize = size > 1032 ? 1032 : size;
3243 3243
     off_t map_off, bytesleft;
3244 3244
     unsigned long xref;
3245
+    long temp_long;
3245 3246
     const char *pdfver, *tmp, *start, *eofmap, *q, *eof;
3246 3247
     unsigned i, alerts = 0;
3247 3248
     unsigned int objs_found = 0;
... ...
@@ -3383,11 +3484,14 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
3383 3383
 
3384 3384
             while (q < eof && (*q == ' ' || *q == '\n' || *q == '\r')) { q++; }
3385 3385
 
3386
-            if (CL_SUCCESS != cli_strntoul_wrap(q, q - eofmap + map_off, 0, 10, &xref)) {
3386
+            if (CL_SUCCESS != cli_strntol_wrap(q, q - eofmap + map_off, 0, 10, &temp_long)) {
3387 3387
                 cli_dbgmsg("cli_pdf: failed to parse PDF trailer xref\n");
3388 3388
                 pdf.flags |= 1 << BAD_PDF_TRAILER;
3389
-            }
3390
-            else {
3389
+            } else if (temp_long < 0) {
3390
+                cli_dbgmsg("cli_pdf: Encountered invalid negative PDF trailer xref (%ld).\n", temp_long);
3391
+                pdf.flags |= 1 << BAD_PDF_TRAILER;
3392
+            } else {
3393
+                xref      = (unsigned long)temp_long;
3391 3394
                 bytesleft = map->len - offset - xref;
3392 3395
                 if (bytesleft > 4096)
3393 3396
                     bytesleft = 4096;
... ...
@@ -4133,6 +4237,7 @@ static void Pages_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname
4133 4133
     const char *begin;
4134 4134
     unsigned int objsize;
4135 4135
     unsigned long npages=0, count;
4136
+    long temp_long;
4136 4137
     struct pdf_array_node *node;
4137 4138
     json_object *pdfobj;
4138 4139
     size_t countsize = 0;
... ...
@@ -4185,10 +4290,16 @@ static void Pages_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname
4185 4185
     countsize = (obj->objstm) ? (size_t)(obj->start + obj->objstm->streambuf + objsize - begin)
4186 4186
                               : (size_t)(obj->start + pdf->map + objsize - begin);
4187 4187
 
4188
-    if ((CL_SUCCESS != cli_strntoul_wrap(begin, countsize, 0, 10, &count)) ||
4189
-        (count != npages)) {
4188
+    if (CL_SUCCESS != cli_strntol_wrap(begin, countsize, 0, 10, &temp_long)) {
4189
+        cli_jsonbool(pdfobj, "IncorrectPagesCount", 1);
4190
+    } else if (temp_long < 0) {
4191
+        cli_jsonbool(pdfobj, "IncorrectPagesCount", 1);
4192
+    } else {
4193
+        count = (unsigned long)temp_long;
4194
+        if (count != npages) {
4190 4195
         cli_jsonbool(pdfobj, "IncorrectPagesCount", 1);
4191 4196
     }
4197
+    }
4192 4198
 
4193 4199
 cleanup:
4194 4200
     pdf_free_array(array);
... ...
@@ -4201,6 +4312,7 @@ static void Colors_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfnam
4201 4201
     cli_ctx *ctx = pdf->ctx;
4202 4202
     json_object *colorsobj, *pdfobj;
4203 4203
     unsigned long ncolors;
4204
+    long temp_long;
4204 4205
     char *p1;
4205 4206
     const char *objstart = (obj->objstm) ? (const char *)(obj->start + obj->objstm->streambuf)
4206 4207
                                          : (const char *)(obj->start + pdf->map);
... ...
@@ -4232,8 +4344,12 @@ static void Colors_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfnam
4232 4232
     if ((size_t)(p1 - objstart) == objsize)
4233 4233
         return;
4234 4234
 
4235
-    if (CL_SUCCESS != cli_strntoul_wrap(p1, (size_t)((p1 - objstart) - objsize), 0, 10, &ncolors))
4235
+    if (CL_SUCCESS != cli_strntol_wrap(p1, (size_t)((p1 - objstart) - objsize), 0, 10, &temp_long)) {
4236
+        return;
4237
+    } else if (temp_long < 0) {
4236 4238
         return;
4239
+    }
4240
+    ncolors = (unsigned long)temp_long;
4237 4241
 
4238 4242
     /* We only care if the number of colors > 2**24 */
4239 4243
     if (ncolors < 1<<24)