You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

560 lines
13 KiB

Index: php5-5.4.45/ext/wddx/tests/bug70741.phpt
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ php5-5.4.45/ext/wddx/tests/bug70741.phpt 2016-06-19 11:51:56.000000000 +0200
@@ -0,0 +1,26 @@
+--TEST--
+Bug #70741 (Session WDDX Packet Deserialization Type Confusion Vulnerability)
+--SKIPIF--
+<?php
+if (!extension_loaded("wddx")) print "skip";
+?>
+--FILE--
+<?php
+ini_set('session.serialize_handler', 'wddx');
+session_start();
+
+$hashtable = str_repeat('A', 66);
+$wddx = "<?xml version='1.0'?>
+<wddxPacket version='1.0'>
+<header/>
+ <data>
+ <string>$hashtable</string>
+ </data>
+</wddxPacket>";
+session_decode($wddx);
+?>
+DONE
+--EXPECTF--
+
+Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s on line %d
+DONE
\ No newline at end of file
Index: php5-5.4.45/ext/wddx/wddx.c
===================================================================
--- php5-5.4.45.orig/ext/wddx/wddx.c 2016-06-19 11:51:56.000000000 +0200
+++ php5-5.4.45/ext/wddx/wddx.c 2016-06-19 11:51:56.000000000 +0200
@@ -72,7 +72,7 @@
stack->varname = NULL; \
} else \
ent.varname = NULL; \
-
+
static int le_wddx;
typedef struct {
@@ -171,7 +171,7 @@
/* }}} */
/* {{{ wddx_stack_init
- */
+ */
static int wddx_stack_init(wddx_stack *stack)
{
stack->top = 0;
@@ -239,7 +239,7 @@
efree(((st_entry *)stack->elements[i])->varname);
}
efree(stack->elements[i]);
- }
+ }
efree(stack->elements);
}
return SUCCESS;
@@ -270,16 +270,16 @@
php_wddx_packet_start(packet, NULL, 0);
php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
-
+
PS_ENCODE_LOOP(
php_wddx_serialize_var(packet, *struc, key, key_length TSRMLS_CC);
);
-
+
php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
php_wddx_packet_end(packet);
*newstr = php_wddx_gather(packet);
php_wddx_destructor(packet);
-
+
if (newlen) {
*newlen = strlen(*newstr);
}
@@ -304,11 +304,14 @@
if (vallen == 0) {
return SUCCESS;
}
-
+
MAKE_STD_ZVAL(retval);
if ((ret = php_wddx_deserialize_ex((char *)val, vallen, retval)) == SUCCESS) {
-
+ if (Z_TYPE_P(retval) != IS_ARRAY) {
+ zval_ptr_dtor(&retval);
+ return FAILURE;
+ }
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(retval));
zend_hash_get_current_data(Z_ARRVAL_P(retval), (void **) &ent) == SUCCESS;
zend_hash_move_forward(Z_ARRVAL_P(retval))) {
@@ -343,7 +346,7 @@
php_session_register_serializer("wddx",
PS_SERIALIZER_ENCODE_NAME(wddx),
PS_SERIALIZER_DECODE_NAME(wddx));
-#endif
+#endif
return SUCCESS;
}
@@ -387,7 +390,7 @@
void php_wddx_packet_end(wddx_packet *packet)
{
php_wddx_add_chunk_static(packet, WDDX_DATA_E);
- php_wddx_add_chunk_static(packet, WDDX_PACKET_E);
+ php_wddx_add_chunk_static(packet, WDDX_PACKET_E);
}
/* }}} */
@@ -423,14 +426,14 @@
{
char tmp_buf[WDDX_BUF_LEN];
zval tmp;
-
+
tmp = *var;
zval_copy_ctor(&tmp);
convert_to_string(&tmp);
snprintf(tmp_buf, sizeof(tmp_buf), WDDX_NUMBER, Z_STRVAL(tmp));
zval_dtor(&tmp);
- php_wddx_add_chunk(packet, tmp_buf);
+ php_wddx_add_chunk(packet, tmp_buf);
}
/* }}} */
@@ -473,7 +476,7 @@
if (call_user_function_ex(CG(function_table), &obj, fname, &retval, 0, 0, 1, NULL TSRMLS_CC) == SUCCESS) {
if (retval && (sleephash = HASH_OF(retval))) {
PHP_CLASS_ATTRIBUTES;
-
+
PHP_SET_CLASS_ATTRIBUTES(obj);
php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
@@ -487,7 +490,7 @@
PHP_CLEANUP_CLASS_ATTRIBUTES();
objhash = HASH_OF(obj);
-
+
for (zend_hash_internal_pointer_reset(sleephash);
zend_hash_get_current_data(sleephash, (void **)&varname) == SUCCESS;
zend_hash_move_forward(sleephash)) {
@@ -500,7 +503,7 @@
php_wddx_serialize_var(packet, *ent, Z_STRVAL_PP(varname), Z_STRLEN_PP(varname) TSRMLS_CC);
}
}
-
+
php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
}
} else {
@@ -519,7 +522,7 @@
php_wddx_add_chunk_static(packet, WDDX_VAR_E);
PHP_CLEANUP_CLASS_ATTRIBUTES();
-
+
objhash = HASH_OF(obj);
for (zend_hash_internal_pointer_reset(objhash);
zend_hash_get_current_data(objhash, (void**)&ent) == SUCCESS;
@@ -530,7 +533,7 @@
if (zend_hash_get_current_key_ex(objhash, &key, &key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) {
const char *class_name, *prop_name;
-
+
zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
php_wddx_serialize_var(packet, *ent, prop_name, strlen(prop_name)+1 TSRMLS_CC);
} else {
@@ -613,7 +616,7 @@
php_wddx_serialize_var(packet, *ent, NULL, 0 TSRMLS_CC);
}
}
-
+
if (is_struct) {
php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
} else {
@@ -639,12 +642,12 @@
efree(tmp_buf);
efree(name_esc);
}
-
+
switch(Z_TYPE_P(var)) {
case IS_STRING:
php_wddx_serialize_string(packet, var TSRMLS_CC);
break;
-
+
case IS_LONG:
case IS_DOUBLE:
php_wddx_serialize_number(packet, var);
@@ -657,14 +660,14 @@
case IS_NULL:
php_wddx_serialize_unset(packet);
break;
-
+
case IS_ARRAY:
ht = Z_ARRVAL_P(var);
if (ht->nApplyCount > 1) {
php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "WDDX doesn't support circular references");
return;
}
- ht->nApplyCount++;
+ ht->nApplyCount++;
php_wddx_serialize_array(packet, var);
ht->nApplyCount--;
break;
@@ -680,7 +683,7 @@
ht->nApplyCount--;
break;
}
-
+
if (name) {
php_wddx_add_chunk_static(packet, WDDX_VAR_E);
}
@@ -702,12 +705,12 @@
if (zend_hash_find(EG(active_symbol_table), Z_STRVAL_P(name_var),
Z_STRLEN_P(name_var)+1, (void**)&val) != FAILURE) {
php_wddx_serialize_var(packet, *val, Z_STRVAL_P(name_var), Z_STRLEN_P(name_var) TSRMLS_CC);
- }
+ }
} else if (Z_TYPE_P(name_var) == IS_ARRAY || Z_TYPE_P(name_var) == IS_OBJECT) {
int is_array = Z_TYPE_P(name_var) == IS_ARRAY;
-
+
target_hash = HASH_OF(name_var);
-
+
if (is_array && target_hash->nApplyCount > 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
return;
@@ -737,10 +740,10 @@
{
st_entry ent;
wddx_stack *stack = (wddx_stack *)user_data;
-
+
if (!strcmp(name, EL_PACKET)) {
int i;
-
+
if (atts) for (i=0; atts[i]; i++) {
if (!strcmp(atts[i], EL_VERSION)) {
/* nothing for now */
@@ -749,7 +752,7 @@
} else if (!strcmp(name, EL_STRING)) {
ent.type = ST_STRING;
SET_STACK_VARNAME;
-
+
ALLOC_ZVAL(ent.data);
INIT_PZVAL(ent.data);
Z_TYPE_P(ent.data) = IS_STRING;
@@ -759,7 +762,7 @@
} else if (!strcmp(name, EL_BINARY)) {
ent.type = ST_BINARY;
SET_STACK_VARNAME;
-
+
ALLOC_ZVAL(ent.data);
INIT_PZVAL(ent.data);
Z_TYPE_P(ent.data) = IS_STRING;
@@ -768,7 +771,7 @@
wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
} else if (!strcmp(name, EL_CHAR)) {
int i;
-
+
if (atts) for (i = 0; atts[i]; i++) {
if (!strcmp(atts[i], EL_CHAR_CODE) && atts[++i] && atts[i][0]) {
char tmp_buf[2];
@@ -781,7 +784,7 @@
} else if (!strcmp(name, EL_NUMBER)) {
ent.type = ST_NUMBER;
SET_STACK_VARNAME;
-
+
ALLOC_ZVAL(ent.data);
INIT_PZVAL(ent.data);
Z_TYPE_P(ent.data) = IS_LONG;
@@ -810,12 +813,12 @@
ALLOC_ZVAL(ent.data);
INIT_PZVAL(ent.data);
ZVAL_NULL(ent.data);
-
+
wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
} else if (!strcmp(name, EL_ARRAY)) {
ent.type = ST_ARRAY;
SET_STACK_VARNAME;
-
+
ALLOC_ZVAL(ent.data);
array_init(ent.data);
INIT_PZVAL(ent.data);
@@ -823,14 +826,14 @@
} else if (!strcmp(name, EL_STRUCT)) {
ent.type = ST_STRUCT;
SET_STACK_VARNAME;
-
+
ALLOC_ZVAL(ent.data);
array_init(ent.data);
INIT_PZVAL(ent.data);
wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
} else if (!strcmp(name, EL_VAR)) {
int i;
-
+
if (atts) for (i = 0; atts[i]; i++) {
if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
stack->varname = estrdup(atts[i]);
@@ -885,13 +888,13 @@
if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
st_entry *recordset;
zval **field;
-
+
if (wddx_stack_top(stack, (void**)&recordset) == SUCCESS &&
recordset->type == ST_RECORDSET &&
zend_hash_find(Z_ARRVAL_P(recordset->data), (char*)atts[i], strlen(atts[i])+1, (void**)&field) == SUCCESS) {
ent.data = *field;
}
-
+
break;
}
}
@@ -900,7 +903,7 @@
} else if (!strcmp(name, EL_DATETIME)) {
ent.type = ST_DATETIME;
SET_STACK_VARNAME;
-
+
ALLOC_ZVAL(ent.data);
INIT_PZVAL(ent.data);
Z_TYPE_P(ent.data) = IS_LONG;
@@ -962,14 +965,14 @@
if (stack->top > 1) {
stack->top--;
wddx_stack_top(stack, (void**)&ent2);
-
+
/* if non-existent field */
if (ent2->type == ST_FIELD && ent2->data == NULL) {
zval_ptr_dtor(&ent1->data);
efree(ent1);
return;
}
-
+
if (Z_TYPE_P(ent2->data) == IS_ARRAY || Z_TYPE_P(ent2->data) == IS_OBJECT) {
target_hash = HASH_OF(ent2->data);
@@ -988,7 +991,7 @@
/* Initialize target object */
MAKE_STD_ZVAL(obj);
object_init_ex(obj, *pce);
-
+
/* Merge current hashtable with object's default properties */
zend_hash_merge(Z_OBJPROP_P(obj),
Z_ARRVAL_P(ent2->data),
@@ -1001,15 +1004,15 @@
/* Clean up old array entry */
zval_ptr_dtor(&ent2->data);
-
+
/* Set stack entry to point to the newly created object */
ent2->data = obj;
-
+
/* Clean up class name var entry */
zval_ptr_dtor(&ent1->data);
} else if (Z_TYPE_P(ent2->data) == IS_OBJECT) {
zend_class_entry *old_scope = EG(scope);
-
+
EG(scope) = Z_OBJCE_P(ent2->data);
Z_DELREF_P(ent1->data);
add_property_zval(ent2->data, ent1->varname, ent1->data);
@@ -1048,7 +1051,7 @@
if (!wddx_stack_is_empty(stack) && !stack->done) {
wddx_stack_top(stack, (void**)&ent);
switch (Z_TYPE_P(ent)) {
- case ST_STRING:
+ case ST_STRING:
if (Z_STRLEN_P(ent->data) == 0) {
STR_FREE(Z_STRVAL_P(ent->data));
Z_STRVAL_P(ent->data) = estrndup(s, len);
@@ -1127,16 +1130,16 @@
XML_Parser parser;
st_entry *ent;
int retval;
-
+
wddx_stack_init(&stack);
parser = XML_ParserCreate("UTF-8");
XML_SetUserData(parser, &stack);
XML_SetElementHandler(parser, php_wddx_push_element, php_wddx_pop_element);
XML_SetCharacterDataHandler(parser, php_wddx_process_data);
-
+
XML_Parse(parser, value, vallen, 1);
-
+
XML_ParserFree(parser);
if (stack.top == 1) {
@@ -1147,7 +1150,7 @@
} else {
retval = FAILURE;
}
-
+
wddx_stack_destroy(&stack);
return retval;
@@ -1162,17 +1165,17 @@
char *comment = NULL;
int comment_len = 0;
wddx_packet *packet;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &var, &comment, &comment_len) == FAILURE) {
return;
}
-
+
packet = php_wddx_constructor();
php_wddx_packet_start(packet, comment, comment_len);
php_wddx_serialize_var(packet, var, NULL, 0 TSRMLS_CC);
php_wddx_packet_end(packet);
-
+
ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
smart_str_free(packet);
efree(packet);
@@ -1190,19 +1193,19 @@
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
return;
}
-
+
packet = php_wddx_constructor();
php_wddx_packet_start(packet, NULL, 0);
php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
-
+
for (i=0; i<num_args; i++) {
if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
convert_to_string_ex(args[i]);
}
php_wddx_add_var(packet, *args[i]);
- }
-
+ }
+
php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
php_wddx_packet_end(packet);
@@ -1251,7 +1254,7 @@
}
packet = php_wddx_constructor();
-
+
php_wddx_packet_start(packet, comment, comment_len);
php_wddx_add_chunk_static(packet, WDDX_STRUCT_S);
@@ -1265,15 +1268,15 @@
{
zval *packet_id;
wddx_packet *packet = NULL;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &packet_id) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(packet, wddx_packet *, &packet_id, -1, "WDDX packet ID", le_wddx);
-
- php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
-
+
+ php_wddx_add_chunk_static(packet, WDDX_STRUCT_E);
+
php_wddx_packet_end(packet);
ZVAL_STRINGL(return_value, packet->c, packet->len, 1);
@@ -1290,7 +1293,7 @@
zval ***args = NULL;
zval *packet_id;
wddx_packet *packet = NULL;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r+", &packet_id, &args, &num_args) == FAILURE) {
return;
}
@@ -1299,12 +1302,12 @@
efree(args);
RETURN_FALSE;
}
-
+
if (!packet) {
efree(args);
RETURN_FALSE;
}
-
+
for (i=0; i<num_args; i++) {
if (Z_TYPE_PP(args[i]) != IS_ARRAY && Z_TYPE_PP(args[i]) != IS_OBJECT) {
convert_to_string_ex(args[i]);
@@ -1317,7 +1320,7 @@
}
/* }}} */
-/* {{{ proto mixed wddx_deserialize(mixed packet)
+/* {{{ proto mixed wddx_deserialize(mixed packet)
Deserializes given packet and returns a PHP value */
PHP_FUNCTION(wddx_deserialize)
{
@@ -1325,7 +1328,7 @@
char *payload;
int payload_len;
php_stream *stream = NULL;
-
+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &packet) == FAILURE) {
return;
}
@@ -1348,7 +1351,7 @@
}
php_wddx_deserialize_ex(payload, payload_len, return_value);
-
+
if (stream) {
pefree(payload, 0);
}