Browse code

bb11588 - fix out of bounds read.

Steven Morgan authored on 2016/06/22 06:22:52
Showing 1 changed files
... ...
@@ -71,17 +71,20 @@ static int xar_cleanup_temp_file(cli_ctx *ctx, int fd, char * tmpname)
71 71
      value - pointer to long to contain the returned value
72 72
    returns - CL_SUCCESS or CL_EFORMAT
73 73
  */
74
-static int xar_get_numeric_from_xml_element(xmlTextReaderPtr reader, long * value)
74
+static int xar_get_numeric_from_xml_element(xmlTextReaderPtr reader, size_t * value)
75 75
 {
76 76
     const xmlChar * numstr;
77
+    ssize_t numval;
78
+
77 79
     if (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) {
78 80
         numstr = xmlTextReaderConstValue(reader);
79 81
         if (numstr) {
80
-            *value = atol((const char *)numstr);
81
-            if (*value < 0) {
82
+            numval = atol((const char *)numstr);
83
+            if (numval < 0) {
82 84
                 cli_dbgmsg("cli_scanxar: XML element value %li\n", *value);
83 85
                 return CL_EFORMAT;
84 86
             }
87
+            *value = numval;
85 88
             return CL_SUCCESS;
86 89
         }
87 90
     }
... ...
@@ -123,8 +126,18 @@ static void xar_get_checksum_values(xmlTextReaderPtr reader, unsigned char ** ck
123 123
     if (xmlTextReaderRead(reader) == 1 && xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) {
124 124
         xmlval = xmlTextReaderConstValue(reader);
125 125
         if (xmlval) {
126
-            *cksum = xmlStrdup(xmlval); 
127
-            cli_dbgmsg("cli_scanxar: checksum value is %s.\n", *cksum);
126
+            cli_dbgmsg("cli_scanxar: checksum value is %s.\n", xmlval);
127
+            if (*hash == XAR_CKSUM_SHA1 && xmlStrlen(xmlval) == 2 * CLI_HASHLEN_SHA1 ||
128
+                *hash == XAR_CKSUM_MD5 && xmlStrlen(xmlval) == 2 * CLI_HASHLEN_MD5)
129
+                {
130
+                    *cksum = xmlStrdup(xmlval); 
131
+                } 
132
+            else
133
+                {
134
+                    cli_dbgmsg("cli_scanxar: checksum type is unknown or length is invalid.\n");
135
+                    *hash = XAR_CKSUM_OTHER;
136
+                    *cksum = NULL;
137
+                }
128 138
         } else {
129 139
             *cksum = NULL;
130 140
             cli_dbgmsg("cli_scanxar: xmlTextReaderConstValue() returns NULL for checksum value.\n");           
... ...
@@ -149,7 +162,7 @@ static void xar_get_checksum_values(xmlTextReaderPtr reader, unsigned char ** ck
149 149
      e_hash - pointer to int for returning extracted checksum algorithm.
150 150
    returns - CL_FORMAT, CL_SUCCESS, CL_BREAK. CL_BREAK indicates no more <data>/<ea> element.
151 151
  */
152
-static int xar_get_toc_data_values(xmlTextReaderPtr reader, long *length, long *offset, long *size, int *encoding,
152
+static int xar_get_toc_data_values(xmlTextReaderPtr reader, size_t *length, size_t *offset, size_t *size, int *encoding,
153 153
                                    unsigned char ** a_cksum, int * a_hash, unsigned char ** e_cksum, int * e_hash)
154 154
 {
155 155
     const xmlChar *name;
... ...
@@ -386,10 +399,10 @@ static int xar_hash_check(int hash, const void * result, const void * expected)
386 386
         return 1;
387 387
     switch (hash) {
388 388
     case XAR_CKSUM_SHA1:
389
-        len = SHA1_HASH_SIZE;
389
+        len = CLI_HASHLEN_SHA1;
390 390
         break;
391 391
     case XAR_CKSUM_MD5:
392
-        len = CLI_HASH_MD5;
392
+        len = CLI_HASHLEN_MD5;
393 393
         break;
394 394
     case XAR_CKSUM_OTHER:
395 395
     case XAR_CKSUM_NONE:
... ...
@@ -417,7 +430,7 @@ int cli_scanxar(cli_ctx *ctx)
417 417
     int fd = -1;
418 418
     struct xar_header hdr;
419 419
     fmap_t *map = *ctx->fmap;
420
-    long length, offset, size, at;
420
+    size_t length, offset, size, at;
421 421
     int encoding;
422 422
     z_stream strm;
423 423
     char *toc, *tmpname;
... ...
@@ -490,6 +503,13 @@ int cli_scanxar(cli_ctx *ctx)
490 490
         goto exit_toc;
491 491
     }
492 492
 
493
+    if (hdr.toc_length_decompressed != strm.total_out) {
494
+        cli_dbgmsg("TOC decompress length %" PRIu64 " does not match amount decompressed %lu\n",
495
+                   hdr.toc_length_decompressed, strm.total_out);
496
+        toc[strm.total_out] = '\0';
497
+        hdr.toc_length_decompressed = strm.total_out;
498
+    }
499
+
493 500
     /* cli_dbgmsg("cli_scanxar: TOC xml:\n%s\n", toc); */
494 501
     /* printf("cli_scanxar: TOC xml:\n%s\n", toc); */
495 502
     /* cli_dbgmsg("cli_scanxar: TOC end:\n"); */
... ...
@@ -557,8 +577,8 @@ int cli_scanxar(cli_ctx *ctx)
557 557
             goto exit_reader;
558 558
         }
559 559
 
560
-        cli_dbgmsg("cli_scanxar: decompress into temp file:\n%s, size %li,\n"
561
-                   "from xar heap offset %li length %li\n",
560
+        cli_dbgmsg("cli_scanxar: decompress into temp file:\n%s, size %zu,\n"
561
+                   "from xar heap offset %zu length %zu\n",
562 562
                    tmpname, size, offset, length);
563 563
 
564 564
 
... ...
@@ -638,11 +658,14 @@ int cli_scanxar(cli_ctx *ctx)
638 638
 #define CLI_LZMA_IBUF_SIZE CLI_LZMA_OBUF_SIZE>>2 /* estimated compression ratio 25% */
639 639
             {
640 640
                 struct CLI_LZMA lz;
641
-                unsigned long in_remaining = length;
641
+                unsigned long in_remaining = MIN(length, map->len - at);
642 642
                 unsigned long out_size = 0;
643 643
                 unsigned char * buff = __lzma_wrap_alloc(NULL, CLI_LZMA_OBUF_SIZE);
644 644
                 int lret;
645
-                
645
+
646
+                if (length > in_remaining)
647
+                    length = in_remaining;
648
+
646 649
                 memset(&lz, 0, sizeof(lz));
647 650
                 if (buff == NULL) {
648 651
                     cli_dbgmsg("cli_scanxar: memory request for lzma decompression buffer fails.\n");
... ...
@@ -655,8 +678,8 @@ int cli_scanxar(cli_ctx *ctx)
655 655
                 if (blockp == NULL) {
656 656
                     char errbuff[128];
657 657
                     cli_strerror(errno, errbuff, sizeof(errbuff));
658
-                    cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
659
-                               length, at, errbuff);
658
+                    cli_dbgmsg("cli_scanxar: Can't read %i bytes @ %li, errno:%s.\n",
659
+                               CLI_LZMA_HDR_SIZE, at, errbuff);
660 660
                     rc = CL_EREAD;
661 661
                     __lzma_wrap_free(NULL, buff);
662 662
                     goto exit_tmpfile;
... ...
@@ -693,7 +716,7 @@ int cli_scanxar(cli_ctx *ctx)
693 693
                         char errbuff[128];
694 694
                         cli_strerror(errno, errbuff, sizeof(errbuff));
695 695
                         cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno: %s.\n",
696
-                                   length, at, errbuff);
696
+                                   lz.avail_in, at, errbuff);
697 697
                         rc = CL_EREAD;
698 698
                         __lzma_wrap_free(NULL, buff);
699 699
                         cli_LzmaShutdown(&lz);
... ...
@@ -758,33 +781,31 @@ int cli_scanxar(cli_ctx *ctx)
758 758
             /* for uncompressed, bzip2, xz, and unknown, just pull the file, cli_magic_scandesc does the rest */
759 759
             do_extract_cksum = 0;
760 760
             {
761
-                unsigned long write_len;
762
-                
761
+                size_t writelen = MIN(map->len - at, length);
762
+
763 763
                 if (ctx->engine->maxfilesize)
764
-                    write_len = MIN((size_t)(ctx->engine->maxfilesize), (size_t)length);
765
-                else
766
-                    write_len = length;
764
+                    writelen = MIN((size_t)(ctx->engine->maxfilesize), writelen);
767 765
                     
768
-                if (!(blockp = (void*)fmap_need_off_once(map, at, length))) {
766
+                if (!(blockp = (void*)fmap_need_off_once(map, at, writelen))) {
769 767
                     char errbuff[128];
770 768
                     cli_strerror(errno, errbuff, sizeof(errbuff));
771
-                    cli_dbgmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
772
-                               length, at, errbuff);
769
+                    cli_dbgmsg("cli_scanxar: Can't read %zu bytes @ %zu, errno:%s.\n",
770
+                               writelen, at, errbuff);
773 771
                     rc = CL_EREAD;
774 772
                     goto exit_tmpfile;
775 773
                 }
776 774
                 
777 775
                 if (a_hash_ctx != NULL)
778
-                    xar_hash_update(a_hash_ctx, blockp, length, a_hash);
776
+                    xar_hash_update(a_hash_ctx, blockp, writelen, a_hash);
779 777
                 
780
-                if (cli_writen(fd, blockp, write_len) < 0) {
781
-                    cli_dbgmsg("cli_scanxar: cli_writen error %li bytes @ %li.\n", length, at);
778
+                if (cli_writen(fd, blockp, writelen) < 0) {
779
+                    cli_dbgmsg("cli_scanxar: cli_writen error %zu bytes @ %li.\n", writelen, at);
782 780
                     rc = CL_EWRITE;
783 781
                     goto exit_tmpfile;
784 782
                 }
785 783
                 /*break;*/
786 784
             }          
787
-        }
785
+        } /* end of switch */
788 786
 
789 787
         if (rc == CL_SUCCESS) {
790 788
             if (a_hash_ctx != NULL) {
... ...
@@ -871,7 +892,7 @@ int cli_scanxar(cli_ctx *ctx)
871 871
     cli_dbgmsg("cli_scanxar: can't scan xar files, need libxml2.\n");
872 872
 #endif
873 873
     if (cksum_fails + extract_errors != 0) {
874
-        cli_warnmsg("cli_scanxar: %u checksum errors and %u extraction errors, use --debug for more info.\n",
874
+        cli_dbgmsg("cli_scanxar: %u checksum errors and %u extraction errors.\n",
875 875
                     cksum_fails, extract_errors);
876 876
     }
877 877