]> granicus.if.org Git - php/commitdiff
Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
authorStanislav Malyshev <stas@php.net>
Mon, 5 Sep 2016 05:07:35 +0000 (22:07 -0700)
committerAnatol Belski <ab@php.net>
Mon, 12 Sep 2016 15:04:19 +0000 (17:04 +0200)
(cherry picked from commit 19484ab77466f99c78fc0e677f7e03da0584d6a2)

ext/phar/tests/bug72928.phpt [new file with mode: 0644]
ext/phar/tests/bug72928.zip [new file with mode: 0644]
ext/phar/util.c
ext/phar/zip.c

diff --git a/ext/phar/tests/bug72928.phpt b/ext/phar/tests/bug72928.phpt
new file mode 100644 (file)
index 0000000..8e6a954
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Phar: #72928 (Out of bound when verify signature of zip phar in phar_parse_zipfile)
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--FILE--
+<?php
+chdir(__DIR__);
+try {
+$phar = new PharData('bug72928.zip');
+var_dump($phar);
+} catch(UnexpectedValueException $e) {
+       print $e->getMessage()."\n";
+}
+?>
+DONE
+--EXPECTF--
+phar error: signature cannot be read in zip-based phar "%sbug72928.zip"
+DONE
\ No newline at end of file
diff --git a/ext/phar/tests/bug72928.zip b/ext/phar/tests/bug72928.zip
new file mode 100644 (file)
index 0000000..c480c5f
Binary files /dev/null and b/ext/phar/tests/bug72928.zip differ
index eca33efc385418f45218b34ddfc723777875d8e1..08d58b9301b0162955e39175adcdd7fa9e6aea43 100644 (file)
@@ -1609,6 +1609,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                        unsigned char digest[64];
                        PHP_SHA512_CTX context;
 
+                       if (sig_len < sizeof(digest)) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
                        PHP_SHA512Init(&context);
                        read_len = end_of_phar;
 
@@ -1642,6 +1649,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                        unsigned char digest[32];
                        PHP_SHA256_CTX context;
 
+                       if (sig_len < sizeof(digest)) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
                        PHP_SHA256Init(&context);
                        read_len = end_of_phar;
 
@@ -1683,6 +1697,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                        unsigned char digest[20];
                        PHP_SHA1_CTX  context;
 
+                       if (sig_len < sizeof(digest)) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
                        PHP_SHA1Init(&context);
                        read_len = end_of_phar;
 
@@ -1716,6 +1737,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ
                        unsigned char digest[16];
                        PHP_MD5_CTX   context;
 
+                       if (sig_len < sizeof(digest)) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
                        PHP_MD5Init(&context);
                        read_len = end_of_phar;
 
index 764f2b133d6c22b690c5daff0a00d5e0b502276c..8f695dd49eeffc14a3989c764cfe23f83403e0d4 100644 (file)
@@ -418,7 +418,7 @@ foundit:
                        php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
                        sig = (char *) emalloc(entry.uncompressed_filesize);
                        read = php_stream_read(fp, sig, entry.uncompressed_filesize);
-                       if (read != entry.uncompressed_filesize) {
+                       if (read != entry.uncompressed_filesize || read <= 8) {
                                php_stream_close(sigfile);
                                efree(sig);
                                PHAR_ZIP_FAIL("signature cannot be read");