118 lines
3.0 KiB
Diff
118 lines
3.0 KiB
Diff
Backported from 5.5 for 5.4 by Remi Collet
|
|
Backported from 5.5 for 5.4 by Remi Collet
|
|
|
|
From b1bd4119bcafab6f9a8f84d92cd65eec3afeface Mon Sep 17 00:00:00 2001
|
|
From: Stanislav Malyshev <stas@php.net>
|
|
Date: Sun, 14 Feb 2016 22:34:39 -0800
|
|
Subject: [PATCH] Fixed bug #71587 - Use-After-Free / Double-Free in WDDX
|
|
Deserialize
|
|
|
|
---
|
|
ext/wddx/tests/bug71587.phpt | 43 +++++++++++++++++++++++++++++++++++++++++++
|
|
ext/wddx/wddx.c | 19 +++++++++++++++----
|
|
2 files changed, 58 insertions(+), 4 deletions(-)
|
|
create mode 100644 ext/wddx/tests/bug71587.phpt
|
|
|
|
diff --git a/ext/wddx/tests/bug71587.phpt b/ext/wddx/tests/bug71587.phpt
|
|
new file mode 100644
|
|
index 0000000..3fdfc35
|
|
--- /dev/null
|
|
+++ b/ext/wddx/tests/bug71587.phpt
|
|
@@ -0,0 +1,43 @@
|
|
+--TEST--
|
|
+Bug #71587 (Use-After-Free / Double-Free in WDDX Deserialize)
|
|
+--SKIPIF--
|
|
+<?php
|
|
+if (!extension_loaded("wddx")) print "skip";
|
|
+?>
|
|
+--FILE--
|
|
+<?php
|
|
+
|
|
+$xml = <<<EOF
|
|
+<?xml version='1.0' ?>
|
|
+<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
|
|
+<wddxPacket version='1.0'>
|
|
+ <array>
|
|
+ <var name='ML'></var>
|
|
+ <string>manhluat</string>
|
|
+ <var name='ML2'></var>
|
|
+ <boolean value='a'/>
|
|
+ <boolean value='true'/>
|
|
+ </array>
|
|
+</wddxPacket>
|
|
+EOF;
|
|
+
|
|
+$wddx = wddx_deserialize($xml);
|
|
+var_dump($wddx);
|
|
+// Print mem leak
|
|
+foreach($wddx as $k=>$v)
|
|
+ printf("Key: %s\nValue: %s\n",bin2hex($k),bin2hex($v));
|
|
+
|
|
+?>
|
|
+DONE
|
|
+--EXPECTF--
|
|
+array(2) {
|
|
+ [0]=>
|
|
+ string(8) "manhluat"
|
|
+ [1]=>
|
|
+ bool(true)
|
|
+}
|
|
+Key: 30
|
|
+Value: 6d616e686c756174
|
|
+Key: 31
|
|
+Value: 31
|
|
+DONE
|
|
diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c
|
|
index 7267ee1..da34246 100644
|
|
--- a/ext/wddx/wddx.c
|
|
+++ b/ext/wddx/wddx.c
|
|
@@ -936,6 +936,16 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
|
|
!strcmp(name, EL_DATETIME)) {
|
|
wddx_stack_top(stack, (void**)&ent1);
|
|
|
|
+ if (!ent1->data) {
|
|
+ if (stack->top > 1) {
|
|
+ stack->top--;
|
|
+ } else {
|
|
+ stack->done = 1;
|
|
+ }
|
|
+ efree(ent1);
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (!strcmp(name, EL_BINARY)) {
|
|
int new_len=0;
|
|
unsigned char *new_str;
|
|
@@ -1032,6 +1042,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
|
|
}
|
|
} else if (!strcmp(name, EL_VAR) && stack->varname) {
|
|
efree(stack->varname);
|
|
+ stack->varname = NULL;
|
|
} else if (!strcmp(name, EL_FIELD)) {
|
|
st_entry *ent;
|
|
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)
|
|
|
|
if (!wddx_stack_is_empty(stack) && !stack->done) {
|
|
wddx_stack_top(stack, (void**)&ent);
|
|
- switch (Z_TYPE_P(ent)) {
|
|
+ switch (ent->type) {
|
|
case ST_STRING:
|
|
if (Z_STRLEN_P(ent->data) == 0) {
|
|
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)
|
|
} else if (!strcmp(s, "false")) {
|
|
Z_LVAL_P(ent->data) = 0;
|
|
} else {
|
|
- stack->top--;
|
|
zval_ptr_dtor(&ent->data);
|
|
- if (ent->varname)
|
|
+ if (ent->varname) {
|
|
efree(ent->varname);
|
|
- efree(ent);
|
|
+ }
|
|
+ ent->data = NULL;
|
|
}
|
|
break;
|
|
|