1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-19792: SCCP causes UAF for return value if both warning and exception are triggered

If an exception _and_ a warning (or deprecation) is emitted, then the
result is destroyed twice. Use an `else if` to prevent this.
This is tested via zend_test because the deprecation that triggered the
original reproducer may disappear in the future.

Closes GH-19793.
This commit is contained in:
Niels Dossche
2025-09-10 21:28:23 +02:00
parent d30ec1df2a
commit 2ad0b5cf05
6 changed files with 47 additions and 4 deletions

2
NEWS
View File

@@ -6,6 +6,8 @@ PHP NEWS
. Fixed bug GH-19765 (object_properties_load() bypasses readonly property
checks). (timwolla)
. Fixed hard_timeout with --enable-zend-max-execution-timers. (Appla)
. Fixed bug GH-19792 (SCCP causes UAF for return value if both warning and
exception are triggered). (nielsdos)
- Standard:
. Fixed bug GH-12265 (Cloning an object breaks serialization recursion).

View File

@@ -842,9 +842,7 @@ static inline zend_result ct_eval_func_call(
zval_ptr_dtor(result);
zend_clear_exception();
retval = FAILURE;
}
if (EG(capture_warnings_during_sccp) > 1) {
} else if (EG(capture_warnings_during_sccp) > 1) {
zval_ptr_dtor(result);
retval = FAILURE;
}

View File

@@ -0,0 +1,27 @@
--TEST--
GH-19792 (SCCP causes UAF for return value if both warning and exception are triggered)
--EXTENSIONS--
opcache
zend_test
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
--FILE--
<?php
function foo()
{
return \zend_test_gh19792();
}
try {
foo();
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECTF--
Warning: a warning in %s on line %d
an exception

View File

@@ -1528,3 +1528,12 @@ static PHP_FUNCTION(zend_test_gh18756)
zend_mm_gc(heap);
zend_mm_shutdown(heap, true, false);
}
static PHP_FUNCTION(zend_test_gh19792)
{
ZEND_PARSE_PARAMETERS_NONE();
RETVAL_STRING("this is a non-interned string");
zend_error(E_WARNING, "a warning");
zend_throw_error(NULL, "an exception");
}

View File

@@ -264,6 +264,9 @@ function zend_test_override_libxml_global_state(): void {}
function zend_test_log_err_debug(string $str): void {}
function zend_test_gh18756(): void {}
/** @compile-time-eval */
function zend_test_gh19792(): void {}
}
namespace ZendTestNS {

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 2f161861ab09b6b5b594dc2db7c2c9df49d76aa7 */
* Stub hash: fa769dbbf7ba1d10f0141fed6a45fc06a84cd94c */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
@@ -164,6 +164,8 @@ ZEND_END_ARG_INFO()
#define arginfo_zend_test_gh18756 arginfo_zend_test_void_return
#define arginfo_zend_test_gh19792 arginfo_zend_test_void_return
#define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled
#define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return
@@ -295,6 +297,7 @@ static ZEND_FUNCTION(zend_test_cast_fread);
static ZEND_FUNCTION(zend_test_is_zend_ptr);
static ZEND_FUNCTION(zend_test_log_err_debug);
static ZEND_FUNCTION(zend_test_gh18756);
static ZEND_FUNCTION(zend_test_gh19792);
static ZEND_FUNCTION(ZendTestNS2_namespaced_func);
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func);
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func);
@@ -376,6 +379,7 @@ static const zend_function_entry ext_functions[] = {
ZEND_FE(zend_test_is_zend_ptr, arginfo_zend_test_is_zend_ptr)
ZEND_FE(zend_test_log_err_debug, arginfo_zend_test_log_err_debug)
ZEND_FE(zend_test_gh18756, arginfo_zend_test_gh18756)
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(zend_test_gh19792, arginfo_zend_test_gh19792)
ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func)
ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func)
ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func)