Skip to content

Commit 91990bb

Browse files
committed
Merge branch 'PHP-5.5.33' into PHP-5.6.19
* PHP-5.5.33: Fix bug #71498: Out-of-Bound Read in phar_parse_zipfile() Fixed bug #71587 - Use-After-Free / Double-Free in WDDX Deserialize
2 parents 68a51ae + a6fdc5b commit 91990bb

File tree

6 files changed

+79
-7
lines changed

6 files changed

+79
-7
lines changed

ext/phar/tests/bug71488.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Phar: bug #71488: Stack overflow when decompressing tar archives
77
$p = new PharData(__DIR__."/bug71488.tar");
88
$newp = $p->decompress("test");
99
?>
10+
1011
DONE
1112
--CLEAN--
1213
<?php

ext/phar/tests/bug71498.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Phar: bug #71498: Out-of-Bound Read in phar_parse_zipfile()
3+
--SKIPIF--
4+
<?php if (!extension_loaded("phar")) die("skip"); ?>
5+
--FILE--
6+
<?php
7+
try {
8+
$p = new PharData(__DIR__."/bug71498.zip");
9+
} catch(UnexpectedValueException $e) {
10+
echo $e->getMessage();
11+
}
12+
?>
13+
14+
DONE
15+
--EXPECTF--
16+
phar error: end of central directory not found in zip-based phar "%s/bug71498.zip"
17+
DONE

ext/phar/tests/bug71498.zip

64.1 KB
Binary file not shown.

ext/phar/zip.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ static void phar_zip_u2d_time(time_t time, char *dtime, char *ddate) /* {{{ */
159159
*
160160
* Parse a new one and add it to the cache, returning either SUCCESS or
161161
* FAILURE, and setting pphar to the pointer to the manifest entry
162-
*
162+
*
163163
* This is used by phar_open_from_fp to process a zip-based phar, but can be called
164164
* directly.
165165
*/
@@ -199,7 +199,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
199199
}
200200

201201
while ((p=(char *) memchr(p + 1, 'P', (size_t) (size - (p + 1 - buf)))) != NULL) {
202-
if (!memcmp(p + 1, "K\5\6", 3)) {
202+
if ((p - buf) + sizeof(locator) <= size && !memcmp(p + 1, "K\5\6", 3)) {
203203
memcpy((void *)&locator, (void *) p, sizeof(locator));
204204
if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) {
205205
/* split archives not handled */
@@ -1161,7 +1161,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, long len, int defau
11611161
static const char newstub[] = "<?php // zip-based phar archive stub file\n__HALT_COMPILER();";
11621162
char halt_stub[] = "__HALT_COMPILER();";
11631163
char *tmp;
1164-
1164+
11651165
php_stream *stubfile, *oldfile;
11661166
php_serialize_data_t metadata_hash;
11671167
int free_user_stub, closeoldfile = 0;

ext/wddx/tests/bug71587.phpt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
Bug #71587 (Use-After-Free / Double-Free in WDDX Deserialize)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("wddx")) print "skip";
6+
?>
7+
--FILE--
8+
<?php
9+
10+
$xml = <<<EOF
11+
<?xml version='1.0' ?>
12+
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
13+
<wddxPacket version='1.0'>
14+
<array>
15+
<var name='ML'></var>
16+
<string>manhluat</string>
17+
<var name='ML2'></var>
18+
<boolean value='a'/>
19+
<boolean value='true'/>
20+
</array>
21+
</wddxPacket>
22+
EOF;
23+
24+
$wddx = wddx_deserialize($xml);
25+
var_dump($wddx);
26+
// Print mem leak
27+
foreach($wddx as $k=>$v)
28+
printf("Key: %s\nValue: %s\n",bin2hex($k),bin2hex($v));
29+
30+
?>
31+
DONE
32+
--EXPECTF--
33+
array(2) {
34+
[0]=>
35+
string(8) "manhluat"
36+
[1]=>
37+
bool(true)
38+
}
39+
Key: 30
40+
Value: 6d616e686c756174
41+
Key: 31
42+
Value: 31
43+
DONE

ext/wddx/wddx.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,16 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
934934
!strcmp(name, EL_DATETIME)) {
935935
wddx_stack_top(stack, (void**)&ent1);
936936

937+
if (!ent1->data) {
938+
if (stack->top > 1) {
939+
stack->top--;
940+
} else {
941+
stack->done = 1;
942+
}
943+
efree(ent1);
944+
return;
945+
}
946+
937947
if (!strcmp(name, EL_BINARY)) {
938948
int new_len=0;
939949
unsigned char *new_str;
@@ -1030,6 +1040,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
10301040
}
10311041
} else if (!strcmp(name, EL_VAR) && stack->varname) {
10321042
efree(stack->varname);
1043+
stack->varname = NULL;
10331044
} else if (!strcmp(name, EL_FIELD)) {
10341045
st_entry *ent;
10351046
wddx_stack_top(stack, (void **)&ent);
@@ -1049,7 +1060,7 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
10491060

10501061
if (!wddx_stack_is_empty(stack) && !stack->done) {
10511062
wddx_stack_top(stack, (void**)&ent);
1052-
switch (Z_TYPE_P(ent)) {
1063+
switch (ent->type) {
10531064
case ST_STRING:
10541065
if (Z_STRLEN_P(ent->data) == 0) {
10551066
STR_FREE(Z_STRVAL_P(ent->data));
@@ -1088,11 +1099,11 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
10881099
} else if (!strcmp(s, "false")) {
10891100
Z_LVAL_P(ent->data) = 0;
10901101
} else {
1091-
stack->top--;
10921102
zval_ptr_dtor(&ent->data);
1093-
if (ent->varname)
1103+
if (ent->varname) {
10941104
efree(ent->varname);
1095-
efree(ent);
1105+
}
1106+
ent->data = NULL;
10961107
}
10971108
break;
10981109

0 commit comments

Comments
 (0)