Skip to content

Commit 38017f7

Browse files
committed
JIT: Implement FFI Array Bounds Checks
1 parent 1a21480 commit 38017f7

File tree

1 file changed

+62
-6
lines changed

1 file changed

+62
-6
lines changed

ext/opcache/jit/zend_jit_ir.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12367,6 +12367,56 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit,
1236712367
}
1236812368

1236912369
#ifdef HAVE_FFI
12370+
static int zend_jit_ffi_abc(zend_jit_ctx *jit,
12371+
const zend_op *opline,
12372+
zend_ffi_type *ffi_type,
12373+
uint32_t op2_info,
12374+
zend_jit_addr op2_addr,
12375+
zend_ssa_range *op2_range)
12376+
{
12377+
int32_t exit_point;
12378+
const void *exit_addr;
12379+
12380+
ZEND_ASSERT(op2_info == MAY_BE_LONG);
12381+
if (ffi_type->kind == ZEND_FFI_TYPE_ARRAY
12382+
&& !(ffi_type->attr & (ZEND_FFI_ATTR_VLA|ZEND_FFI_ATTR_INCOMPLETE_ARRAY))) {
12383+
if (Z_MODE(op2_addr) == IS_CONST_ZVAL) {
12384+
zval *zv = Z_ZV(op2_addr);
12385+
ZEND_ASSERT(Z_TYPE_P(zv) == IS_LONG);
12386+
if (Z_LVAL_P(zv) < 0 || Z_LVAL_P(zv) >= ffi_type->array.length) {
12387+
/* Always out of range */
12388+
exit_point = zend_jit_trace_get_exit_point(opline, 0);
12389+
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
12390+
if (!exit_addr) {
12391+
return 0;
12392+
}
12393+
jit_SIDE_EXIT(jit, ir_CONST_ADDR(exit_addr));
12394+
}
12395+
} else if (!op2_range || op2_range->min < 0 || op2_range->max >= ffi_type->array.length) {
12396+
if (op2_range->max < 0 || op2_range->min >= ffi_type->array.length) {
12397+
/* Always out of range */
12398+
exit_point = zend_jit_trace_get_exit_point(opline, 0);
12399+
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
12400+
if (!exit_addr) {
12401+
return 0;
12402+
}
12403+
jit_SIDE_EXIT(jit, ir_CONST_ADDR(exit_addr));
12404+
} else {
12405+
/* Array Bounds Check */
12406+
exit_point = zend_jit_trace_get_exit_point(opline, 0);
12407+
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
12408+
if (!exit_addr) {
12409+
return 0;
12410+
}
12411+
ir_GUARD(ir_ULT(jit_Z_LVAL(jit, op2_addr), ir_CONST_LONG(ffi_type->array.length)),
12412+
ir_CONST_ADDR(exit_addr));
12413+
}
12414+
}
12415+
}
12416+
12417+
return 1;
12418+
}
12419+
1237012420
static int zend_jit_ffi_fetch_dim_read(zend_jit_ctx *jit,
1237112421
const zend_op *opline,
1237212422
zend_ssa *ssa,
@@ -12386,9 +12436,11 @@ static int zend_jit_ffi_fetch_dim_read(zend_jit_ctx *jit,
1238612436

1238712437
// TODO: ce guard ???
1238812438
// TODO: ffi type guard ???
12389-
if (op1_ffi_type->kind == ZEND_FFI_TYPE_ARRAY) {
12390-
// TODO: array bounds check ???
12439+
12440+
if (!zend_jit_ffi_abc(jit, opline, op1_ffi_type, op2_info, op2_addr, op2_range)) {
12441+
return 0;
1239112442
}
12443+
1239212444
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
1239312445
ir_ref cdata_ref = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1239412446
ir_ref ptr = ir_ADD_A(cdata_ref, ir_MUL_L(jit_Z_LVAL(jit, op2_addr), ir_CONST_LONG(el_type->size)));
@@ -13122,9 +13174,11 @@ static int zend_jit_ffi_assign_dim(zend_jit_ctx *jit,
1312213174

1312313175
// TODO: ce guard ???
1312413176
// TODO: ffi type guard ???
13125-
if (op1_ffi_type->kind == ZEND_FFI_TYPE_ARRAY) {
13126-
// TODO: array bounds check ???
13177+
13178+
if (!zend_jit_ffi_abc(jit, opline, op1_ffi_type, op2_info, op2_addr, op2_range)) {
13179+
return 0;
1312713180
}
13181+
1312813182
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
1312913183
ir_ref cdata_ref = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1313013184
ir_ref ptr = ir_ADD_A(cdata_ref, ir_MUL_L(jit_Z_LVAL(jit, op2_addr), ir_CONST_LONG(el_type->size)));
@@ -13437,9 +13491,11 @@ static int zend_jit_ffi_assign_dim_op(zend_jit_ctx *jit,
1343713491

1343813492
// TODO: ce guard ???
1343913493
// TODO: ffi type guard ???
13440-
if (op1_ffi_type->kind == ZEND_FFI_TYPE_ARRAY) {
13441-
// TODO: array bounds check ???
13494+
13495+
if (!zend_jit_ffi_abc(jit, opline, op1_ffi_type, op2_info, op2_addr, op2_range)) {
13496+
return 0;
1344213497
}
13498+
1344313499
ir_ref obj_ref = jit_Z_PTR(jit, op1_addr);
1344413500
ir_ref cdata_ref = ir_LOAD_A(ir_ADD_OFFSET(obj_ref, offsetof(zend_ffi_cdata, ptr)));
1344513501
ir_ref ptr = ir_ADD_A(cdata_ref, ir_MUL_L(jit_Z_LVAL(jit, op2_addr), ir_CONST_LONG(el_type->size)));

0 commit comments

Comments
 (0)