mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
Merge branch 'PHP-5.6'
* PHP-5.6: (21 commits) fix unit tests update NEWS add NEWS for fixes Improve fix for #70172 Fix bug #70312 - HAVAL gives wrong hashes in specific cases fix test add test Fix bug #70366 - use-after-free vulnerability in unserialize() with SplDoublyLinkedList Fix bug #70365 - use-after-free vulnerability in unserialize() with SplObjectStorage Fix bug #70172 - Use After Free Vulnerability in unserialize() Fix bug #70388 - SOAP serialize_function_call() type confusion Fixed bug #70350: ZipArchive::extractTo allows for directory traversal when creating directories Improve fix for #70385 Fix bug #70345 (Multiple vulnerabilities related to PCRE functions) Fix bug #70385 (Buffer over-read in exif_read_data with TIFF IFD tag byte value of 32 bytes) Fix bug #70219 (Use after free vulnerability in session deserializer) Fix bug ##70284 (Use after free vulnerability in unserialize() with GMP) Fix for bug #69782 Add CVE IDs asigned (post release) to PHP 5.4.43 Add CVE IDs asigned to #69085 (PHP 5.4.39) ... Conflicts: ext/exif/exif.c ext/gmp/gmp.c ext/pcre/php_pcre.c ext/session/session.c ext/session/tests/session_decode_variation3.phpt ext/soap/soap.c ext/spl/spl_observer.c ext/standard/var.c ext/standard/var_unserializer.c ext/standard/var_unserializer.re ext/xsl/xsltprocessor.c
This commit is contained in:
commit
9b1a224d4e
@ -1243,26 +1243,35 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
|
||||
{
|
||||
zval *prop, tmp;
|
||||
zend_string *key;
|
||||
zend_long h;
|
||||
zend_property_info *property_info;
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
|
||||
property_info = zend_get_property_info(object->ce, key, 1);
|
||||
if (property_info != ZEND_WRONG_PROPERTY_INFO &&
|
||||
property_info &&
|
||||
(property_info->flags & ZEND_ACC_STATIC) == 0) {
|
||||
zval *slot = OBJ_PROP(object, property_info->offset);
|
||||
zval_ptr_dtor(slot);
|
||||
ZVAL_COPY_VALUE(slot, prop);
|
||||
zval_add_ref(slot);
|
||||
if (object->properties) {
|
||||
ZVAL_INDIRECT(&tmp, slot);
|
||||
zend_hash_update(object->properties, key, &tmp);
|
||||
ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
|
||||
if(key) {
|
||||
property_info = zend_get_property_info(object->ce, key, 1);
|
||||
if (property_info != ZEND_WRONG_PROPERTY_INFO &&
|
||||
property_info &&
|
||||
(property_info->flags & ZEND_ACC_STATIC) == 0) {
|
||||
zval *slot = OBJ_PROP(object, property_info->offset);
|
||||
zval_ptr_dtor(slot);
|
||||
ZVAL_COPY_VALUE(slot, prop);
|
||||
zval_add_ref(slot);
|
||||
if (object->properties) {
|
||||
ZVAL_INDIRECT(&tmp, slot);
|
||||
zend_hash_update(object->properties, key, &tmp);
|
||||
}
|
||||
} else {
|
||||
if (!object->properties) {
|
||||
rebuild_object_properties(object);
|
||||
}
|
||||
prop = zend_hash_update(object->properties, key, prop);
|
||||
zval_add_ref(prop);
|
||||
}
|
||||
} else {
|
||||
if (!object->properties) {
|
||||
rebuild_object_properties(object);
|
||||
}
|
||||
prop = zend_hash_update(object->properties, key, prop);
|
||||
prop = zend_hash_index_update(object->properties, h, prop);
|
||||
zval_add_ref(prop);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
@ -2945,13 +2945,13 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||
if (length<byte_count-1) {
|
||||
/* When there are any characters after the first NUL */
|
||||
ImageInfo->CopyrightPhotographer = estrdup(value_ptr);
|
||||
ImageInfo->CopyrightEditor = estrdup(value_ptr+length+1);
|
||||
ImageInfo->CopyrightEditor = estrndup(value_ptr+length+1, byte_count-length-1);
|
||||
spprintf(&ImageInfo->Copyright, 0, "%s, %s", value_ptr, value_ptr+length+1);
|
||||
/* format = TAG_FMT_UNDEFINED; this musn't be ASCII */
|
||||
/* but we are not supposed to change this */
|
||||
/* keep in mind that image_info does not store editor value */
|
||||
} else {
|
||||
ImageInfo->Copyright = estrdup(value_ptr);
|
||||
ImageInfo->Copyright = estrndup(value_ptr, byte_count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -3042,10 +3042,10 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||
break;
|
||||
|
||||
case TAG_MAKE:
|
||||
ImageInfo->make = estrdup(value_ptr);
|
||||
ImageInfo->make = estrndup(value_ptr, byte_count);
|
||||
break;
|
||||
case TAG_MODEL:
|
||||
ImageInfo->model = estrdup(value_ptr);
|
||||
ImageInfo->model = estrndup(value_ptr, byte_count);
|
||||
break;
|
||||
|
||||
case TAG_MAKER_NOTE:
|
||||
|
@ -585,44 +585,42 @@ static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned ch
|
||||
{
|
||||
mpz_ptr gmpnum;
|
||||
const unsigned char *p, *max;
|
||||
zval zv;
|
||||
zval *zv;
|
||||
int retval = FAILURE;
|
||||
php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data;
|
||||
|
||||
ZVAL_UNDEF(&zv);
|
||||
PHP_VAR_UNSERIALIZE_INIT(unserialize_data);
|
||||
gmp_create(object, &gmpnum);
|
||||
|
||||
p = buf;
|
||||
max = buf + buf_len;
|
||||
|
||||
if (!php_var_unserialize(&zv, &p, max, &unserialize_data)
|
||||
|| Z_TYPE(zv) != IS_STRING
|
||||
|| convert_to_gmp(gmpnum, &zv, 10) == FAILURE
|
||||
zv = var_tmp_var(&unserialize_data);
|
||||
if (!php_var_unserialize(zv, &p, max, &unserialize_data)
|
||||
|| Z_TYPE_P(zv) != IS_STRING
|
||||
|| convert_to_gmp(gmpnum, zv, 10) == FAILURE
|
||||
) {
|
||||
zend_throw_exception(NULL, "Could not unserialize number", 0);
|
||||
goto exit;
|
||||
}
|
||||
zval_dtor(&zv);
|
||||
ZVAL_UNDEF(&zv);
|
||||
|
||||
if (!php_var_unserialize(&zv, &p, max, &unserialize_data)
|
||||
|| Z_TYPE(zv) != IS_ARRAY
|
||||
zv = var_tmp_var(&unserialize_data);
|
||||
if (!php_var_unserialize(zv, &p, max, &unserialize_data)
|
||||
|| Z_TYPE_P(zv) != IS_ARRAY
|
||||
) {
|
||||
zend_throw_exception(NULL, "Could not unserialize properties", 0);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (zend_hash_num_elements(Z_ARRVAL(zv)) != 0) {
|
||||
if (zend_hash_num_elements(Z_ARRVAL_P(zv)) != 0) {
|
||||
zend_hash_copy(
|
||||
zend_std_get_properties(object), Z_ARRVAL(zv),
|
||||
zend_std_get_properties(object), Z_ARRVAL_P(zv),
|
||||
(copy_ctor_func_t) zval_add_ref
|
||||
);
|
||||
}
|
||||
|
||||
retval = SUCCESS;
|
||||
exit:
|
||||
zval_dtor(&zv);
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data);
|
||||
return retval;
|
||||
}
|
||||
|
50
ext/gmp/tests/bug70284.phpt
Normal file
50
ext/gmp/tests/bug70284.phpt
Normal file
@ -0,0 +1,50 @@
|
||||
--TEST--
|
||||
Bug #70284 (Use after free vulnerability in unserialize() with GMP)
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("gmp")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$inner = 'r:2;a:1:{i:0;a:1:{i:0;r:4;}}';
|
||||
$exploit = 'a:2:{i:0;s:1:"1";i:1;C:3:"GMP":'.strlen($inner).':{'.$inner.'}}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
$fakezval = ptr2str(1122334455);
|
||||
$fakezval .= ptr2str(0);
|
||||
$fakezval .= "\x00\x00\x00\x00";
|
||||
$fakezval .= "\x01";
|
||||
$fakezval .= "\x00";
|
||||
$fakezval .= "\x00\x00";
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$v[$i] = $fakezval.$i;
|
||||
}
|
||||
|
||||
var_dump($data);
|
||||
|
||||
function ptr2str($ptr)
|
||||
{
|
||||
$out = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$out .= chr($ptr & 0xff);
|
||||
$ptr >>= 8;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(1) "1"
|
||||
[1]=>
|
||||
object(GMP)#%d (2) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(1) "1"
|
||||
}
|
||||
["num"]=>
|
||||
string(1) "1"
|
||||
}
|
||||
}
|
@ -336,7 +336,7 @@ PHP_HASH_API void PHP_HAVAL128Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@ -390,7 +390,7 @@ PHP_HASH_API void PHP_HAVAL160Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@ -444,7 +444,7 @@ PHP_HASH_API void PHP_HAVAL192Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@ -484,7 +484,7 @@ PHP_HASH_API void PHP_HAVAL224Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
@ -525,7 +525,7 @@ PHP_HASH_API void PHP_HAVAL256Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||
|
||||
/* Pad out to 118 mod 128.
|
||||
*/
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
|
||||
index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
|
||||
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
||||
|
||||
|
18
ext/hash/tests/bug70312.phpt
Normal file
18
ext/hash/tests/bug70312.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Bug #70312 HAVAL gives wrong hashes in specific cases
|
||||
--SKIPIF--
|
||||
<?php if(!extension_loaded("hash")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(hash('haval128,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval160,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval192,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval224,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
var_dump(hash('haval256,5', '1234567890123456789012345678901234567890123456789012345678901234'));
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(32) "f3f0d23819b87228b4b70ee350afaa9d"
|
||||
string(40) "aded6485e137f11d7292212ba3fa961714df0564"
|
||||
string(48) "e53da2b16269fe732e9a898a96707a9f28404d7333b02286"
|
||||
string(56) "c574fb307f0817b514b9bb2e7c4bfaffb7ad667aca3c8b523fefcf10"
|
||||
string(64) "fb73c19300b14d5cb393d929bf005e6c2d459a4c9c009e9813af1d2d3637ee8f"
|
@ -64,7 +64,7 @@ unlink($file);
|
||||
adler32: ff87222e
|
||||
crc32: 61664d33
|
||||
gost: d9e65f0c0c2ef944e4f8a01f4a46365c4f33a2853756878182a7f03e1490a4cd
|
||||
haval128,3: 8bb81269aca8b7f87829020d76a4e841
|
||||
haval128,3: c25962b13383c3ed9f13817c8f2ae7d6
|
||||
md2: 70f791c0d8fa9edd7d08e32fcba8c354
|
||||
md4: a9d034b16bb290c57a645afd6f14cd3b
|
||||
md5: 704bf818448f5bbb94061332d2c889aa
|
||||
|
@ -45,7 +45,7 @@ echo "sha256(raw): " . bin2hex(hash_hmac('sha256', $content, $key, TRUE)) . "\n"
|
||||
adler32: 12c803f7
|
||||
crc32: 96859101
|
||||
gost: a4a3c80bdf3f8665bf07376a34dc9c1b11af7c813f4928f62e39f0c0dc564dad
|
||||
haval128,3: 82cd0f4bd36729b5c80c33efa8c13ac5
|
||||
haval128,3: 4d1318607f0406bd1b7bd50907772672
|
||||
md2: 6d111dab563025e4cb5f4425c991fa12
|
||||
md4: 10cdbfe843000c623f8b8da0d5d20b0b
|
||||
md5: 2a632783e2812cf23de100d7d6a463ae
|
||||
|
@ -73,7 +73,7 @@ unlink($file);
|
||||
adler32: 0f8c02f9
|
||||
crc32: f2a60b9c
|
||||
gost: 94c39a40d5db852a8dc3d24e37eebf2d53e3d711457c59cd02b614f792a9d918
|
||||
haval128,3: e8fcff647f1a675acb429130fb94a17e
|
||||
haval128,3: f1cea637451097d790354a86de3f54a3
|
||||
md2: a685475e600314bb549ab4f33c3b27cb
|
||||
md4: cbc6bff781f48f57378d3effa27553e4
|
||||
md5: 8bddf39dd1c566c27acc7fa85ec36acf
|
||||
|
@ -758,7 +758,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
/* If subpatterns array has been passed, fill it in with values. */
|
||||
if (subpats != NULL) {
|
||||
/* Try to get the list of substrings and display a warning if failed. */
|
||||
if (pcre_get_substring_list(subject, offsets, count, &stringlist) < 0) {
|
||||
if ((offsets[1] - offsets[0] < 0) || pcre_get_substring_list(subject, offsets, count, &stringlist) < 0) {
|
||||
if (subpat_names) {
|
||||
efree(subpat_names);
|
||||
}
|
||||
@ -1177,7 +1177,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
|
||||
piece = subject + start_offset;
|
||||
|
||||
/* if (EXPECTED(count > 0 && (limit == -1 || limit > 0))) */
|
||||
if (EXPECTED(count > 0 && limit)) {
|
||||
if (EXPECTED(count > 0 && (offsets[1] - offsets[0] >= 0) && limit)) {
|
||||
if (UNEXPECTED(replace_count)) {
|
||||
++*replace_count;
|
||||
}
|
||||
@ -1799,7 +1799,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||
}
|
||||
|
||||
/* If something matched */
|
||||
if (count > 0) {
|
||||
if (count > 0 && (offsets[1] - offsets[0] >= 0)) {
|
||||
if (!no_empty || &subject[offsets[0]] != last_match) {
|
||||
|
||||
if (offset_capture) {
|
||||
|
24
ext/pcre/tests/bug70345.phpt
Normal file
24
ext/pcre/tests/bug70345.phpt
Normal file
@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Bug #70345 (Multiple vulnerabilities related to PCRE functions)
|
||||
--FILE--
|
||||
<?php
|
||||
$regex = '/(?=xyz\K)/';
|
||||
$subject = "aaaaxyzaaaa";
|
||||
|
||||
$v = preg_split($regex, $subject);
|
||||
print_r($v);
|
||||
|
||||
$regex = '/(a(?=xyz\K))/';
|
||||
$subject = "aaaaxyzaaaa";
|
||||
preg_match($regex, $subject, $matches);
|
||||
|
||||
var_dump($matches);
|
||||
--EXPECTF--
|
||||
Array
|
||||
(
|
||||
[0] => aaaaxyzaaaa
|
||||
)
|
||||
|
||||
Warning: preg_match(): Get subpatterns list failed in %s on line %d
|
||||
array(0) {
|
||||
}
|
@ -64,6 +64,7 @@ PHPAPI ZEND_DECLARE_MODULE_GLOBALS(ps)
|
||||
|
||||
static int php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra);
|
||||
static int (*php_session_rfc1867_orig_callback)(unsigned int event, void *event_data, void **extra);
|
||||
static void php_session_track_init(void);
|
||||
|
||||
/* SessionHandler class */
|
||||
zend_class_entry *php_session_class_entry;
|
||||
@ -138,6 +139,7 @@ static inline void php_rshutdown_session_globals(void) /* {{{ */
|
||||
static int php_session_destroy(void) /* {{{ */
|
||||
{
|
||||
int retval = SUCCESS;
|
||||
zend_string *var_name;
|
||||
|
||||
if (PS(session_status) != php_session_active) {
|
||||
php_error_docref(NULL, E_WARNING, "Trying to destroy uninitialized session");
|
||||
@ -235,6 +237,7 @@ static int php_session_decode(zend_string *data) /* {{{ */
|
||||
}
|
||||
if (PS(serializer)->decode(ZSTR_VAL(data), ZSTR_LEN(data)) == FAILURE) {
|
||||
php_session_destroy();
|
||||
php_session_track_init();
|
||||
php_error_docref(NULL, E_WARNING, "Failed to decode session object. Session has been destroyed");
|
||||
return FAILURE;
|
||||
}
|
||||
@ -952,6 +955,8 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
|
||||
var_replace(&var_hash, ¤t, zv);
|
||||
} else {
|
||||
zval_ptr_dtor(¤t);
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
PS_ADD_VARL(name);
|
||||
@ -1042,6 +1047,8 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
|
||||
var_replace(&var_hash, ¤t, zv);
|
||||
} else {
|
||||
zval_ptr_dtor(¤t);
|
||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
PS_ADD_VARL(name);
|
||||
@ -2169,8 +2176,7 @@ static PHP_FUNCTION(session_decode)
|
||||
}
|
||||
|
||||
if (php_session_decode(str) == FAILURE) {
|
||||
/* FIXME: session_decode() should return FALSE */
|
||||
/* RETURN_FALSE; */
|
||||
RETURN_FALSE;
|
||||
}
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ $data = "foo|a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}guff|R:1;blah|R:1;";
|
||||
|
||||
var_dump(session_start());
|
||||
for($index = 0; $index < strlen($data); $index++) {
|
||||
if(session_status() != PHP_SESSION_ACTIVE) { session_start(); }
|
||||
echo "\n-- Iteration $index --\n";
|
||||
$encoded = substr($data, 0, $index);
|
||||
var_dump(session_decode($encoded));
|
||||
@ -53,213 +54,213 @@ array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 4 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 5 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 6 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 7 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 8 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 9 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 10 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 11 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 12 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 13 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 14 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 15 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 16 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 17 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 18 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 19 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 20 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 21 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 22 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 23 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 24 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 25 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 26 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 27 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 28 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 29 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 30 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 31 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 32 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 33 --
|
||||
bool(true)
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 34 --
|
||||
@ -333,67 +334,31 @@ array(1) {
|
||||
}
|
||||
|
||||
-- Iteration 39 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 40 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 41 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 42 --
|
||||
bool(true)
|
||||
array(2) {
|
||||
["foo"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 43 --
|
||||
@ -512,104 +477,33 @@ array(2) {
|
||||
}
|
||||
|
||||
-- Iteration 48 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 49 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 50 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
-- Iteration 51 --
|
||||
bool(true)
|
||||
array(3) {
|
||||
["foo"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["guff"]=>
|
||||
&array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
int(2)
|
||||
[2]=>
|
||||
int(3)
|
||||
}
|
||||
["blah"]=>
|
||||
NULL
|
||||
}
|
||||
bool(true)
|
||||
Done
|
||||
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Warning: session_destroy(): Trying to destroy uninitialized session in %s/session_decode_error2.php on line %d
|
||||
bool(false)
|
||||
Done
|
||||
|
@ -1505,7 +1505,7 @@ static void _soap_server_exception(soapServicePtr service, sdlFunctionPtr functi
|
||||
add_soap_fault_ex(&exception_object, this_ptr, "Server", "Internal Error", NULL, NULL);
|
||||
}
|
||||
soap_server_fault_ex(function, &exception_object, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -2924,8 +2924,10 @@ PHP_METHOD(SoapClient, __call)
|
||||
free_soap_headers = 1;
|
||||
}
|
||||
ZEND_HASH_FOREACH_VAL(default_headers, tmp) {
|
||||
Z_ADDREF_P(tmp);
|
||||
zend_hash_next_index_insert(soap_headers, tmp);
|
||||
if(Z_TYPE_P(tmp) == IS_OBJECT) {
|
||||
Z_ADDREF_P(tmp);
|
||||
zend_hash_next_index_insert(soap_headers, tmp);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
soap_headers = Z_ARRVAL_P(tmp);
|
||||
@ -4332,9 +4334,14 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
|
||||
zval* header;
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(soap_headers, header) {
|
||||
HashTable *ht = Z_OBJPROP_P(header);
|
||||
HashTable *ht;
|
||||
zval *name, *ns, *tmp;
|
||||
|
||||
if (Z_TYPE_P(header) != IS_OBJECT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ht = Z_OBJPROP_P(header);
|
||||
if ((name = zend_hash_str_find(ht, "name", sizeof("name")-1)) != NULL &&
|
||||
Z_TYPE_P(name) == IS_STRING &&
|
||||
(ns = zend_hash_str_find(ht, "namespace", sizeof("namespace")-1)) != NULL &&
|
||||
|
17
ext/soap/tests/bug70388.phpt
Normal file
17
ext/soap/tests/bug70388.phpt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Bug #70388 (SOAP serialize_function_call() type confusion / RCE)
|
||||
--SKIPIF--
|
||||
<?php require_once('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$dummy = unserialize('O:10:"SoapClient":3:{s:3:"uri";s:1:"X";s:8:"location";s:22:"http://localhost/a.xml";s:17:"__default_headers";a:1:{i:1;s:1337:"'.str_repeat("X", 1337).'";}}');
|
||||
try {
|
||||
var_dump($dummy->notexisting());
|
||||
} catch(Exception $e) {
|
||||
var_dump($e->getMessage());
|
||||
var_dump(get_class($e));
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "%s"
|
||||
string(9) "SoapFault"
|
@ -1210,6 +1210,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
|
||||
if (!php_var_unserialize(elem, &p, s + buf_len, &var_hash)) {
|
||||
goto error;
|
||||
}
|
||||
var_push_dtor(&var_hash, elem);
|
||||
|
||||
spl_ptr_llist_push(intern->llist, elem);
|
||||
}
|
||||
|
50
ext/spl/tests/bug70155.phpt
Normal file
50
ext/spl/tests/bug70155.phpt
Normal file
@ -0,0 +1,50 @@
|
||||
--TEST--
|
||||
SPL: Bug #70155 Use After Free Vulnerability in unserialize() with SPLArrayObject
|
||||
--FILE--
|
||||
<?php
|
||||
$inner = 'x:i:0;O:12:"DateInterval":1:{s:1:"y";i:3;};m:a:1:{i:0;R:2;}';
|
||||
$exploit = 'C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}';
|
||||
$data = unserialize($exploit);
|
||||
|
||||
var_dump($data);
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
object(ArrayObject)#1 (2) {
|
||||
[0]=>
|
||||
int(0)
|
||||
["storage":"ArrayObject":private]=>
|
||||
object(DateInterval)#2 (15) {
|
||||
["y"]=>
|
||||
int(3)
|
||||
["m"]=>
|
||||
int(-1)
|
||||
["d"]=>
|
||||
int(-1)
|
||||
["h"]=>
|
||||
int(-1)
|
||||
["i"]=>
|
||||
int(-1)
|
||||
["s"]=>
|
||||
int(-1)
|
||||
["weekday"]=>
|
||||
int(-1)
|
||||
["weekday_behavior"]=>
|
||||
int(-1)
|
||||
["first_last_day_of"]=>
|
||||
int(-1)
|
||||
["invert"]=>
|
||||
int(0)
|
||||
["days"]=>
|
||||
int(-1)
|
||||
["special_type"]=>
|
||||
int(0)
|
||||
["special_amount"]=>
|
||||
int(-1)
|
||||
["have_weekday_relative"]=>
|
||||
int(0)
|
||||
["have_special_relative"]=>
|
||||
int(0)
|
||||
}
|
||||
}
|
||||
===DONE===
|
50
ext/spl/tests/bug70365.phpt
Normal file
50
ext/spl/tests/bug70365.phpt
Normal file
@ -0,0 +1,50 @@
|
||||
--TEST--
|
||||
SPL: Bug #70365 use-after-free vulnerability in unserialize() with SplObjectStorage
|
||||
--FILE--
|
||||
<?php
|
||||
class obj {
|
||||
var $ryat;
|
||||
function __wakeup() {
|
||||
$this->ryat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$fakezval = ptr2str(1122334455);
|
||||
$fakezval .= ptr2str(0);
|
||||
$fakezval .= "\x00\x00\x00\x00";
|
||||
$fakezval .= "\x01";
|
||||
$fakezval .= "\x00";
|
||||
$fakezval .= "\x00\x00";
|
||||
|
||||
$inner = 'x:i:1;O:8:"stdClass":0:{},i:1;;m:a:0:{}';
|
||||
$exploit = 'a:5:{i:0;i:1;i:1;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;R:6;i:4;s:'.strlen($fakezval).':"'.$fakezval.'";}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
var_dump($data);
|
||||
|
||||
function ptr2str($ptr)
|
||||
{
|
||||
$out = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$out .= chr($ptr & 0xff);
|
||||
$ptr >>= 8;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
--EXPECTF--
|
||||
array(5) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
&int(1)
|
||||
[2]=>
|
||||
object(obj)#%d (1) {
|
||||
["ryat"]=>
|
||||
&int(1)
|
||||
}
|
||||
[3]=>
|
||||
int(1)
|
||||
[4]=>
|
||||
string(24) "%s"
|
||||
}
|
54
ext/spl/tests/bug70366.phpt
Normal file
54
ext/spl/tests/bug70366.phpt
Normal file
@ -0,0 +1,54 @@
|
||||
--TEST--
|
||||
SPL: Bug #70366 use-after-free vulnerability in unserialize() with SplDoublyLinkedList
|
||||
--FILE--
|
||||
<?php
|
||||
class obj {
|
||||
var $ryat;
|
||||
function __wakeup() {
|
||||
$this->ryat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$fakezval = ptr2str(1122334455);
|
||||
$fakezval .= ptr2str(0);
|
||||
$fakezval .= "\x00\x00\x00\x00";
|
||||
$fakezval .= "\x01";
|
||||
$fakezval .= "\x00";
|
||||
$fakezval .= "\x00\x00";
|
||||
|
||||
$inner = 'i:1234;:i:1;';
|
||||
$exploit = 'a:5:{i:0;i:1;i:1;C:19:"SplDoublyLinkedList":'.strlen($inner).':{'.$inner.'}i:2;O:3:"obj":1:{s:4:"ryat";R:3;}i:3;a:1:{i:0;R:5;}i:4;s:'.strlen($fakezval).':"'.$fakezval.'";}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
var_dump($data);
|
||||
|
||||
function ptr2str($ptr)
|
||||
{
|
||||
$out = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$out .= chr($ptr & 0xff);
|
||||
$ptr >>= 8;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(5) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
&int(1)
|
||||
[2]=>
|
||||
object(obj)#%d (1) {
|
||||
["ryat"]=>
|
||||
&int(1)
|
||||
}
|
||||
[3]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
int(1)
|
||||
}
|
||||
[4]=>
|
||||
string(24) "%s"
|
||||
}
|
54
ext/standard/tests/serialize/bug70172.phpt
Normal file
54
ext/standard/tests/serialize/bug70172.phpt
Normal file
@ -0,0 +1,54 @@
|
||||
--TEST--
|
||||
Bug #70172 - Use After Free Vulnerability in unserialize()
|
||||
--XFAIL--
|
||||
Memory leak on debug build, needs fix.
|
||||
--FILE--
|
||||
<?php
|
||||
class obj implements Serializable {
|
||||
var $data;
|
||||
function serialize() {
|
||||
return serialize($this->data);
|
||||
}
|
||||
function unserialize($data) {
|
||||
$this->data = unserialize($data);
|
||||
}
|
||||
}
|
||||
|
||||
$fakezval = ptr2str(1122334455);
|
||||
$fakezval .= ptr2str(0);
|
||||
$fakezval .= "\x00\x00\x00\x00";
|
||||
$fakezval .= "\x01";
|
||||
$fakezval .= "\x00";
|
||||
$fakezval .= "\x00\x00";
|
||||
|
||||
$inner = 'r:2;';
|
||||
$exploit = 'a:2:{i:0;i:1;i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$v[$i] = $fakezval.$i;
|
||||
}
|
||||
|
||||
var_dump($data);
|
||||
|
||||
function ptr2str($ptr)
|
||||
{
|
||||
$out = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$out .= chr($ptr & 0xff);
|
||||
$ptr >>= 8;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
int(1)
|
||||
[1]=>
|
||||
object(obj)#%d (1) {
|
||||
["data"]=>
|
||||
int(1)
|
||||
}
|
||||
}
|
68
ext/standard/tests/serialize/bug70172_2.phpt
Normal file
68
ext/standard/tests/serialize/bug70172_2.phpt
Normal file
@ -0,0 +1,68 @@
|
||||
--TEST--
|
||||
Bug #70172 - Use After Free Vulnerability in unserialize()
|
||||
--FILE--
|
||||
<?php
|
||||
class obj implements Serializable {
|
||||
var $data;
|
||||
function serialize() {
|
||||
return serialize($this->data);
|
||||
}
|
||||
function unserialize($data) {
|
||||
$this->data = unserialize($data);
|
||||
}
|
||||
}
|
||||
|
||||
class obj2 {
|
||||
var $ryat;
|
||||
function __wakeup() {
|
||||
$this->ryat = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$fakezval = ptr2str(1122334455);
|
||||
$fakezval .= ptr2str(0);
|
||||
$fakezval .= "\x00\x00\x00\x00";
|
||||
$fakezval .= "\x01";
|
||||
$fakezval .= "\x00";
|
||||
$fakezval .= "\x00\x00";
|
||||
|
||||
$inner = 'r:2;';
|
||||
$exploit = 'a:2:{i:0;O:4:"obj2":1:{s:4:"ryat";C:3:"obj":'.strlen($inner).':{'.$inner.'}}i:1;a:1:{i:0;a:1:{i:0;R:4;}}}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$v[$i] = $fakezval.$i;
|
||||
}
|
||||
|
||||
var_dump($data);
|
||||
|
||||
function ptr2str($ptr)
|
||||
{
|
||||
$out = '';
|
||||
for ($i = 0; $i < 8; $i++) {
|
||||
$out .= chr($ptr & 0xff);
|
||||
$ptr >>= 8;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(obj2)#%d (1) {
|
||||
["ryat"]=>
|
||||
int(1)
|
||||
}
|
||||
[1]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
[0]=>
|
||||
&object(obj2)#%d (1) {
|
||||
["ryat"]=>
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
ext/standard/tests/serialize/bug70219.phpt
Normal file
40
ext/standard/tests/serialize/bug70219.phpt
Normal file
@ -0,0 +1,40 @@
|
||||
--TEST--
|
||||
Bug #70219 Use after free vulnerability in session deserializer
|
||||
--FILE--
|
||||
<?php
|
||||
class obj implements Serializable {
|
||||
var $data;
|
||||
function serialize() {
|
||||
return serialize($this->data);
|
||||
}
|
||||
function unserialize($data) {
|
||||
session_start();
|
||||
session_decode($data);
|
||||
}
|
||||
}
|
||||
|
||||
$inner = 'ryat|a:1:{i:0;a:1:{i:1;';
|
||||
$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}';
|
||||
|
||||
$data = unserialize($exploit);
|
||||
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$v[$i] = 'hi'.$i;
|
||||
}
|
||||
|
||||
var_dump($data);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s on line %d
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(obj)#%d (1) {
|
||||
["data"]=>
|
||||
NULL
|
||||
}
|
||||
[1]=>
|
||||
&array(1) {
|
||||
["data"]=>
|
||||
NULL
|
||||
}
|
||||
}
|
@ -1045,6 +1045,7 @@ PHP_FUNCTION(unserialize)
|
||||
php_unserialize_data_t var_hash;
|
||||
zval *options = NULL, *classes = NULL;
|
||||
HashTable *class_hash = NULL;
|
||||
zval *old_rval = return_value;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &options) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Generated by re2c 0.13.5 */
|
||||
/* Generated by re2c 0.13.7.5 */
|
||||
#line 1 "ext/standard/var_unserializer.re"
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
@ -103,9 +103,15 @@ PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
|
||||
#if 0
|
||||
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval *rval)
|
||||
{
|
||||
var_dtor_entries *var_hash = (*var_hashx)->last_dtor;
|
||||
var_entries *var_hash;
|
||||
|
||||
if (!var_hashx || !*var_hashx) {
|
||||
return;
|
||||
}
|
||||
|
||||
var_hash = (*var_hashx)->last_dtor;
|
||||
#if VAR_ENTRIES_DBG
|
||||
fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
|
||||
fprintf(stderr, "var_push_dtor_no_addref(%p, %ld): %d (%d)\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
|
||||
#endif
|
||||
|
||||
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
||||
@ -183,6 +189,9 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
|
||||
|
||||
while (var_dtor_hash) {
|
||||
for (i = 0; i < var_dtor_hash->used_slots; i++) {
|
||||
#if VAR_ENTRIES_DBG
|
||||
fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i]));
|
||||
#endif
|
||||
zval_ptr_dtor(&var_dtor_hash->data[i]);
|
||||
}
|
||||
next = var_dtor_hash->next;
|
||||
@ -263,7 +272,7 @@ static inline int unserialize_allowed_class(zend_string *class_name, HashTable *
|
||||
#define YYMARKER marker
|
||||
|
||||
|
||||
#line 271 "ext/standard/var_unserializer.re"
|
||||
#line 280 "ext/standard/var_unserializer.re"
|
||||
|
||||
|
||||
|
||||
@ -530,7 +539,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
|
||||
start = cursor;
|
||||
|
||||
|
||||
#line 534 "ext/standard/var_unserializer.c"
|
||||
#line 543 "ext/standard/var_unserializer.c"
|
||||
{
|
||||
YYCTYPE yych;
|
||||
static const unsigned char yybm[] = {
|
||||
@ -590,9 +599,9 @@ yy2:
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if (yych == ':') goto yy95;
|
||||
yy3:
|
||||
#line 881 "ext/standard/var_unserializer.re"
|
||||
#line 893 "ext/standard/var_unserializer.re"
|
||||
{ return 0; }
|
||||
#line 596 "ext/standard/var_unserializer.c"
|
||||
#line 605 "ext/standard/var_unserializer.c"
|
||||
yy4:
|
||||
yych = *(YYMARKER = ++YYCURSOR);
|
||||
if (yych == ':') goto yy89;
|
||||
@ -635,13 +644,13 @@ yy13:
|
||||
goto yy3;
|
||||
yy14:
|
||||
++YYCURSOR;
|
||||
#line 875 "ext/standard/var_unserializer.re"
|
||||
#line 887 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
/* this is the case where we have less data than planned */
|
||||
php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data");
|
||||
return 0; /* not sure if it should be 0 or 1 here? */
|
||||
}
|
||||
#line 645 "ext/standard/var_unserializer.c"
|
||||
#line 654 "ext/standard/var_unserializer.c"
|
||||
yy16:
|
||||
yych = *++YYCURSOR;
|
||||
goto yy3;
|
||||
@ -667,11 +676,12 @@ yy20:
|
||||
if (yybm[0+yych] & 128) {
|
||||
goto yy20;
|
||||
}
|
||||
if (yych != ':') goto yy18;
|
||||
if (yych <= '/') goto yy18;
|
||||
if (yych >= ';') goto yy18;
|
||||
yych = *++YYCURSOR;
|
||||
if (yych != '"') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 730 "ext/standard/var_unserializer.re"
|
||||
#line 741 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
size_t len, len2, len3, maxlen;
|
||||
zend_long elements;
|
||||
@ -686,6 +696,7 @@ yy20:
|
||||
zval retval;
|
||||
zval args[1];
|
||||
|
||||
if (!var_hash) return 0;
|
||||
if (*start == 'C') {
|
||||
custom_object = 1;
|
||||
}
|
||||
@ -816,7 +827,7 @@ yy20:
|
||||
|
||||
return object_common2(UNSERIALIZE_PASSTHRU, elements);
|
||||
}
|
||||
#line 820 "ext/standard/var_unserializer.c"
|
||||
#line 831 "ext/standard/var_unserializer.c"
|
||||
yy25:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= ',') {
|
||||
@ -841,15 +852,16 @@ yy27:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych != '"') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 722 "ext/standard/var_unserializer.re"
|
||||
#line 732 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
if (!var_hash) return 0;
|
||||
|
||||
//??? INIT_PZVAL(rval);
|
||||
|
||||
return object_common2(UNSERIALIZE_PASSTHRU,
|
||||
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
|
||||
}
|
||||
#line 853 "ext/standard/var_unserializer.c"
|
||||
#line 865 "ext/standard/var_unserializer.c"
|
||||
yy32:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == '+') goto yy33;
|
||||
@ -870,11 +882,12 @@ yy34:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych != '{') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 701 "ext/standard/var_unserializer.re"
|
||||
#line 710 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
zend_long elements = parse_iv(start + 2);
|
||||
/* use iv() not uiv() in order to check data range */
|
||||
*p = YYCURSOR;
|
||||
if (!var_hash) return 0;
|
||||
|
||||
if (elements < 0) {
|
||||
return 0;
|
||||
@ -891,7 +904,7 @@ yy34:
|
||||
|
||||
return finish_nested_data(UNSERIALIZE_PASSTHRU);
|
||||
}
|
||||
#line 895 "ext/standard/var_unserializer.c"
|
||||
#line 908 "ext/standard/var_unserializer.c"
|
||||
yy39:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == '+') goto yy40;
|
||||
@ -912,7 +925,7 @@ yy41:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych != '"') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 673 "ext/standard/var_unserializer.re"
|
||||
#line 682 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
size_t len, maxlen;
|
||||
zend_string *str;
|
||||
@ -940,7 +953,7 @@ yy41:
|
||||
ZVAL_STR(rval, str);
|
||||
return 1;
|
||||
}
|
||||
#line 944 "ext/standard/var_unserializer.c"
|
||||
#line 957 "ext/standard/var_unserializer.c"
|
||||
yy46:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == '+') goto yy47;
|
||||
@ -961,7 +974,7 @@ yy48:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych != '"') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 646 "ext/standard/var_unserializer.re"
|
||||
#line 655 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
size_t len, maxlen;
|
||||
char *str;
|
||||
@ -988,7 +1001,7 @@ yy48:
|
||||
ZVAL_STRINGL(rval, str, len);
|
||||
return 1;
|
||||
}
|
||||
#line 992 "ext/standard/var_unserializer.c"
|
||||
#line 1005 "ext/standard/var_unserializer.c"
|
||||
yy53:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= '/') {
|
||||
@ -1076,7 +1089,7 @@ yy61:
|
||||
}
|
||||
yy63:
|
||||
++YYCURSOR;
|
||||
#line 637 "ext/standard/var_unserializer.re"
|
||||
#line 646 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
#if SIZEOF_ZEND_LONG == 4
|
||||
use_double:
|
||||
@ -1085,7 +1098,7 @@ use_double:
|
||||
ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
|
||||
return 1;
|
||||
}
|
||||
#line 1089 "ext/standard/var_unserializer.c"
|
||||
#line 1102 "ext/standard/var_unserializer.c"
|
||||
yy65:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= ',') {
|
||||
@ -1144,7 +1157,7 @@ yy73:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych != ';') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 621 "ext/standard/var_unserializer.re"
|
||||
#line 630 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
*p = YYCURSOR;
|
||||
|
||||
@ -1160,7 +1173,7 @@ yy73:
|
||||
|
||||
return 1;
|
||||
}
|
||||
#line 1164 "ext/standard/var_unserializer.c"
|
||||
#line 1177 "ext/standard/var_unserializer.c"
|
||||
yy76:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych == 'N') goto yy73;
|
||||
@ -1187,7 +1200,7 @@ yy79:
|
||||
if (yych <= '9') goto yy79;
|
||||
if (yych != ';') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 595 "ext/standard/var_unserializer.re"
|
||||
#line 604 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
#if SIZEOF_ZEND_LONG == 4
|
||||
int digits = YYCURSOR - start - 3;
|
||||
@ -1213,7 +1226,7 @@ yy79:
|
||||
ZVAL_LONG(rval, parse_iv(start + 2));
|
||||
return 1;
|
||||
}
|
||||
#line 1217 "ext/standard/var_unserializer.c"
|
||||
#line 1230 "ext/standard/var_unserializer.c"
|
||||
yy83:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= '/') goto yy18;
|
||||
@ -1221,22 +1234,22 @@ yy83:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych != ';') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 589 "ext/standard/var_unserializer.re"
|
||||
#line 598 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
*p = YYCURSOR;
|
||||
ZVAL_BOOL(rval, parse_iv(start + 2));
|
||||
return 1;
|
||||
}
|
||||
#line 1231 "ext/standard/var_unserializer.c"
|
||||
#line 1244 "ext/standard/var_unserializer.c"
|
||||
yy87:
|
||||
++YYCURSOR;
|
||||
#line 583 "ext/standard/var_unserializer.re"
|
||||
#line 592 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
*p = YYCURSOR;
|
||||
ZVAL_NULL(rval);
|
||||
return 1;
|
||||
}
|
||||
#line 1240 "ext/standard/var_unserializer.c"
|
||||
#line 1253 "ext/standard/var_unserializer.c"
|
||||
yy89:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= ',') {
|
||||
@ -1259,7 +1272,7 @@ yy91:
|
||||
if (yych <= '9') goto yy91;
|
||||
if (yych != ';') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 560 "ext/standard/var_unserializer.re"
|
||||
#line 569 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
zend_long id;
|
||||
|
||||
@ -1282,7 +1295,7 @@ yy91:
|
||||
|
||||
return 1;
|
||||
}
|
||||
#line 1286 "ext/standard/var_unserializer.c"
|
||||
#line 1299 "ext/standard/var_unserializer.c"
|
||||
yy95:
|
||||
yych = *++YYCURSOR;
|
||||
if (yych <= ',') {
|
||||
@ -1305,7 +1318,7 @@ yy97:
|
||||
if (yych <= '9') goto yy97;
|
||||
if (yych != ';') goto yy18;
|
||||
++YYCURSOR;
|
||||
#line 538 "ext/standard/var_unserializer.re"
|
||||
#line 547 "ext/standard/var_unserializer.re"
|
||||
{
|
||||
zend_long id;
|
||||
|
||||
@ -1327,9 +1340,9 @@ yy97:
|
||||
|
||||
return 1;
|
||||
}
|
||||
#line 1331 "ext/standard/var_unserializer.c"
|
||||
#line 1344 "ext/standard/var_unserializer.c"
|
||||
}
|
||||
#line 883 "ext/standard/var_unserializer.re"
|
||||
#line 895 "ext/standard/var_unserializer.re"
|
||||
|
||||
|
||||
return 0;
|
||||
|
@ -101,9 +101,15 @@ PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
|
||||
#if 0
|
||||
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval *rval)
|
||||
{
|
||||
var_dtor_entries *var_hash = (*var_hashx)->last_dtor;
|
||||
var_entries *var_hash;
|
||||
|
||||
if (!var_hashx || !*var_hashx) {
|
||||
return;
|
||||
}
|
||||
|
||||
var_hash = (*var_hashx)->last_dtor;
|
||||
#if VAR_ENTRIES_DBG
|
||||
fprintf(stderr, "var_push_dtor_no_addref(%ld): %d (%d)\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
|
||||
fprintf(stderr, "var_push_dtor_no_addref(%p, %ld): %d (%d)\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval), Z_REFCOUNT_PP(rval));
|
||||
#endif
|
||||
|
||||
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
||||
@ -181,6 +187,9 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
|
||||
|
||||
while (var_dtor_hash) {
|
||||
for (i = 0; i < var_dtor_hash->used_slots; i++) {
|
||||
#if VAR_ENTRIES_DBG
|
||||
fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_dtor_hash->data[i], Z_REFCOUNT_P(var_dtor_hash->data[i]));
|
||||
#endif
|
||||
zval_ptr_dtor(&var_dtor_hash->data[i]);
|
||||
}
|
||||
next = var_dtor_hash->next;
|
||||
@ -702,6 +711,7 @@ use_double:
|
||||
zend_long elements = parse_iv(start + 2);
|
||||
/* use iv() not uiv() in order to check data range */
|
||||
*p = YYCURSOR;
|
||||
if (!var_hash) return 0;
|
||||
|
||||
if (elements < 0) {
|
||||
return 0;
|
||||
@ -720,6 +730,7 @@ use_double:
|
||||
}
|
||||
|
||||
"o:" iv ":" ["] {
|
||||
if (!var_hash) return 0;
|
||||
|
||||
//??? INIT_PZVAL(rval);
|
||||
|
||||
@ -741,6 +752,7 @@ object ":" uiv ":" ["] {
|
||||
zval retval;
|
||||
zval args[1];
|
||||
|
||||
if (!var_hash) return 0;
|
||||
if (*start == 'C') {
|
||||
custom_object = 1;
|
||||
}
|
||||
|
@ -218,7 +218,9 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
|
||||
if (error == 1) {
|
||||
for (i = nargs - 1; i >= 0; i--) {
|
||||
obj = valuePop(ctxt);
|
||||
xmlXPathFreeObject(obj);
|
||||
if (obj) {
|
||||
xmlXPathFreeObject(obj);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
|
||||
|
||||
/* it is a directory only, see #40228 */
|
||||
if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
|
||||
len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file);
|
||||
len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, path_cleaned);
|
||||
is_dir_only = 1;
|
||||
} else {
|
||||
memcpy(file_dirname, path_cleaned, path_cleaned_len);
|
||||
|
33
ext/zip/tests/bug70350.phpt
Normal file
33
ext/zip/tests/bug70350.phpt
Normal file
@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
Bug #70350 (ZipArchive::extractTo allows for directory traversal when creating directories)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if(!extension_loaded('zip')) die('skip');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$dir = dirname(__FILE__)."/bug70350";
|
||||
mkdir($dir);
|
||||
$archive = new ZipArchive();
|
||||
$archive->open("$dir/a.zip",ZipArchive::CREATE);
|
||||
$archive->addEmptyDir("../down2/");
|
||||
$archive->close();
|
||||
|
||||
$archive2 = new ZipArchive();
|
||||
$archive2->open("$dir/a.zip");
|
||||
$archive2->extractTo($dir);
|
||||
$archive2->close();
|
||||
var_dump(file_exists("$dir/down2/"));
|
||||
var_dump(file_exists("../down2/"));
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
$dir = dirname(__FILE__)."/bug70350";
|
||||
rmdir("$dir/down2");
|
||||
unlink("$dir/a.zip");
|
||||
rmdir($dir);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(false)
|
Loading…
Reference in New Issue
Block a user