Skip to content
Open
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_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 @@ -5205,7 +5208,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 @@ -5257,9 +5260,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_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 @@ -5286,9 +5289,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 @@ -5309,7 +5312,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 @@ -5334,7 +5337,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
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
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
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
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)
27 changes: 27 additions & 0 deletions ext/opcache/tests/opt/dce_018.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
DCE must not remove ASSIGN_DIM with a float key
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
$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
27 changes: 27 additions & 0 deletions ext/opcache/tests/opt/dce_019.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
DCE must not remove INIT_ARRAY with a float key
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
$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
27 changes: 27 additions & 0 deletions ext/opcache/tests/opt/dce_020.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
DCE must not remove ADD_ARRAY_ELEMENT with a float key
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
$a = [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/opt/dce_021.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--TEST--
DCE must not remove ARRAY_KEY_EXISTS with a float key
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.file_update_protection=0
--EXTENSIONS--
opcache
--FILE--
<?php
set_error_handler(function ($errno, $errstr) {
throw new Exception($errstr);
});

function test(float $k) {
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
29 changes: 29 additions & 0 deletions ext/opcache/tests/opt/dce_022.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
--TEST--
DCE must not remove ISSET_ISEMPTY_DIM_OBJ with a resource key
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
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 = [];
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