mirror of
https://github.com/php/php-src.git
synced 2025-08-16 22:18:50 +02:00
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5: 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 for bug #69782 Add CVE IDs asigned (post release) to PHP 5.4.43 Add CVE IDs asigned to #69085 (PHP 5.4.39) 5.4.45 next Conflicts: ext/pcre/php_pcre.c ext/standard/var_unserializer.c ext/standard/var_unserializer.re ext/zip/php_zip.c
This commit is contained in:
commit
c19d59c550
24 changed files with 970 additions and 827 deletions
|
@ -2954,13 +2954,13 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||||
if (length<byte_count-1) {
|
if (length<byte_count-1) {
|
||||||
/* When there are any characters after the first NUL */
|
/* When there are any characters after the first NUL */
|
||||||
ImageInfo->CopyrightPhotographer = estrdup(value_ptr);
|
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);
|
spprintf(&ImageInfo->Copyright, 0, "%s, %s", value_ptr, value_ptr+length+1);
|
||||||
/* format = TAG_FMT_UNDEFINED; this musn't be ASCII */
|
/* format = TAG_FMT_UNDEFINED; this musn't be ASCII */
|
||||||
/* but we are not supposed to change this */
|
/* but we are not supposed to change this */
|
||||||
/* keep in mind that image_info does not store editor value */
|
/* keep in mind that image_info does not store editor value */
|
||||||
} else {
|
} else {
|
||||||
ImageInfo->Copyright = estrdup(value_ptr);
|
ImageInfo->Copyright = estrndup(value_ptr, byte_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3051,10 +3051,10 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAG_MAKE:
|
case TAG_MAKE:
|
||||||
ImageInfo->make = estrdup(value_ptr);
|
ImageInfo->make = estrndup(value_ptr, byte_count);
|
||||||
break;
|
break;
|
||||||
case TAG_MODEL:
|
case TAG_MODEL:
|
||||||
ImageInfo->model = estrdup(value_ptr);
|
ImageInfo->model = estrndup(value_ptr, byte_count);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TAG_MAKER_NOTE:
|
case TAG_MAKER_NOTE:
|
||||||
|
|
|
@ -336,7 +336,7 @@ PHP_HASH_API void PHP_HAVAL128Final(unsigned char *digest, PHP_HAVAL_CTX * conte
|
||||||
|
|
||||||
/* Pad out to 118 mod 128.
|
/* 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);
|
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
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.
|
/* 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);
|
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
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.
|
/* 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);
|
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
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.
|
/* 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);
|
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
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.
|
/* 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);
|
padLen = (index < 118) ? (118 - index) : (246 - index);
|
||||||
PHP_HAVALUpdate(context, PADDING, padLen);
|
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"
|
|
@ -709,7 +709,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 subpatterns array has been passed, fill it in with values. */
|
||||||
if (subpats != NULL) {
|
if (subpats != NULL) {
|
||||||
/* Try to get the list of substrings and display a warning if failed. */
|
/* 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) {
|
||||||
efree(subpat_names);
|
efree(subpat_names);
|
||||||
efree(offsets);
|
efree(offsets);
|
||||||
if (match_sets) efree(match_sets);
|
if (match_sets) efree(match_sets);
|
||||||
|
@ -1170,7 +1170,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
|
||||||
|
|
||||||
piece = subject + start_offset;
|
piece = subject + start_offset;
|
||||||
|
|
||||||
if (count > 0 && (limit == -1 || limit > 0)) {
|
if (count > 0 && (offsets[1] - offsets[0] >= 0) && (limit == -1 || limit > 0)) {
|
||||||
if (replace_count) {
|
if (replace_count) {
|
||||||
++*replace_count;
|
++*replace_count;
|
||||||
}
|
}
|
||||||
|
@ -1627,7 +1627,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If something matched */
|
/* If something matched */
|
||||||
if (count > 0) {
|
if (count > 0 && (offsets[1] - offsets[0] >= 0)) {
|
||||||
if (!no_empty || &subject[offsets[0]] != last_match) {
|
if (!no_empty || &subject[offsets[0]] != last_match) {
|
||||||
|
|
||||||
if (offset_capture) {
|
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) {
|
||||||
|
}
|
|
@ -216,16 +216,18 @@ static char *php_session_encode(int *newlen TSRMLS_DC) /* {{{ */
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static void php_session_decode(const char *val, int vallen TSRMLS_DC) /* {{{ */
|
static int php_session_decode(const char *val, int vallen TSRMLS_DC) /* {{{ */
|
||||||
{
|
{
|
||||||
if (!PS(serializer)) {
|
if (!PS(serializer)) {
|
||||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object");
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown session.serialize_handler. Failed to decode session object");
|
||||||
return;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) {
|
if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) {
|
||||||
php_session_destroy(TSRMLS_C);
|
php_session_destroy(TSRMLS_C);
|
||||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to decode session object. Session has been destroyed");
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to decode session object. Session has been destroyed");
|
||||||
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -947,8 +949,11 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */
|
||||||
ALLOC_INIT_ZVAL(current);
|
ALLOC_INIT_ZVAL(current);
|
||||||
if (php_var_unserialize(¤t, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
|
if (php_var_unserialize(¤t, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
|
||||||
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
|
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
|
||||||
|
} else {
|
||||||
|
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||||
|
return FAILURE;
|
||||||
}
|
}
|
||||||
zval_ptr_dtor(¤t);
|
var_push_dtor_no_addref(&var_hash, ¤t);
|
||||||
}
|
}
|
||||||
PS_ADD_VARL(name, namelen);
|
PS_ADD_VARL(name, namelen);
|
||||||
efree(name);
|
efree(name);
|
||||||
|
@ -1039,8 +1044,13 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */
|
||||||
ALLOC_INIT_ZVAL(current);
|
ALLOC_INIT_ZVAL(current);
|
||||||
if (php_var_unserialize(¤t, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
|
if (php_var_unserialize(¤t, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) {
|
||||||
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
|
php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC);
|
||||||
|
} else {
|
||||||
|
var_push_dtor_no_addref(&var_hash, ¤t);
|
||||||
|
efree(name);
|
||||||
|
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||||
|
return FAILURE;
|
||||||
}
|
}
|
||||||
zval_ptr_dtor(¤t);
|
var_push_dtor_no_addref(&var_hash, ¤t);
|
||||||
}
|
}
|
||||||
PS_ADD_VARL(name, namelen);
|
PS_ADD_VARL(name, namelen);
|
||||||
skip:
|
skip:
|
||||||
|
@ -2063,9 +2073,7 @@ static PHP_FUNCTION(session_decode)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
php_session_decode(str, str_len TSRMLS_CC);
|
RETVAL_BOOL(php_session_decode(str, str_len TSRMLS_CC) == SUCCESS);
|
||||||
|
|
||||||
RETURN_TRUE;
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
|
@ -53,563 +53,247 @@ array(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 4 --
|
-- Iteration 4 --
|
||||||
bool(true)
|
|
||||||
array(1) {
|
Warning: session_decode(): Failed to decode session object. Session has been destroyed in %s/session_decode_error2.php on line %d
|
||||||
["foo"]=>
|
bool(false)
|
||||||
NULL
|
array(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 5 --
|
-- Iteration 5 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 6 --
|
-- Iteration 6 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 7 --
|
-- Iteration 7 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 8 --
|
-- Iteration 8 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 9 --
|
-- Iteration 9 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 10 --
|
-- Iteration 10 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 11 --
|
-- Iteration 11 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 12 --
|
-- Iteration 12 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 13 --
|
-- Iteration 13 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 14 --
|
-- Iteration 14 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 15 --
|
-- Iteration 15 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 16 --
|
-- Iteration 16 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 17 --
|
-- Iteration 17 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 18 --
|
-- Iteration 18 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 19 --
|
-- Iteration 19 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 20 --
|
-- Iteration 20 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 21 --
|
-- Iteration 21 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 22 --
|
-- Iteration 22 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 23 --
|
-- Iteration 23 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 24 --
|
-- Iteration 24 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 25 --
|
-- Iteration 25 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 26 --
|
-- Iteration 26 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 27 --
|
-- Iteration 27 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 28 --
|
-- Iteration 28 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 29 --
|
-- Iteration 29 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 30 --
|
-- Iteration 30 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 31 --
|
-- Iteration 31 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 32 --
|
-- Iteration 32 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 33 --
|
-- Iteration 33 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 34 --
|
-- Iteration 34 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 35 --
|
-- Iteration 35 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 36 --
|
-- Iteration 36 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 37 --
|
-- Iteration 37 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 38 --
|
-- Iteration 38 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(1) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 39 --
|
-- Iteration 39 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 40 --
|
-- Iteration 40 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 41 --
|
-- Iteration 41 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 42 --
|
-- Iteration 42 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
NULL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 43 --
|
-- Iteration 43 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 44 --
|
-- Iteration 44 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 45 --
|
-- Iteration 45 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 46 --
|
-- Iteration 46 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 47 --
|
-- Iteration 47 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(2) {
|
array(0) {
|
||||||
["foo"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
["guff"]=>
|
|
||||||
&array(3) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
[1]=>
|
|
||||||
int(2)
|
|
||||||
[2]=>
|
|
||||||
int(3)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 48 --
|
-- Iteration 48 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(3) {
|
array(0) {
|
||||||
["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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 49 --
|
-- Iteration 49 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(3) {
|
array(0) {
|
||||||
["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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 50 --
|
-- Iteration 50 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(3) {
|
array(0) {
|
||||||
["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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Iteration 51 --
|
-- Iteration 51 --
|
||||||
bool(true)
|
bool(false)
|
||||||
array(3) {
|
array(0) {
|
||||||
["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_destroy(): Trying to destroy uninitialized session in %s/session_decode_error2.php on line %d
|
||||||
|
bool(false)
|
||||||
|
Done
|
||||||
|
|
|
@ -49,7 +49,7 @@ array(3) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Warning: session_decode(): Unknown session.serialize_handler. Failed to decode session object in %s on line %d
|
Warning: session_decode(): Unknown session.serialize_handler. Failed to decode session object in %s on line %d
|
||||||
bool(true)
|
bool(false)
|
||||||
array(3) {
|
array(3) {
|
||||||
["foo"]=>
|
["foo"]=>
|
||||||
int(1234567890)
|
int(1234567890)
|
||||||
|
|
|
@ -2921,8 +2921,10 @@ PHP_METHOD(SoapClient, __call)
|
||||||
}
|
}
|
||||||
zend_hash_internal_pointer_reset(default_headers);
|
zend_hash_internal_pointer_reset(default_headers);
|
||||||
while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
|
while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
|
||||||
|
if(Z_TYPE_PP(tmp) == IS_OBJECT) {
|
||||||
Z_ADDREF_PP(tmp);
|
Z_ADDREF_PP(tmp);
|
||||||
zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
|
zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
|
||||||
|
}
|
||||||
zend_hash_move_forward(default_headers);
|
zend_hash_move_forward(default_headers);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -4346,11 +4348,18 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
|
||||||
if (head) {
|
if (head) {
|
||||||
zval** header;
|
zval** header;
|
||||||
|
|
||||||
zend_hash_internal_pointer_reset(soap_headers);
|
for(zend_hash_internal_pointer_reset(soap_headers);
|
||||||
while (zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS) {
|
zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS;
|
||||||
HashTable *ht = Z_OBJPROP_PP(header);
|
zend_hash_move_forward(soap_headers)
|
||||||
|
) {
|
||||||
|
HashTable *ht;
|
||||||
zval **name, **ns, **tmp;
|
zval **name, **ns, **tmp;
|
||||||
|
|
||||||
|
if (Z_TYPE_PP(header) != IS_OBJECT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ht = Z_OBJPROP_PP(header);
|
||||||
if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
|
if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
|
||||||
Z_TYPE_PP(name) == IS_STRING &&
|
Z_TYPE_PP(name) == IS_STRING &&
|
||||||
zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
|
zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
|
||||||
|
@ -4389,7 +4398,6 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
|
||||||
xmlSetNs(h, nsptr);
|
xmlSetNs(h, nsptr);
|
||||||
set_soap_header_attributes(h, ht, version);
|
set_soap_header_attributes(h, ht, version);
|
||||||
}
|
}
|
||||||
zend_hash_move_forward(soap_headers);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
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"
|
|
@ -1219,6 +1219,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize)
|
||||||
zval_ptr_dtor(&elem);
|
zval_ptr_dtor(&elem);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
var_push_dtor(&var_hash, &elem);
|
||||||
|
|
||||||
spl_ptr_llist_push(intern->llist, elem TSRMLS_CC);
|
spl_ptr_llist_push(intern->llist, elem TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
|
@ -859,6 +859,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||||
zval_ptr_dtor(&pentry);
|
zval_ptr_dtor(&pentry);
|
||||||
goto outexcept;
|
goto outexcept;
|
||||||
}
|
}
|
||||||
|
var_push_dtor(&var_hash, &pentry);
|
||||||
if(Z_TYPE_P(pentry) != IS_OBJECT) {
|
if(Z_TYPE_P(pentry) != IS_OBJECT) {
|
||||||
zval_ptr_dtor(&pentry);
|
zval_ptr_dtor(&pentry);
|
||||||
goto outexcept;
|
goto outexcept;
|
||||||
|
@ -870,6 +871,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
|
||||||
zval_ptr_dtor(&pinf);
|
zval_ptr_dtor(&pinf);
|
||||||
goto outexcept;
|
goto outexcept;
|
||||||
}
|
}
|
||||||
|
var_push_dtor(&var_hash, &pinf);
|
||||||
}
|
}
|
||||||
|
|
||||||
hash = spl_object_storage_get_hash(intern, getThis(), pentry, &hash_len TSRMLS_CC);
|
hash = spl_object_storage_get_hash(intern, getThis(), pentry, &hash_len TSRMLS_CC);
|
||||||
|
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
ext/standard/tests/serialize/bug70219.phpt
Normal file
38
ext/standard/tests/serialize/bug70219.phpt
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
--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(0) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -948,6 +948,8 @@ PHP_FUNCTION(unserialize)
|
||||||
int buf_len;
|
int buf_len;
|
||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
php_unserialize_data_t var_hash;
|
php_unserialize_data_t var_hash;
|
||||||
|
int oldlevel;
|
||||||
|
zval *old_rval = return_value;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
|
@ -967,6 +969,20 @@ PHP_FUNCTION(unserialize)
|
||||||
}
|
}
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
if (return_value != old_rval) {
|
||||||
|
/*
|
||||||
|
* Terrible hack due to the fact that executor passes us zval *,
|
||||||
|
* but unserialize with r/R wants to replace it with another zval *
|
||||||
|
*/
|
||||||
|
zval_dtor(old_rval);
|
||||||
|
*old_rval = *return_value;
|
||||||
|
zval_copy_ctor(old_rval);
|
||||||
|
var_push_dtor_no_addref(&var_hash, &return_value);
|
||||||
|
/* FIXME: old_rval is not freed in some scenarios, see bug #70172
|
||||||
|
var_push_dtor_no_addref(&var_hash, &old_rval); */
|
||||||
|
} else {
|
||||||
|
var_push_dtor(&var_hash, &return_value);
|
||||||
|
}
|
||||||
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
|
@ -68,7 +68,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
|
||||||
|
|
||||||
var_hash = (*var_hashx)->last_dtor;
|
var_hash = (*var_hashx)->last_dtor;
|
||||||
#if VAR_ENTRIES_DBG
|
#if VAR_ENTRIES_DBG
|
||||||
fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
|
fprintf(stderr, "var_push_dtor(%p, %ld): %d\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
||||||
|
@ -91,9 +91,15 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
|
||||||
|
|
||||||
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval)
|
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval)
|
||||||
{
|
{
|
||||||
var_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
|
#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
|
#endif
|
||||||
|
|
||||||
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
||||||
|
@ -172,6 +178,9 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
|
||||||
|
|
||||||
while (var_hash) {
|
while (var_hash) {
|
||||||
for (i = 0; i < var_hash->used_slots; i++) {
|
for (i = 0; i < var_hash->used_slots; i++) {
|
||||||
|
#if VAR_ENTRIES_DBG
|
||||||
|
fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_hash->data[i], Z_REFCOUNT_P(var_hash->data[i]));
|
||||||
|
#endif
|
||||||
zval_ptr_dtor(&var_hash->data[i]);
|
zval_ptr_dtor(&var_hash->data[i]);
|
||||||
}
|
}
|
||||||
next = var_hash->next;
|
next = var_hash->next;
|
||||||
|
@ -232,7 +241,7 @@ static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen
|
||||||
#define YYMARKER marker
|
#define YYMARKER marker
|
||||||
|
|
||||||
|
|
||||||
#line 240 "ext/standard/var_unserializer.re"
|
#line 249 "ext/standard/var_unserializer.re"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,23 +312,20 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
|
||||||
ALLOC_INIT_ZVAL(key);
|
ALLOC_INIT_ZVAL(key);
|
||||||
|
|
||||||
if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
|
if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
|
||||||
zval_dtor(key);
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
FREE_ZVAL(key);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
|
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
|
||||||
zval_dtor(key);
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
FREE_ZVAL(key);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALLOC_INIT_ZVAL(data);
|
ALLOC_INIT_ZVAL(data);
|
||||||
|
|
||||||
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
|
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
|
||||||
zval_dtor(key);
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
FREE_ZVAL(key);
|
var_push_dtor_no_addref(var_hash, &data);
|
||||||
zval_ptr_dtor(&data);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,9 +354,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
|
||||||
sizeof data, NULL);
|
sizeof data, NULL);
|
||||||
}
|
}
|
||||||
var_push_dtor(var_hash, &data);
|
var_push_dtor(var_hash, &data);
|
||||||
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
zval_dtor(key);
|
|
||||||
FREE_ZVAL(key);
|
|
||||||
|
|
||||||
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
|
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
|
||||||
(*p)--;
|
(*p)--;
|
||||||
|
@ -478,7 +482,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#line 482 "ext/standard/var_unserializer.c"
|
#line 486 "ext/standard/var_unserializer.c"
|
||||||
{
|
{
|
||||||
YYCTYPE yych;
|
YYCTYPE yych;
|
||||||
static const unsigned char yybm[] = {
|
static const unsigned char yybm[] = {
|
||||||
|
@ -538,9 +542,9 @@ yy2:
|
||||||
yych = *(YYMARKER = ++YYCURSOR);
|
yych = *(YYMARKER = ++YYCURSOR);
|
||||||
if (yych == ':') goto yy95;
|
if (yych == ':') goto yy95;
|
||||||
yy3:
|
yy3:
|
||||||
#line 833 "ext/standard/var_unserializer.re"
|
#line 840 "ext/standard/var_unserializer.re"
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
#line 544 "ext/standard/var_unserializer.c"
|
#line 548 "ext/standard/var_unserializer.c"
|
||||||
yy4:
|
yy4:
|
||||||
yych = *(YYMARKER = ++YYCURSOR);
|
yych = *(YYMARKER = ++YYCURSOR);
|
||||||
if (yych == ':') goto yy89;
|
if (yych == ':') goto yy89;
|
||||||
|
@ -583,13 +587,13 @@ yy13:
|
||||||
goto yy3;
|
goto yy3;
|
||||||
yy14:
|
yy14:
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 827 "ext/standard/var_unserializer.re"
|
#line 834 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
/* this is the case where we have less data than planned */
|
/* this is the case where we have less data than planned */
|
||||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
|
||||||
return 0; /* not sure if it should be 0 or 1 here? */
|
return 0; /* not sure if it should be 0 or 1 here? */
|
||||||
}
|
}
|
||||||
#line 593 "ext/standard/var_unserializer.c"
|
#line 597 "ext/standard/var_unserializer.c"
|
||||||
yy16:
|
yy16:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
goto yy3;
|
goto yy3;
|
||||||
|
@ -620,7 +624,7 @@ yy20:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych != '"') goto yy18;
|
if (yych != '"') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 681 "ext/standard/var_unserializer.re"
|
#line 687 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
size_t len, len2, len3, maxlen;
|
size_t len, len2, len3, maxlen;
|
||||||
long elements;
|
long elements;
|
||||||
|
@ -636,6 +640,7 @@ yy20:
|
||||||
zval **args[1];
|
zval **args[1];
|
||||||
zval *arg_func_name;
|
zval *arg_func_name;
|
||||||
|
|
||||||
|
if (!var_hash) return 0;
|
||||||
if (*start == 'C') {
|
if (*start == 'C') {
|
||||||
custom_object = 1;
|
custom_object = 1;
|
||||||
}
|
}
|
||||||
|
@ -766,7 +771,7 @@ yy20:
|
||||||
|
|
||||||
return object_common2(UNSERIALIZE_PASSTHRU, elements);
|
return object_common2(UNSERIALIZE_PASSTHRU, elements);
|
||||||
}
|
}
|
||||||
#line 770 "ext/standard/var_unserializer.c"
|
#line 775 "ext/standard/var_unserializer.c"
|
||||||
yy25:
|
yy25:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych <= ',') {
|
if (yych <= ',') {
|
||||||
|
@ -791,15 +796,16 @@ yy27:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych != '"') goto yy18;
|
if (yych != '"') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 673 "ext/standard/var_unserializer.re"
|
#line 678 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
|
if (!var_hash) return 0;
|
||||||
|
|
||||||
INIT_PZVAL(*rval);
|
INIT_PZVAL(*rval);
|
||||||
|
|
||||||
return object_common2(UNSERIALIZE_PASSTHRU,
|
return object_common2(UNSERIALIZE_PASSTHRU,
|
||||||
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
|
object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
|
||||||
}
|
}
|
||||||
#line 803 "ext/standard/var_unserializer.c"
|
#line 809 "ext/standard/var_unserializer.c"
|
||||||
yy32:
|
yy32:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych == '+') goto yy33;
|
if (yych == '+') goto yy33;
|
||||||
|
@ -820,11 +826,12 @@ yy34:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych != '{') goto yy18;
|
if (yych != '{') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 653 "ext/standard/var_unserializer.re"
|
#line 657 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
long elements = parse_iv(start + 2);
|
long elements = parse_iv(start + 2);
|
||||||
/* use iv() not uiv() in order to check data range */
|
/* use iv() not uiv() in order to check data range */
|
||||||
*p = YYCURSOR;
|
*p = YYCURSOR;
|
||||||
|
if (!var_hash) return 0;
|
||||||
|
|
||||||
if (elements < 0) {
|
if (elements < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -840,7 +847,7 @@ yy34:
|
||||||
|
|
||||||
return finish_nested_data(UNSERIALIZE_PASSTHRU);
|
return finish_nested_data(UNSERIALIZE_PASSTHRU);
|
||||||
}
|
}
|
||||||
#line 844 "ext/standard/var_unserializer.c"
|
#line 851 "ext/standard/var_unserializer.c"
|
||||||
yy39:
|
yy39:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych == '+') goto yy40;
|
if (yych == '+') goto yy40;
|
||||||
|
@ -861,7 +868,7 @@ yy41:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych != '"') goto yy18;
|
if (yych != '"') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 624 "ext/standard/var_unserializer.re"
|
#line 628 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
size_t len, maxlen;
|
size_t len, maxlen;
|
||||||
char *str;
|
char *str;
|
||||||
|
@ -890,7 +897,7 @@ yy41:
|
||||||
ZVAL_STRINGL(*rval, str, len, 0);
|
ZVAL_STRINGL(*rval, str, len, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 894 "ext/standard/var_unserializer.c"
|
#line 901 "ext/standard/var_unserializer.c"
|
||||||
yy46:
|
yy46:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych == '+') goto yy47;
|
if (yych == '+') goto yy47;
|
||||||
|
@ -911,7 +918,7 @@ yy48:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych != '"') goto yy18;
|
if (yych != '"') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 596 "ext/standard/var_unserializer.re"
|
#line 600 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
size_t len, maxlen;
|
size_t len, maxlen;
|
||||||
char *str;
|
char *str;
|
||||||
|
@ -939,7 +946,7 @@ yy48:
|
||||||
ZVAL_STRINGL(*rval, str, len, 1);
|
ZVAL_STRINGL(*rval, str, len, 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 943 "ext/standard/var_unserializer.c"
|
#line 950 "ext/standard/var_unserializer.c"
|
||||||
yy53:
|
yy53:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych <= '/') {
|
if (yych <= '/') {
|
||||||
|
@ -1027,7 +1034,7 @@ yy61:
|
||||||
}
|
}
|
||||||
yy63:
|
yy63:
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 586 "ext/standard/var_unserializer.re"
|
#line 590 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
#if SIZEOF_LONG == 4
|
#if SIZEOF_LONG == 4
|
||||||
use_double:
|
use_double:
|
||||||
|
@ -1037,7 +1044,7 @@ use_double:
|
||||||
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
|
ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 1041 "ext/standard/var_unserializer.c"
|
#line 1048 "ext/standard/var_unserializer.c"
|
||||||
yy65:
|
yy65:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych <= ',') {
|
if (yych <= ',') {
|
||||||
|
@ -1096,7 +1103,7 @@ yy73:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych != ';') goto yy18;
|
if (yych != ';') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 571 "ext/standard/var_unserializer.re"
|
#line 575 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
*p = YYCURSOR;
|
*p = YYCURSOR;
|
||||||
INIT_PZVAL(*rval);
|
INIT_PZVAL(*rval);
|
||||||
|
@ -1111,7 +1118,7 @@ yy73:
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 1115 "ext/standard/var_unserializer.c"
|
#line 1122 "ext/standard/var_unserializer.c"
|
||||||
yy76:
|
yy76:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych == 'N') goto yy73;
|
if (yych == 'N') goto yy73;
|
||||||
|
@ -1138,7 +1145,7 @@ yy79:
|
||||||
if (yych <= '9') goto yy79;
|
if (yych <= '9') goto yy79;
|
||||||
if (yych != ';') goto yy18;
|
if (yych != ';') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 544 "ext/standard/var_unserializer.re"
|
#line 548 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
#if SIZEOF_LONG == 4
|
#if SIZEOF_LONG == 4
|
||||||
int digits = YYCURSOR - start - 3;
|
int digits = YYCURSOR - start - 3;
|
||||||
|
@ -1165,7 +1172,7 @@ yy79:
|
||||||
ZVAL_LONG(*rval, parse_iv(start + 2));
|
ZVAL_LONG(*rval, parse_iv(start + 2));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 1169 "ext/standard/var_unserializer.c"
|
#line 1176 "ext/standard/var_unserializer.c"
|
||||||
yy83:
|
yy83:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych <= '/') goto yy18;
|
if (yych <= '/') goto yy18;
|
||||||
|
@ -1173,24 +1180,24 @@ yy83:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych != ';') goto yy18;
|
if (yych != ';') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 537 "ext/standard/var_unserializer.re"
|
#line 541 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
*p = YYCURSOR;
|
*p = YYCURSOR;
|
||||||
INIT_PZVAL(*rval);
|
INIT_PZVAL(*rval);
|
||||||
ZVAL_BOOL(*rval, parse_iv(start + 2));
|
ZVAL_BOOL(*rval, parse_iv(start + 2));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 1184 "ext/standard/var_unserializer.c"
|
#line 1191 "ext/standard/var_unserializer.c"
|
||||||
yy87:
|
yy87:
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 530 "ext/standard/var_unserializer.re"
|
#line 534 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
*p = YYCURSOR;
|
*p = YYCURSOR;
|
||||||
INIT_PZVAL(*rval);
|
INIT_PZVAL(*rval);
|
||||||
ZVAL_NULL(*rval);
|
ZVAL_NULL(*rval);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 1194 "ext/standard/var_unserializer.c"
|
#line 1201 "ext/standard/var_unserializer.c"
|
||||||
yy89:
|
yy89:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych <= ',') {
|
if (yych <= ',') {
|
||||||
|
@ -1213,7 +1220,7 @@ yy91:
|
||||||
if (yych <= '9') goto yy91;
|
if (yych <= '9') goto yy91;
|
||||||
if (yych != ';') goto yy18;
|
if (yych != ';') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 507 "ext/standard/var_unserializer.re"
|
#line 511 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
long id;
|
long id;
|
||||||
|
|
||||||
|
@ -1236,7 +1243,7 @@ yy91:
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 1240 "ext/standard/var_unserializer.c"
|
#line 1247 "ext/standard/var_unserializer.c"
|
||||||
yy95:
|
yy95:
|
||||||
yych = *++YYCURSOR;
|
yych = *++YYCURSOR;
|
||||||
if (yych <= ',') {
|
if (yych <= ',') {
|
||||||
|
@ -1259,7 +1266,7 @@ yy97:
|
||||||
if (yych <= '9') goto yy97;
|
if (yych <= '9') goto yy97;
|
||||||
if (yych != ';') goto yy18;
|
if (yych != ';') goto yy18;
|
||||||
++YYCURSOR;
|
++YYCURSOR;
|
||||||
#line 486 "ext/standard/var_unserializer.re"
|
#line 490 "ext/standard/var_unserializer.re"
|
||||||
{
|
{
|
||||||
long id;
|
long id;
|
||||||
|
|
||||||
|
@ -1272,7 +1279,7 @@ yy97:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*rval != NULL) {
|
if (*rval != NULL) {
|
||||||
zval_ptr_dtor(rval);
|
var_push_dtor_no_addref(var_hash, rval);
|
||||||
}
|
}
|
||||||
*rval = *rval_ref;
|
*rval = *rval_ref;
|
||||||
Z_ADDREF_PP(rval);
|
Z_ADDREF_PP(rval);
|
||||||
|
@ -1280,9 +1287,9 @@ yy97:
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 1284 "ext/standard/var_unserializer.c"
|
#line 1291 "ext/standard/var_unserializer.c"
|
||||||
}
|
}
|
||||||
#line 835 "ext/standard/var_unserializer.re"
|
#line 842 "ext/standard/var_unserializer.re"
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -66,7 +66,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
|
||||||
|
|
||||||
var_hash = (*var_hashx)->last_dtor;
|
var_hash = (*var_hashx)->last_dtor;
|
||||||
#if VAR_ENTRIES_DBG
|
#if VAR_ENTRIES_DBG
|
||||||
fprintf(stderr, "var_push_dtor(%ld): %d\n", var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
|
fprintf(stderr, "var_push_dtor(%p, %ld): %d\n", *rval, var_hash?var_hash->used_slots:-1L, Z_TYPE_PP(rval));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
||||||
|
@ -89,9 +89,15 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval **rval)
|
||||||
|
|
||||||
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval)
|
PHPAPI void var_push_dtor_no_addref(php_unserialize_data_t *var_hashx, zval **rval)
|
||||||
{
|
{
|
||||||
var_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
|
#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
|
#endif
|
||||||
|
|
||||||
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
if (!var_hash || var_hash->used_slots == VAR_ENTRIES_MAX) {
|
||||||
|
@ -170,6 +176,9 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
|
||||||
|
|
||||||
while (var_hash) {
|
while (var_hash) {
|
||||||
for (i = 0; i < var_hash->used_slots; i++) {
|
for (i = 0; i < var_hash->used_slots; i++) {
|
||||||
|
#if VAR_ENTRIES_DBG
|
||||||
|
fprintf(stderr, "var_destroy dtor(%p, %ld)\n", var_hash->data[i], Z_REFCOUNT_P(var_hash->data[i]));
|
||||||
|
#endif
|
||||||
zval_ptr_dtor(&var_hash->data[i]);
|
zval_ptr_dtor(&var_hash->data[i]);
|
||||||
}
|
}
|
||||||
next = var_hash->next;
|
next = var_hash->next;
|
||||||
|
@ -307,23 +316,20 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
|
||||||
ALLOC_INIT_ZVAL(key);
|
ALLOC_INIT_ZVAL(key);
|
||||||
|
|
||||||
if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
|
if (!php_var_unserialize(&key, p, max, NULL TSRMLS_CC)) {
|
||||||
zval_dtor(key);
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
FREE_ZVAL(key);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
|
if (Z_TYPE_P(key) != IS_LONG && Z_TYPE_P(key) != IS_STRING) {
|
||||||
zval_dtor(key);
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
FREE_ZVAL(key);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALLOC_INIT_ZVAL(data);
|
ALLOC_INIT_ZVAL(data);
|
||||||
|
|
||||||
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
|
if (!php_var_unserialize(&data, p, max, var_hash TSRMLS_CC)) {
|
||||||
zval_dtor(key);
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
FREE_ZVAL(key);
|
var_push_dtor_no_addref(var_hash, &data);
|
||||||
zval_ptr_dtor(&data);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,9 +358,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
|
||||||
sizeof data, NULL);
|
sizeof data, NULL);
|
||||||
}
|
}
|
||||||
var_push_dtor(var_hash, &data);
|
var_push_dtor(var_hash, &data);
|
||||||
|
var_push_dtor_no_addref(var_hash, &key);
|
||||||
zval_dtor(key);
|
|
||||||
FREE_ZVAL(key);
|
|
||||||
|
|
||||||
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
|
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {
|
||||||
(*p)--;
|
(*p)--;
|
||||||
|
@ -495,7 +499,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*rval != NULL) {
|
if (*rval != NULL) {
|
||||||
zval_ptr_dtor(rval);
|
var_push_dtor_no_addref(var_hash, rval);
|
||||||
}
|
}
|
||||||
*rval = *rval_ref;
|
*rval = *rval_ref;
|
||||||
Z_ADDREF_PP(rval);
|
Z_ADDREF_PP(rval);
|
||||||
|
@ -654,6 +658,7 @@ use_double:
|
||||||
long elements = parse_iv(start + 2);
|
long elements = parse_iv(start + 2);
|
||||||
/* use iv() not uiv() in order to check data range */
|
/* use iv() not uiv() in order to check data range */
|
||||||
*p = YYCURSOR;
|
*p = YYCURSOR;
|
||||||
|
if (!var_hash) return 0;
|
||||||
|
|
||||||
if (elements < 0) {
|
if (elements < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -671,6 +676,7 @@ use_double:
|
||||||
}
|
}
|
||||||
|
|
||||||
"o:" iv ":" ["] {
|
"o:" iv ":" ["] {
|
||||||
|
if (!var_hash) return 0;
|
||||||
|
|
||||||
INIT_PZVAL(*rval);
|
INIT_PZVAL(*rval);
|
||||||
|
|
||||||
|
@ -693,6 +699,7 @@ object ":" uiv ":" ["] {
|
||||||
zval **args[1];
|
zval **args[1];
|
||||||
zval *arg_func_name;
|
zval *arg_func_name;
|
||||||
|
|
||||||
|
if (!var_hash) return 0;
|
||||||
if (*start == 'C') {
|
if (*start == 'C') {
|
||||||
custom_object = 1;
|
custom_object = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,8 +223,10 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
|
||||||
if (error == 1) {
|
if (error == 1) {
|
||||||
for (i = nargs - 1; i >= 0; i--) {
|
for (i = nargs - 1; i >= 0; i--) {
|
||||||
obj = valuePop(ctxt);
|
obj = valuePop(ctxt);
|
||||||
|
if (obj) {
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,9 +304,11 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
|
||||||
fci.function_table = EG(function_table);
|
fci.function_table = EG(function_table);
|
||||||
|
|
||||||
obj = valuePop(ctxt);
|
obj = valuePop(ctxt);
|
||||||
if (obj->stringval == NULL) {
|
if (obj == NULL || obj->stringval == NULL) {
|
||||||
|
if (obj) {
|
||||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
|
||||||
xmlXPathFreeObject(obj);
|
xmlXPathFreeObject(obj);
|
||||||
|
}
|
||||||
valuePush(ctxt, xmlXPathNewString(""));
|
valuePush(ctxt, xmlXPathNewString(""));
|
||||||
if (fci.param_count > 0) {
|
if (fci.param_count > 0) {
|
||||||
for (i = 0; i < nargs - 1; i++) {
|
for (i = 0; i < nargs - 1; i++) {
|
||||||
|
|
|
@ -200,7 +200,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
|
||||||
|
|
||||||
/* it is a directory only, see #40228 */
|
/* it is a directory only, see #40228 */
|
||||||
if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
|
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;
|
is_dir_only = 1;
|
||||||
} else {
|
} else {
|
||||||
memcpy(file_dirname, path_cleaned, path_cleaned_len);
|
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…
Add table
Add a link
Reference in a new issue