Skip to content

Commit 66a0f06

Browse files
committed
Merge branch 'PHP-5.6' into PHP-7.0
* PHP-5.6: Fix bug #77143 - add more checks to buffer reads Fix #77020: null pointer dereference in imap_mail
2 parents 6e3f5d5 + 5421267 commit 66a0f06

File tree

6 files changed

+55
-11
lines changed

6 files changed

+55
-11
lines changed

ext/imap/php_imap.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4128,7 +4128,6 @@ PHP_FUNCTION(imap_mail)
41284128
if (!ZSTR_LEN(message)) {
41294129
/* this is not really an error, so it is allowed. */
41304130
php_error_docref(NULL, E_WARNING, "No message string in mail command");
4131-
message = NULL;
41324131
}
41334132

41344133
if (_php_imap_mail(ZSTR_VAL(to), ZSTR_VAL(subject), ZSTR_VAL(message), headers?ZSTR_VAL(headers):NULL, cc?ZSTR_VAL(cc):NULL,

ext/imap/tests/bug77020.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Bug #77020 (null pointer dereference in imap_mail)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('imap')) die('skip imap extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
imap_mail('1', 1, NULL);
10+
?>
11+
===DONE===
12+
--EXPECTF--
13+
Warning: imap_mail(): No message string in mail command in %s on line %d
14+
%s
15+
===DONE===

ext/phar/phar.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,18 @@ int phar_parse_metadata(char **buffer, zval *metadata, php_uint32 zip_metadata_l
642642
}
643643
/* }}}*/
644644

645+
/**
646+
* Size of fixed fields in the manifest.
647+
* See: http://php.net/manual/en/phar.fileformat.phar.php
648+
*/
649+
#define MANIFEST_FIXED_LEN 18
650+
651+
#define SAFE_PHAR_GET_32(buffer, endbuffer, var) \
652+
if (UNEXPECTED(buffer + 4 >= endbuffer)) { \
653+
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)"); \
654+
} \
655+
PHAR_GET_32(buffer, var);
656+
645657
/**
646658
* Does not check for a previously opened phar in the cache.
647659
*
@@ -725,12 +737,12 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
725737
savebuf = buffer;
726738
endbuffer = buffer + manifest_len;
727739

728-
if (manifest_len < 10 || manifest_len != php_stream_read(fp, buffer, manifest_len)) {
740+
if (manifest_len < MANIFEST_FIXED_LEN || manifest_len != php_stream_read(fp, buffer, manifest_len)) {
729741
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
730742
}
731743

732744
/* extract the number of entries */
733-
PHAR_GET_32(buffer, manifest_count);
745+
SAFE_PHAR_GET_32(buffer, endbuffer, manifest_count);
734746

735747
if (manifest_count == 0) {
736748
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
750762
return FAILURE;
751763
}
752764

753-
PHAR_GET_32(buffer, manifest_flags);
765+
SAFE_PHAR_GET_32(buffer, endbuffer, manifest_flags);
754766

755767
manifest_flags &= ~PHAR_HDR_COMPRESSION_MASK;
756768
manifest_flags &= ~PHAR_FILE_COMPRESSION_MASK;
@@ -970,13 +982,13 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
970982
}
971983

972984
/* extract alias */
973-
PHAR_GET_32(buffer, tmp_len);
985+
SAFE_PHAR_GET_32(buffer, endbuffer, tmp_len);
974986

975987
if (buffer + tmp_len > endbuffer) {
976988
MAPPHAR_FAIL("internal corruption of phar \"%s\" (buffer overrun)");
977989
}
978990

979-
if (manifest_len < 10 + tmp_len) {
991+
if (manifest_len < MANIFEST_FIXED_LEN + tmp_len) {
980992
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)")
981993
}
982994

@@ -1014,7 +1026,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
10141026
}
10151027

10161028
/* we have 5 32-bit items plus 1 byte at least */
1017-
if (manifest_count > ((manifest_len - 10 - tmp_len) / (5 * 4 + 1))) {
1029+
if (manifest_count > ((manifest_len - MANIFEST_FIXED_LEN - tmp_len) / (5 * 4 + 1))) {
10181030
/* prevent serious memory issues */
10191031
MAPPHAR_FAIL("internal corruption of phar \"%s\" (too many manifest entries for size of manifest)")
10201032
}
@@ -1023,12 +1035,12 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char
10231035
mydata->is_persistent = PHAR_G(persist);
10241036

10251037
/* check whether we have meta data, zero check works regardless of byte order */
1026-
PHAR_GET_32(buffer, len);
1038+
SAFE_PHAR_GET_32(buffer, endbuffer, len);
10271039
if (mydata->is_persistent) {
10281040
mydata->metadata_len = len;
1029-
if(!len) {
1041+
if (!len) {
10301042
/* FIXME: not sure why this is needed but removing it breaks tests */
1031-
PHAR_GET_32(buffer, len);
1043+
SAFE_PHAR_GET_32(buffer, endbuffer, len);
10321044
}
10331045
}
10341046
if(len > endbuffer - buffer) {

ext/phar/tests/bug73768.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ echo "OK\n";
1313
}
1414
?>
1515
--EXPECTF--
16-
cannot load phar "%sbug73768.phar" with implicit alias "" under different alias "alias.phar"
16+
internal corruption of phar "%sbug73768.phar" (truncated manifest header)

ext/phar/tests/bug77143.phar

50 Bytes
Binary file not shown.

ext/phar/tests/bug77143.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
PHP bug #77143: Heap Buffer Overflow (READ: 4) in phar_parse_pharfile
3+
--INI--
4+
phar.readonly=0
5+
--SKIPIF--
6+
<?php if (!extension_loaded("phar")) die("skip"); ?>
7+
--FILE--
8+
<?php
9+
chdir(__DIR__);
10+
try {
11+
var_dump(new Phar('bug77143.phar',0,'project.phar'));
12+
echo "OK\n";
13+
} catch(UnexpectedValueException $e) {
14+
echo $e->getMessage();
15+
}
16+
?>
17+
--EXPECTF--
18+
internal corruption of phar "%sbug77143.phar" (truncated manifest header)

0 commit comments

Comments
 (0)