From 398a10a58a764a18723bea394afdeac92f881e10 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 16 Jan 2023 23:09:58 +0100 Subject: [PATCH 1/2] Fix phpdbg segmentation fault in case of malformed input If you were to enter "w $>" the function would crash with a segmentation fault because last_index is still NULL at that point. Fix it by checking for NULL and erroring out if it is. Closes GH-10353 Signed-off-by: George Peter Banyard --- NEWS | 1 + sapi/phpdbg/phpdbg_utils.c | 3 +++ sapi/phpdbg/tests/watch_007.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 sapi/phpdbg/tests/watch_007.phpt diff --git a/NEWS b/NEWS index a8a72492a96..069ae40f597 100644 --- a/NEWS +++ b/NEWS @@ -46,6 +46,7 @@ PHP NEWS . Fix undefined behaviour in phpdbg_load_module_or_extension(). (nielsdos) . Fix NULL pointer dereference in phpdbg_create_conditional_breal(). (nielsdos) . Fix GH-9710: phpdbg memory leaks by option "-h" (nielsdos) + . Fix phpdbg segmentation fault in case of malformed input (nielsdos) - Posix: . Fix memory leak in posix_ttyname() (girgias) diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index 344b9c73e47..f638d608905 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -466,6 +466,9 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable case ']': break; case '>': + if (!last_index) { + goto error; + } if (last_index[index_len - 1] == '-') { new_index = 1; index_len--; diff --git a/sapi/phpdbg/tests/watch_007.phpt b/sapi/phpdbg/tests/watch_007.phpt new file mode 100644 index 00000000000..f1980d60dd9 --- /dev/null +++ b/sapi/phpdbg/tests/watch_007.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test malformed watchpoint name +--INI-- +opcache.optimization_level=0 +--PHPDBG-- +b test +r +w $> +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at test] +prompt> [Breakpoint #0 in test() at %s:%d, hits: 1] +>00004: } + 00005: test(); + 00006: $a = 2; +prompt> [Malformed input] +prompt> +--FILE-- + Date: Mon, 16 Jan 2023 22:33:06 +0100 Subject: [PATCH 2/2] Handle exceptions from __toString in XXH3's initialization The initialization routine for XXH3 was not prepared for exceptions from seed. Fix this by using try_convert_to_string. For discussion, please see: GH-10305 Closes GH-10352 Signed-off-by: George Peter Banyard --- NEWS | 3 +++ ext/hash/hash_xxhash.c | 4 +++- ext/hash/tests/xxhash_secret.phpt | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 069ae40f597..6d206f82523 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,9 @@ PHP NEWS . Fixed bug #67244 (Wrong owner:group for listening unix socket). (Jakub Zelenka) +- Hash: + . Handle exceptions from __toString in XXH3's initialization (nielsdos) + - LDAP: . Fixed bug GH-10112 (LDAP\Connection::__construct() refers to ldap_create()). (cmb) diff --git a/ext/hash/hash_xxhash.c b/ext/hash/hash_xxhash.c index 7ecedd81287..8a155c98622 100644 --- a/ext/hash/hash_xxhash.c +++ b/ext/hash/hash_xxhash.c @@ -174,7 +174,9 @@ zend_always_inline static void _PHP_XXH3_Init(PHP_XXH3_64_CTX *ctx, HashTable *a func_init_seed(&ctx->s, (XXH64_hash_t)Z_LVAL_P(_seed)); return; } else if (_secret) { - convert_to_string(_secret); + if (!try_convert_to_string(_secret)) { + return; + } size_t len = Z_STRLEN_P(_secret); if (len < PHP_XXH3_SECRET_SIZE_MIN) { zend_throw_error(NULL, "%s: Secret length must be >= %u bytes, %zu bytes passed", algo_name, XXH3_SECRET_SIZE_MIN, len); diff --git a/ext/hash/tests/xxhash_secret.phpt b/ext/hash/tests/xxhash_secret.phpt index 91e7d929d32..6f1efbe6c90 100644 --- a/ext/hash/tests/xxhash_secret.phpt +++ b/ext/hash/tests/xxhash_secret.phpt @@ -3,6 +3,13 @@ Hash: xxHash secret --FILE-- getMessage()); } + try { + $ctx = hash_init($a, options: ["secret" => new StringableThrowingClass()]); + } catch (Throwable $e) { + var_dump($e->getMessage()); + } + try { $ctx = hash_init($a, options: ["secret" => str_repeat('a', 17)]); } catch (Throwable $e) { @@ -35,8 +48,10 @@ foreach (["xxh3", "xxh128"] as $a) { ?> --EXPECT-- string(67) "xxh3: Only one of seed or secret is to be passed for initialization" +string(23) "exception in __toString" string(57) "xxh3: Secret length must be >= 136 bytes, 17 bytes passed" 8028aa834c03557a == 8028aa834c03557a == true string(69) "xxh128: Only one of seed or secret is to be passed for initialization" +string(23) "exception in __toString" string(59) "xxh128: Secret length must be >= 136 bytes, 17 bytes passed" 54279097795e7218093a05d4d781cbb9 == 54279097795e7218093a05d4d781cbb9 == true