]> granicus.if.org Git - php/commitdiff
Fixed bug #67329 fileinfo: NULL pointer deference flaw by processing certain CDF...
authorAnatol Belski <ab@php.net>
Tue, 3 Jun 2014 09:37:20 +0000 (11:37 +0200)
committerAnatol Belski <ab@php.net>
Tue, 3 Jun 2014 09:37:20 +0000 (11:37 +0200)
NEWS
ext/fileinfo/libmagic/cdf.c
ext/fileinfo/libmagic/cdf.h
ext/fileinfo/libmagic/readcdf.c

diff --git a/NEWS b/NEWS
index 081bf42b2c598fd844e798976e6adc9f7501f7c3..b5d8d2350120aead72a0e6e61f08412d6cd25c8e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,8 @@ PHP                                                                        NEWS
   . Fixed bug #67328 (fileinfo: fileinfo: numerous file_printf calls resulting in
     performance degradation).
   . Fixed bug #67326 (fileinfo: cdf_read_short_sector insufficient boundary check).
+  . Fixed bug #67329 (fileinfo: NULL pointer deference flaw by processing certain
+    CDF files).
 
 - SPL:
   . Fixed bug #67359 (Segfault in recursiveDirectoryIterator). (Laruence)
index 16649f193fbce5336369f30ce23cad3fd24f87aa..cbe3b0cf7727fbb93273d9ea0be9a0d4310ce52a 100644 (file)
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.53 2013/02/26 16:20:42 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.55 2014/02/27 23:26:17 christos Exp $")
 #endif
 
 #include <assert.h>
@@ -688,11 +688,13 @@ out:
 
 int
 cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h,
-    const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn)
+    const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn,
+    const cdf_directory_t **root)
 {
        size_t i;
        const cdf_directory_t *d;
 
+       *root = NULL;
        for (i = 0; i < dir->dir_len; i++)
                if (dir->dir_tab[i].d_type == CDF_DIR_TYPE_ROOT_STORAGE)
                        break;
@@ -701,6 +703,7 @@ cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h,
        if (i == dir->dir_len)
                goto out;
        d = &dir->dir_tab[i];
+       *root = d;
 
        /* If the it is not there, just fake it; some docs don't have it */
        if (d->d_stream_first_sector < 0)
index 70eb519465d54ed92f76e4b0e1fa637193ec6216..00131e02f4f2eecf35188c8a0e3566fe4ff5c65e 100644 (file)
@@ -300,7 +300,8 @@ int cdf_read_dir(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *,
 int cdf_read_ssat(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *,
     cdf_sat_t *);
 int cdf_read_short_stream(const cdf_info_t *, const cdf_header_t *,
-    const cdf_sat_t *, const cdf_dir_t *, cdf_stream_t *);
+    const cdf_sat_t *, const cdf_dir_t *, cdf_stream_t *,
+    const cdf_directory_t **);
 int cdf_read_property_info(const cdf_stream_t *, const cdf_header_t *, uint32_t,
     cdf_property_info_t **, size_t *, size_t *);
 int cdf_read_summary_info(const cdf_info_t *, const cdf_header_t *,
index 1600625eb88d7cb4411469134664afce29098efb..ec97ced44b292e4e796761ff99d32c7b31723dcd 100644 (file)
@@ -26,7 +26,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.37 2014/01/06 13:41:18 rrt Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.40 2014/03/06 15:23:33 christos Exp $")
 #endif
 
 #include <stdlib.h>
@@ -77,6 +77,40 @@ static const struct nv {
 # define strcasestr strstr
 #endif
 
+static const struct cv {
+       uint64_t clsid[2];
+       const char *mime;
+} clsid2mime[] = {
+       {
+#ifdef PHP_WIN32
+               { 0x00000000000c1084ui64, 0x46000000000000c0ui64 },
+#else
+               { 0x00000000000c1084LLU, 0x46000000000000c0LLU },
+#endif
+               "x-msi",
+       }
+}, clsid2desc[] = {
+       {
+#ifdef PHP_WIN32
+               { 0x00000000000c1084ui64, 0x46000000000000c0ui64 },
+#else
+               { 0x00000000000c1084LLU, 0x46000000000000c0LLU },
+#endif
+               "MSI Installer",
+       },
+};
+
+private const char *
+cdf_clsid_to_mime(const uint64_t clsid[2], const struct cv *cv)
+{
+       size_t i;
+       for (i = 0; cv[i].mime != NULL; i++) {
+               if (clsid[0] == cv[i].clsid[0] && clsid[1] == cv[i].clsid[1])
+                       return cv[i].mime;
+       }
+       return NULL;
+}
+
 private const char *
 cdf_app_to_mime(const char *vbuf, const struct nv *nv)
 {
@@ -95,7 +129,7 @@ cdf_app_to_mime(const char *vbuf, const struct nv *nv)
 
 private int
 cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
-    size_t count)
+    size_t count, const cdf_directory_t *root_storage)
 {
         size_t i;
         cdf_timestamp_t tp;
@@ -107,6 +141,9 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
 
        memset(&ts, 0, sizeof(ts));
 
+        if (!NOTMIME(ms) && root_storage)
+               str = cdf_clsid_to_mime(root_storage->d_storage_uuid, clsid2mime);
+
         for (i = 0; i < count; i++) {
                 cdf_print_property_name(buf, sizeof(buf), info[i].pi_id);
                 switch (info[i].pi_type) {
@@ -163,7 +200,7 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
                                                     buf, vbuf) == -1)
                                                         return -1;
                                         }
-                                } else if (info[i].pi_id ==
+                                } else if (str == NULL && info[i].pi_id ==
                                    CDF_PROPERTY_NAME_OF_APPLICATION) {
                                        str = cdf_app_to_mime(vbuf, app2mime);
                                }
@@ -217,7 +254,7 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info,
 
 private int
 cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h,
-    const cdf_stream_t *sst)
+    const cdf_stream_t *sst, const cdf_directory_t *root_storage)
 {
         cdf_summary_info_header_t si;
         cdf_property_info_t *info;
@@ -228,6 +265,8 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h,
                 return -1;
 
         if (NOTMIME(ms)) {
+               const char *str;
+
                 if (file_printf(ms, "Composite Document File V2 Document")
                    == -1)
                         return -1;
@@ -255,9 +294,15 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h,
                                 return -2;
                         break;
                 }
-        }
+               if (root_storage) {
+                       str = cdf_clsid_to_mime(root_storage->d_storage_uuid, clsid2desc);
+                       if (str)
+                               if (file_printf(ms, ", %s", str) == -1)
+                                       return -2;
+                       }
+               }
 
-        m = cdf_file_property_info(ms, info, count);
+        m = cdf_file_property_info(ms, info, count, root_storage);
         free(info);
 
         return m == -1 ? -2 : m;
@@ -275,6 +320,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
         int i;
         const char *expn = "";
         const char *corrupt = "corrupt: ";
+        const cdf_directory_t *root_storage;
 
         info.i_fd = fd;
         info.i_buf = buf;
@@ -308,7 +354,8 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
                 goto out2;
         }
 
-        if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst)) == -1) {
+        if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst,
+           &root_storage)) == -1) {
                 expn = "Cannot read short stream";
                 goto out3;
         }
@@ -329,23 +376,21 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
 #ifdef CDF_DEBUG
         cdf_dump_summary_info(&h, &scn);
 #endif
-        if ((i = cdf_file_summary_info(ms, &h, &scn)) < 0)
-                expn = "Can't expand summary_info";
+        if ((i = cdf_file_summary_info(ms, &h, &scn, root_storage)) < 0)
+            expn = "Can't expand summary_info";
+
        if (i == 0) {
                const char *str = NULL;
                cdf_directory_t *d;
                char name[__arraycount(d->d_name)];
                size_t j, k;
-               for (j = 0; j < dir.dir_len; j++) {
+
+               for (j = 0; str == NULL && j < dir.dir_len; j++) {
                        d = &dir.dir_tab[j];
                        for (k = 0; k < sizeof(name); k++)
                                name[k] = (char)cdf_tole2(d->d_name[k]);
-                       if (NOTMIME(ms))
-                               str = cdf_app_to_mime(name, name2desc);
-                       else
-                               str = cdf_app_to_mime(name, name2mime);
-                       if (str != NULL)
-                               break;
+                       str = cdf_app_to_mime(name,
+                           NOTMIME(ms) ? name2desc : name2mime);
                }
                if (NOTMIME(ms)) {
                        if (str != NULL) {