Skip to content

Commit b1bd411

Browse files
committed
Fixed bug #71587 - Use-After-Free / Double-Free in WDDX Deserialize
1 parent 377d353 commit b1bd411

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

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
@@ -936,6 +936,16 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
936936
!strcmp(name, EL_DATETIME)) {
937937
wddx_stack_top(stack, (void**)&ent1);
938938

939+
if (!ent1->data) {
940+
if (stack->top > 1) {
941+
stack->top--;
942+
} else {
943+
stack->done = 1;
944+
}
945+
efree(ent1);
946+
return;
947+
}
948+
939949
if (!strcmp(name, EL_BINARY)) {
940950
int new_len=0;
941951
unsigned char *new_str;
@@ -1032,6 +1042,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
10321042
}
10331043
} else if (!strcmp(name, EL_VAR) && stack->varname) {
10341044
efree(stack->varname);
1045+
stack->varname = NULL;
10351046
} else if (!strcmp(name, EL_FIELD)) {
10361047
st_entry *ent;
10371048
wddx_stack_top(stack, (void **)&ent);
@@ -1051,7 +1062,7 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
10511062

10521063
if (!wddx_stack_is_empty(stack) && !stack->done) {
10531064
wddx_stack_top(stack, (void**)&ent);
1054-
switch (Z_TYPE_P(ent)) {
1065+
switch (ent->type) {
10551066
case ST_STRING:
10561067
if (Z_STRLEN_P(ent->data) == 0) {
10571068
STR_FREE(Z_STRVAL_P(ent->data));
@@ -1090,11 +1101,11 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
10901101
} else if (!strcmp(s, "false")) {
10911102
Z_LVAL_P(ent->data) = 0;
10921103
} else {
1093-
stack->top--;
10941104
zval_ptr_dtor(&ent->data);
1095-
if (ent->varname)
1105+
if (ent->varname) {
10961106
efree(ent->varname);
1097-
efree(ent);
1107+
}
1108+
ent->data = NULL;
10981109
}
10991110
break;
11001111

0 commit comments

Comments
 (0)