Skip to content

Commit 3d8d13f

Browse files
committed
Merge branch 'PHP-7.2' into PHP-7.3
* PHP-7.2: 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 Don't need interactive progress on git clones in Travis Fix TSRM signature - php_stream_stat macro has it's own TSRM Regenerate certificates for openssl tests Improve test for bug77022
2 parents 1deee2b + 8fff902 commit 3d8d13f

File tree

8 files changed

+63
-12
lines changed

8 files changed

+63
-12
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
git:
2+
quiet: true
3+
14
dist: trusty
25
language: c
36
sudo: required

ext/imap/php_imap.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4116,7 +4116,6 @@ PHP_FUNCTION(imap_mail)
41164116
if (!ZSTR_LEN(message)) {
41174117
/* this is not really an error, so it is allowed. */
41184118
php_error_docref(NULL, E_WARNING, "No message string in mail command");
4119-
message = NULL;
41204119
}
41214120

41224121
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
@@ -640,6 +640,18 @@ int phar_parse_metadata(char **buffer, zval *metadata, uint32_t zip_metadata_len
640640
}
641641
/* }}}*/
642642

643+
/**
644+
* Size of fixed fields in the manifest.
645+
* See: http://php.net/manual/en/phar.fileformat.phar.php
646+
*/
647+
#define MANIFEST_FIXED_LEN 18
648+
649+
#define SAFE_PHAR_GET_32(buffer, endbuffer, var) \
650+
if (UNEXPECTED(buffer + 4 > endbuffer)) { \
651+
MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest header)"); \
652+
} \
653+
PHAR_GET_32(buffer, var);
654+
643655
/**
644656
* Does not check for a previously opened phar in the cache.
645657
*
@@ -725,12 +737,12 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, size_t fname_len, ch
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, size_t fname_len, ch
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, size_t fname_len, ch
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, size_t fname_len, ch
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, size_t fname_len, ch
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 > (size_t)(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/bug77022.phpt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
--TEST--
22
Phar: Bug #77022: PharData always creates new files with mode 0666
33
--SKIPIF--
4-
<?php if (!extension_loaded("phar")) die("skip"); ?>
4+
<?php
5+
if (!extension_loaded("phar")) die("skip");
6+
if (defined("PHP_WINDOWS_VERSION_MAJOR")) die("skip not for Windows")
7+
?>
58
--FILE--
69
<?php
710
umask(022);
@@ -11,6 +14,7 @@ $sFile = tempnam(__DIR__, 'test77022');
1114
var_dump(decoct(stat($sFile)['mode']));
1215

1316
foreach([Phar::TAR => 'tar', Phar::ZIP => 'zip'] as $mode => $ext) {
17+
clearstatcache();
1418
$phar = new PharData(__DIR__ . '/test77022.' . $ext, null, null, $mode);
1519
$phar->addFile($sFile, 'test-file-phar');
1620
$phar->addFromString("test-from-string", 'test-file-phar');

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)