From: Stanislav Malyshev Date: Mon, 5 Sep 2016 05:07:35 +0000 (-0700) Subject: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile X-Git-Tag: php-7.1.0RC2~18^2^2~13 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=223266e4e46b9188353db93771369078c2e94353;p=php Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile --- diff --git a/ext/phar/tests/bug72928.phpt b/ext/phar/tests/bug72928.phpt new file mode 100644 index 0000000000..8e6a95418c --- /dev/null +++ b/ext/phar/tests/bug72928.phpt @@ -0,0 +1,18 @@ +--TEST-- +Phar: #72928 (Out of bound when verify signature of zip phar in phar_parse_zipfile) +--SKIPIF-- + +--FILE-- +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 index 0000000000..c480c5f537 Binary files /dev/null and b/ext/phar/tests/bug72928.zip differ diff --git a/ext/phar/util.c b/ext/phar/util.c index 4bbd8676cb..828be8f9a2 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1650,6 +1650,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; @@ -1683,6 +1690,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; @@ -1724,6 +1738,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; @@ -1757,6 +1778,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; diff --git a/ext/phar/zip.c b/ext/phar/zip.c index bf895e7dfe..ed156a2d00 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -430,7 +430,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");