Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions ext/curl/curl_escape.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public function execute(Frame $frame): void
if (null === $frame->returnVar) {
return;
}
$value = VmString::coerceStringBuiltinArg(
// Z_PARAM_STR — null TypeError on 8.4 forward profile (#20695, ext/curl/interface.c)
$value = VmString::coerceZparamStrBuiltinArg(
$frame->calledArgs[1],
'curl_escape',
1,
Expand All @@ -56,7 +57,15 @@ public function call(Context $context, JITVariable ...$args): Value
}
// Handle is required for php-src-strict arity/type; encoding matches curl_easy_escape
// unreserved set (rawurlencode) and does not depend on handle state.
$str = JitStringBuiltinArg::lower($context, $args[1], 'curl_escape', 1, 'string');
// Z_PARAM_STR — null TypeError on 8.4 forward profile (#20695).
// Early-return like urlencode: after TypeError+abort, do not link rawurlencode (#20695 AOT).
if (
(JITVariable::TYPE_NULL === $args[1]->type || ($args[1]->isNullConstant ?? false))
&& ($context->callerStrictTypes || JitStringBuiltinArg::requiresZparamStrStrictNullOnForwardProfile())
) {
return JitStringBuiltinArg::lowerZparamStr($context, $args[1], 'curl_escape', 1, 'string');
}
$str = JitStringBuiltinArg::lowerZparamStr($context, $args[1], 'curl_escape', 1, 'string');

return JitUrlencode::rawurlencode($context, $str);
}
Expand Down
13 changes: 11 additions & 2 deletions ext/curl/curl_unescape.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public function execute(Frame $frame): void
if (null === $frame->returnVar) {
return;
}
$value = VmString::coerceStringBuiltinArg(
// Z_PARAM_STR — null TypeError on 8.4 forward profile (#20695, ext/curl/interface.c)
$value = VmString::coerceZparamStrBuiltinArg(
$frame->calledArgs[1],
'curl_unescape',
1,
Expand All @@ -54,7 +55,15 @@ public function call(Context $context, JITVariable ...$args): Value
\count($args)
));
}
$str = JitStringBuiltinArg::lower($context, $args[1], 'curl_unescape', 1, 'string');
// Z_PARAM_STR — null TypeError on 8.4 forward profile (#20695).
// Early-return like urlencode: after TypeError+abort, do not link rawurldecode (#20695 AOT).
if (
(JITVariable::TYPE_NULL === $args[1]->type || ($args[1]->isNullConstant ?? false))
&& ($context->callerStrictTypes || JitStringBuiltinArg::requiresZparamStrStrictNullOnForwardProfile())
) {
return JitStringBuiltinArg::lowerZparamStr($context, $args[1], 'curl_unescape', 1, 'string');
}
$str = JitStringBuiltinArg::lowerZparamStr($context, $args[1], 'curl_unescape', 1, 'string');

return JitUrlencode::rawurldecode($context, $str);
}
Expand Down
15 changes: 15 additions & 0 deletions test/compliance/cases/stdlib/curl_escape_null.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
stdlib curl_escape()/curl_unescape(null) — coerce under 8.2 profile (#20695, ext/curl/interface.c)
--ENV--
PHP_COMPILER_PROFILE=8.2
--FILE--
<?php
$ch = curl_init();
var_export(curl_escape($ch, null));
echo "\n";
var_export(curl_unescape($ch, null));
echo "\n";
?>
--EXPECT--
''
''
23 changes: 23 additions & 0 deletions test/compliance/cases/stdlib/curl_escape_null_forward84.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
stdlib curl_escape()/curl_unescape(null) — TypeError on 8.4 forward profile (#20695, ext/curl/interface.c)
--ENV--
PHP_COMPILER_PROFILE=8.4
--FILE--
<?php
$ch = curl_init();
try {
curl_escape($ch, null);
echo "escape_uncaught\n";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
try {
curl_unescape($ch, null);
echo "unescape_uncaught\n";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
curl_escape(): Argument #2 ($string) must be of type string, null given
curl_unescape(): Argument #2 ($string) must be of type string, null given
24 changes: 24 additions & 0 deletions test/compliance/cases/stdlib/curl_escape_null_forward84_jit.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
--TEST--
stdlib curl_escape()/curl_unescape(null) — TypeError on 8.4 forward profile JIT (#20695, ext/curl/interface.c)
--ENV--
PHP_COMPILER_PROFILE=8.4
--JIT--
--FILE--
<?php
$ch = curl_init();
try {
curl_escape($ch, null);
echo "escape_uncaught\n";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
try {
curl_unescape($ch, null);
echo "unescape_uncaught\n";
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
curl_escape(): Argument #2 ($string) must be of type string, null given
curl_unescape(): Argument #2 ($string) must be of type string, null given
12 changes: 12 additions & 0 deletions test/fixtures/aot/cases/curl_escape_null_forward84.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
AOT: curl_escape(null) — TypeError on 8.4 forward profile (#20695, ext/curl/interface.c)
--ENV--
PHP_COMPILER_PROFILE=8.4
--FILE--
<?php
// JIT/AOT encode path does not require a live CurlHandle (curl_init is VM-only; #6322).
$h = 0;
curl_escape($h, null);
--EXPECT--
--EXPECT_EXIT--
255