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;