From 102d53bd275f5c08e7042eaac5fb74f73eded62a Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sun, 14 Feb 2016 00:44:03 -0600 Subject: [PATCH 1/5] Random: fix for issues with serialize() --- phpseclib/Crypt/Random.php | 52 +++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 4ff913ab..9f2487cb 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -148,13 +148,13 @@ if (!function_exists('crypt_random_string')) { session_start(); $v = $seed = $_SESSION['seed'] = pack('H*', sha1( - serialize($_SERVER) . - serialize($_POST) . - serialize($_GET) . - serialize($_COOKIE) . - serialize($GLOBALS) . - serialize($_SESSION) . - serialize($_OLD_SESSION) + phpseclib_safe_serialize($_SERVER) . + phpseclib_safe_serialize($_POST) . + phpseclib_safe_serialize($_GET) . + phpseclib_safe_serialize($_COOKIE) . + phpseclib_safe_serialize($GLOBALS) . + phpseclib_safe_serialize($_SESSION) . + phpseclib_safe_serialize($_OLD_SESSION) )); if (!isset($_SESSION['count'])) { $_SESSION['count'] = 0; @@ -260,6 +260,44 @@ if (!function_exists('crypt_random_string')) { } } +if (!function_exists('phpseclib_safe_serialize')) { + /** + * Safely serialize variables + * + * If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier. + * PHP 5.3 will emit a warning. + * + * @param mixed $arr + * @param array $refs optional + * @access public + */ + function phpseclib_safe_serialize(&$arr) + { + if (is_object($arr)) { + return ''; + } + if (!is_array($arr)) { + return serialize($arr); + } + $safearr = array(); + $unset = false; + if (!isset($arr['__phpseclib_marker'])) { + $unset = true; + $arr['__phpseclib_marker'] = true; + } + foreach (array_keys($arr) as $key) { + if (is_object($arr[$key]) || $key == '__phpseclib_marker') { + continue; + } + $safearr[$key] = is_array($arr[$key]) ? phpseclib_safe_serialize($arr[$key], $refs) : $arr[$key]; + } + if ($unset) { + unset($arr['__phpseclib_marker']); + } + return serialize($safearr); + } +} + if (!function_exists('phpseclib_resolve_include_path')) { /** * Resolve filename against the include path. From 047f2617f164f8f95d1c576994008719af68fecb Mon Sep 17 00:00:00 2001 From: Joey3000 Date: Sun, 14 Feb 2016 13:40:58 +0100 Subject: [PATCH 2/5] Circular reference handling improvement Refs https://github.com/phpseclib/phpseclib/pull/934/files#r52838650 This does the following: * Addresses the comments to https://github.com/terrafrost/phpseclib/commit/102d53bd275f5c08e7042eaac5fb74f73eded62a * Fixes an "Allowed memory size of ... bytes exhausted" issue and simplifies the implementation, bringing it closer to the example in https://stackoverflow.com/questions/9042142/detecting-infinite-array-recursion-in-php/9293146#9293146 --- phpseclib/Crypt/Random.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 9f2487cb..46a441ec 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -268,7 +268,6 @@ if (!function_exists('phpseclib_safe_serialize')) { * PHP 5.3 will emit a warning. * * @param mixed $arr - * @param array $refs optional * @access public */ function phpseclib_safe_serialize(&$arr) @@ -280,20 +279,16 @@ if (!function_exists('phpseclib_safe_serialize')) { return serialize($arr); } $safearr = array(); - $unset = false; - if (!isset($arr['__phpseclib_marker'])) { - $unset = true; - $arr['__phpseclib_marker'] = true; - } + $arr['__phpseclib_marker'] = true; foreach (array_keys($arr) as $key) { - if (is_object($arr[$key]) || $key == '__phpseclib_marker') { - continue; + // do not recurse on: + // - the '__phpseclib_marker' key itself + // - a circular reference (marked with that key) + if ($key !== '__phpseclib_marker' && !isset($arr[$key]['__phpseclib_marker'])) { + $safearr[$key] = is_array($arr[$key]) ? phpseclib_safe_serialize($arr[$key]) : $arr[$key]; } - $safearr[$key] = is_array($arr[$key]) ? phpseclib_safe_serialize($arr[$key], $refs) : $arr[$key]; - } - if ($unset) { - unset($arr['__phpseclib_marker']); } + unset($arr['__phpseclib_marker']); return serialize($safearr); } } From 6eb35eb42c6833d58f8aae41ece77e0541bf7e23 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sun, 14 Feb 2016 11:23:53 -0600 Subject: [PATCH 3/5] Random: a few more tweaks --- phpseclib/Crypt/Random.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 46a441ec..2a5b8d94 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -148,10 +148,10 @@ if (!function_exists('crypt_random_string')) { session_start(); $v = $seed = $_SESSION['seed'] = pack('H*', sha1( - phpseclib_safe_serialize($_SERVER) . - phpseclib_safe_serialize($_POST) . - phpseclib_safe_serialize($_GET) . - phpseclib_safe_serialize($_COOKIE) . + (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') . + (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') . + (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') . + (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') . phpseclib_safe_serialize($GLOBALS) . phpseclib_safe_serialize($_SESSION) . phpseclib_safe_serialize($_OLD_SESSION) From 062aa41ba002684101fe5dd526c161c9afa6085d Mon Sep 17 00:00:00 2001 From: Joey3000 Date: Tue, 16 Feb 2016 19:41:41 +0100 Subject: [PATCH 4/5] Fixing Uncaught Error: Cannot use object of type test as array Refs https://github.com/phpseclib/phpseclib/pull/934/files#r53035721 --- phpseclib/Crypt/Random.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 2a5b8d94..f28b180a 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -275,17 +275,19 @@ if (!function_exists('phpseclib_safe_serialize')) { if (is_object($arr)) { return ''; } + // prevent circular array recursion + if (isset($arr['__phpseclib_marker'])) { + return ''; + } if (!is_array($arr)) { return serialize($arr); } $safearr = array(); $arr['__phpseclib_marker'] = true; foreach (array_keys($arr) as $key) { - // do not recurse on: - // - the '__phpseclib_marker' key itself - // - a circular reference (marked with that key) - if ($key !== '__phpseclib_marker' && !isset($arr[$key]['__phpseclib_marker'])) { - $safearr[$key] = is_array($arr[$key]) ? phpseclib_safe_serialize($arr[$key]) : $arr[$key]; + // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage + if ($key !== '__phpseclib_marker') { + $safearr[$key] = phpseclib_safe_serialize($arr[$key]); } } unset($arr['__phpseclib_marker']); From 94b669d7ed4251519cbfcd15c3b1da6d790dcf83 Mon Sep 17 00:00:00 2001 From: Joey3000 Date: Tue, 16 Feb 2016 20:45:05 +0100 Subject: [PATCH 5/5] Reorder array checks Make sure that `if (isset($arr['__phpseclib_marker']))` is done on an array only. --- phpseclib/Crypt/Random.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index f28b180a..472d47c0 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -275,13 +275,13 @@ if (!function_exists('phpseclib_safe_serialize')) { if (is_object($arr)) { return ''; } + if (!is_array($arr)) { + return serialize($arr); + } // prevent circular array recursion if (isset($arr['__phpseclib_marker'])) { return ''; } - if (!is_array($arr)) { - return serialize($arr); - } $safearr = array(); $arr['__phpseclib_marker'] = true; foreach (array_keys($arr) as $key) {