Skip to content
Draft
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
17 changes: 10 additions & 7 deletions Zend/Optimizer/zend_inference.c
Original file line number Diff line number Diff line change
Expand Up @@ -4926,6 +4926,9 @@ ZEND_API zend_result zend_ssa_inference(zend_arena **arena, const zend_op_array
}
/* }}} */

/* Key types whose conversion to an array offset may emit a diagnostic */
#define MAY_BE_THROWING_KEY (MAY_BE_NULL|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)

ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, const zend_ssa *ssa, uint32_t t1, uint32_t t2)
{
if (opline->op1_type == IS_CV) {
Expand Down Expand Up @@ -5208,7 +5211,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
return 1;
}
return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_TRUE|MAY_BE_FALSE|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)) || opline->op2_type == IS_UNUSED ||
(t2 & (MAY_BE_UNDEF|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
(t2 & (MAY_BE_UNDEF|MAY_BE_THROWING_KEY));
case ZEND_ASSIGN_OBJ:
if (t1 & (MAY_BE_ANY-MAY_BE_OBJECT)) {
return 1;
Expand Down Expand Up @@ -5260,9 +5263,9 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
case ZEND_ROPE_END:
return t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT);
case ZEND_INIT_ARRAY:
return (opline->op2_type != IS_UNUSED) && (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
return (opline->op2_type != IS_UNUSED) && (t2 & MAY_BE_THROWING_KEY);
case ZEND_ADD_ARRAY_ELEMENT:
return (opline->op2_type == IS_UNUSED) || (t2 & (MAY_BE_NULL|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
return (opline->op2_type == IS_UNUSED) || (t2 & MAY_BE_THROWING_KEY);
case ZEND_STRLEN:
return (t1 & MAY_BE_ANY) != MAY_BE_STRING;
case ZEND_COUNT:
Expand All @@ -5289,9 +5292,9 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
case ZEND_FETCH_IS:
return (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
return (t1 & MAY_BE_OBJECT) || (t2 & (MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT));
return (t1 & MAY_BE_OBJECT) || (t2 & MAY_BE_THROWING_KEY);
case ZEND_FETCH_DIM_IS:
return (t1 & MAY_BE_OBJECT) || (t2 & (MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
return (t1 & MAY_BE_OBJECT) || (t2 & MAY_BE_THROWING_KEY);
case ZEND_CAST:
switch (opline->extended_value) {
case IS_LONG:
Expand All @@ -5313,7 +5316,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
if ((t2 & MAY_BE_ANY) != MAY_BE_ARRAY) {
return 1;
}
if ((t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
if (t1 & MAY_BE_THROWING_KEY) {
return 1;
}
return 0;
Expand All @@ -5338,7 +5341,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
if (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
return 1;
}
if (t2 & (MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_OBJECT)) {
if (t2 & MAY_BE_THROWING_KEY) {
return 1;
}
if (opline->op2_type == IS_UNUSED) {
Expand Down
27 changes: 27 additions & 0 deletions ext/opcache/tests/jit/add_array_element_float_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
JIT ADD_ARRAY_ELEMENT: float key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
var_dump([0, $k => 1]);
}

try {
test(1.5);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Implicit conversion from float 1.5 to int loses precision
27 changes: 27 additions & 0 deletions ext/opcache/tests/jit/array_key_exists_float_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
JIT ARRAY_KEY_EXISTS: float key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
var_dump(array_key_exists($k, []));
}

try {
test(1.5);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Implicit conversion from float 1.5 to int loses precision
27 changes: 27 additions & 0 deletions ext/opcache/tests/jit/array_key_exists_null_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
JIT ARRAY_KEY_EXISTS: null key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(null $k) {
var_dump(array_key_exists($k, []));
}

try {
test(null);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead
28 changes: 28 additions & 0 deletions ext/opcache/tests/jit/assign_dim_float_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
JIT ASSIGN_DIM: float key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
$a = [];
var_dump($a[$k] = 1);
}

try {
test(1.5);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Implicit conversion from float 1.5 to int loses precision
28 changes: 28 additions & 0 deletions ext/opcache/tests/jit/assign_dim_null_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
JIT ASSIGN_DIM: null key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(null $k) {
$a = [];
var_dump($a[$k] = 1);
}

try {
test(null);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Using null as an array offset is deprecated, use an empty string instead
37 changes: 37 additions & 0 deletions ext/opcache/tests/jit/fetch_dim_w_float_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
JIT FETCH_DIM_W: float key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

class C {
function __destruct() {
echo "destruct\n";
}
}

function g($x, &$y) {}

function test(float $k) {
$c = new C;
g($c, $a[$k]);
}

try {
test(1.5);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
destruct
Exception: Implicit conversion from float 1.5 to int loses precision
37 changes: 37 additions & 0 deletions ext/opcache/tests/jit/fetch_dim_w_null_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
JIT FETCH_DIM_W: null key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

class C {
function __destruct() {
echo "destruct\n";
}
}

function g($x, &$y) {}

function test(null $k) {
$c = new C;
g($c, $a[$k]);
}

try {
test(null);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
destruct
Exception: Using null as an array offset is deprecated, use an empty string instead
27 changes: 27 additions & 0 deletions ext/opcache/tests/jit/init_array_float_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
JIT INIT_ARRAY: float key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
var_dump([$k => 1]);
}

try {
test(1.5);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Implicit conversion from float 1.5 to int loses precision
27 changes: 27 additions & 0 deletions ext/opcache/tests/jit/init_array_null_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
JIT INIT_ARRAY: null key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(null $k) {
var_dump([$k => 1]);
}

try {
test(null);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Using null as an array offset is deprecated, use an empty string instead
28 changes: 28 additions & 0 deletions ext/opcache/tests/jit/isset_isempty_dim_obj_null_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--TEST--
JIT ISSET_ISEMPTY_DIM_OBJ: null key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(null $k) {
$a = [];
var_dump(isset($a[$k]));
}

try {
test(null);
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECT--
Exception: Using null as an array offset is deprecated, use an empty string instead
29 changes: 29 additions & 0 deletions ext/opcache/tests/jit/isset_isempty_dim_obj_resource_key.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--TEST--
JIT ISSET_ISEMPTY_DIM_OBJ: resource key conversion may throw
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.jit=function
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test() {
$k = fopen("php://memory", "r");
$a = [];
var_dump(isset($a[$k]));
}

try {
test();
} catch (Exception $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}
?>
--EXPECTF--
Exception: Resource ID#%d used as offset, casting to integer (%d)
Loading
Loading