summaryrefslogtreecommitdiff
path: root/ext/phar
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2018-12-03 00:42:45 -0800
committerStanislav Malyshev <stas@php.net>2018-12-03 00:42:45 -0800
commit8ab5d22332b4fbb9b683bac36ce0b5ebc5501794 (patch)
treee3c4bd9828e3a325cd756882dd6a287f9b01e7e6 /ext/phar
parent61af343768edd7f72219f9d328cde44697ad5cf3 (diff)
parent5718d73dbbca4a1940fef48749ae8c43cc4157a0 (diff)
downloadphp-git-8ab5d22332b4fbb9b683bac36ce0b5ebc5501794.tar.gz
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0: Fix bug #77143 - add more checks to buffer reads Fix bug #77143 - add more checks to buffer reads Fix #77020: null pointer dereference in imap_mail
Diffstat (limited to 'ext/phar')
-rw-r--r--ext/phar/phar.c30
-rw-r--r--ext/phar/tests/bug73768.phpt2
-rw-r--r--ext/phar/tests/bug77143.pharbin0 -> 50 bytes
-rw-r--r--ext/phar/tests/bug77143.phpt18
4 files changed, 40 insertions, 10 deletions
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 414acc78f7..82a9ef3194 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -643,6 +643,18 @@ int phar_parse_metadata(char **buffer, zval *metadata, uint32_t zip_metadata_len
/* }}}*/
/**
+ * Size of fixed fields in the manifest.
+ * See: http://php.net/manual/en/phar.fileformat.phar.php
+ */
+#define MANIFEST_FIXED_LEN 18
+
+#define SAFE_PHAR_GET_32(buffer, endbuffer, var) \
+ if (UNEXPECTED(buffer + 4 > endbuffer)) { \
+ MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)"); \
+ } \
+ PHAR_GET_32(buffer, var);
+
+/**
* Does not check for a previously opened phar in the cache.
*
* Parse a new one and add it to the cache, returning either SUCCESS or
@@ -725,12 +737,12 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
savebuf = buffer;
endbuffer = buffer + manifest_len;
- if (manifest_len < 10 || manifest_len != php_stream_read(fp, buffer, manifest_len)) {
+ if (manifest_len < MANIFEST_FIXED_LEN || manifest_len != php_stream_read(fp, buffer, manifest_len)) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
}
/* extract the number of entries */
- PHAR_GET_32(buffer, manifest_count);
+ SAFE_PHAR_GET_32(buffer, endbuffer, manifest_count);
if (manifest_count == 0) {
MAPPHAR_FAIL("in phar \"%s\", manifest claims to have zero entries. Phars must have at least 1 entry");
@@ -750,7 +762,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
return FAILURE;
}
- PHAR_GET_32(buffer, manifest_flags);
+ SAFE_PHAR_GET_32(buffer, endbuffer, manifest_flags);
manifest_flags &= ~PHAR_HDR_COMPRESSION_MASK;
manifest_flags &= ~PHAR_FILE_COMPRESSION_MASK;
@@ -970,13 +982,13 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
}
/* extract alias */
- PHAR_GET_32(buffer, tmp_len);
+ SAFE_PHAR_GET_32(buffer, endbuffer, tmp_len);
if (buffer + tmp_len > endbuffer) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (buffer overrun)");
}
- if (manifest_len < 10 + tmp_len) {
+ if (manifest_len < MANIFEST_FIXED_LEN + tmp_len) {
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
}
@@ -1014,7 +1026,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
}
/* we have 5 32-bit items plus 1 byte at least */
- if (manifest_count > ((manifest_len - 10 - tmp_len) / (5 * 4 + 1))) {
+ if (manifest_count > ((manifest_len - MANIFEST_FIXED_LEN - tmp_len) / (5 * 4 + 1))) {
/* prevent serious memory issues */
MAPPHAR_FAIL("internal corruption of phar \"%s\" (too many manifest entries for size of manifest)")
}
@@ -1023,12 +1035,12 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
mydata->is_persistent = PHAR_G(persist);
/* check whether we have meta data, zero check works regardless of byte order */
- PHAR_GET_32(buffer, len);
+ SAFE_PHAR_GET_32(buffer, endbuffer, len);
if (mydata->is_persistent) {
mydata->metadata_len = len;
- if(!len) {
+ if (!len) {
/* FIXME: not sure why this is needed but removing it breaks tests */
- PHAR_GET_32(buffer, len);
+ SAFE_PHAR_GET_32(buffer, endbuffer, len);
}
}
if(len > (size_t)(endbuffer - buffer)) {
diff --git a/ext/phar/tests/bug73768.phpt b/ext/phar/tests/bug73768.phpt
index 37a4da0253..3062268b80 100644
--- a/ext/phar/tests/bug73768.phpt
+++ b/ext/phar/tests/bug73768.phpt
@@ -13,4 +13,4 @@ echo "OK\n";
}
?>
--EXPECTF--
-cannot load phar "%sbug73768.phar" with implicit alias "" under different alias "alias.phar"
+internal corruption of phar "%sbug73768.phar" (truncated manifest header)
diff --git a/ext/phar/tests/bug77143.phar b/ext/phar/tests/bug77143.phar
new file mode 100644
index 0000000000..eb797b5195
--- /dev/null
+++ b/ext/phar/tests/bug77143.phar
Binary files differ
diff --git a/ext/phar/tests/bug77143.phpt b/ext/phar/tests/bug77143.phpt
new file mode 100644
index 0000000000..f9f80fc4f4
--- /dev/null
+++ b/ext/phar/tests/bug77143.phpt
@@ -0,0 +1,18 @@
+--TEST--
+PHP bug #77143: Heap Buffer Overflow (READ: 4) in phar_parse_pharfile
+--INI--
+phar.readonly=0
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--FILE--
+<?php
+chdir(__DIR__);
+try {
+var_dump(new Phar('bug77143.phar',0,'project.phar'));
+echo "OK\n";
+} catch(UnexpectedValueException $e) {
+ echo $e->getMessage();
+}
+?>
+--EXPECTF--
+internal corruption of phar "%sbug77143.phar" (truncated manifest header)