Skip to content

Commit 7de1b30

Browse files
committed
Refactor SplFixedArray offset handling
- Implement warning for resource type - Relax restictions on a string offset to better match the normal conversion to int semantics as the offset is always an integer (similar to string offsets) - NULL is still not support as an offset - Throw a proper TypeError instead of a RuntimeException
1 parent 00a2cd1 commit 7de1b30

File tree

3 files changed

+38
-35
lines changed

3 files changed

+38
-35
lines changed

ext/spl/spl_fixedarray.c

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,13 @@ static zend_object *spl_fixedarray_object_clone(zend_object *old_object)
311311

312312
static zend_long spl_offset_convert_to_long(zval *offset) /* {{{ */
313313
{
314-
zend_ulong idx;
314+
zend_long index;
315315

316316
try_again:
317317
switch (Z_TYPE_P(offset)) {
318318
case IS_STRING:
319-
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), idx)) {
320-
return idx;
319+
if (IS_LONG == is_numeric_str_function(Z_STR_P(offset), &index, NULL)) {
320+
return index;
321321
}
322322
break;
323323
case IS_DOUBLE:
@@ -332,9 +332,13 @@ static zend_long spl_offset_convert_to_long(zval *offset) /* {{{ */
332332
offset = Z_REFVAL_P(offset);
333333
goto try_again;
334334
case IS_RESOURCE:
335+
zend_error(E_WARNING, "Resource ID#%d used as offset, casting to integer (%d)",
336+
Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
335337
return Z_RES_HANDLE_P(offset);
336-
}
337-
return -1;
338+
}
339+
340+
zend_type_error("Illegal offset type");
341+
return 0;
338342
}
339343

340344
static zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *intern, zval *offset)
@@ -348,13 +352,13 @@ static zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *
348352
return NULL;
349353
}
350354

351-
if (Z_TYPE_P(offset) != IS_LONG) {
352-
index = spl_offset_convert_to_long(offset);
353-
} else {
354-
index = Z_LVAL_P(offset);
355+
index = spl_offset_convert_to_long(offset);
356+
if (EG(exception)) {
357+
return NULL;
355358
}
356359

357360
if (index < 0 || index >= intern->array.size) {
361+
// TODO Change error message and use OutOfBound SPL Exception?
358362
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
359363
return NULL;
360364
} else {
@@ -400,13 +404,13 @@ static void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object *
400404
return;
401405
}
402406

403-
if (Z_TYPE_P(offset) != IS_LONG) {
404-
index = spl_offset_convert_to_long(offset);
405-
} else {
406-
index = Z_LVAL_P(offset);
407+
index = spl_offset_convert_to_long(offset);
408+
if (EG(exception)) {
409+
return;
407410
}
408411

409412
if (index < 0 || index >= intern->array.size) {
413+
// TODO Change error message and use OutOfBound SPL Exception?
410414
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
411415
return;
412416
} else {
@@ -438,13 +442,13 @@ static void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object *
438442
{
439443
zend_long index;
440444

441-
if (Z_TYPE_P(offset) != IS_LONG) {
442-
index = spl_offset_convert_to_long(offset);
443-
} else {
444-
index = Z_LVAL_P(offset);
445+
index = spl_offset_convert_to_long(offset);
446+
if (EG(exception)) {
447+
return;
445448
}
446449

447450
if (index < 0 || index >= intern->array.size) {
451+
// TODO Change error message and use OutOfBound SPL Exception?
448452
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
449453
return;
450454
} else {
@@ -472,10 +476,9 @@ static int spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *int
472476
zend_long index;
473477
int retval;
474478

475-
if (Z_TYPE_P(offset) != IS_LONG) {
476-
index = spl_offset_convert_to_long(offset);
477-
} else {
478-
index = Z_LVAL_P(offset);
479+
index = spl_offset_convert_to_long(offset);
480+
if (EG(exception)) {
481+
return 0;
479482
}
480483

481484
if (index < 0 || index >= intern->array.size) {

ext/spl/tests/fixedarray_001.phpt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ $a = new SplFixedArray(0);
77
try {
88
$a[0] = "value1";
99
} catch (RuntimeException $e) {
10-
echo "Exception: ".$e->getMessage()."\n";
10+
echo $e::class, ': ', $e->getMessage(), "\n";
1111
}
1212
try {
1313
var_dump($a["asdf"]);
14-
} catch (RuntimeException $e) {
15-
echo "Exception: ".$e->getMessage()."\n";
14+
} catch (\TypeError $e) {
15+
echo $e::class, ': ', $e->getMessage(), "\n";
1616
}
1717
try {
1818
unset($a[-1]);
1919
} catch (RuntimeException $e) {
20-
echo "Exception: ".$e->getMessage()."\n";
20+
echo $e::class, ': ', $e->getMessage(), "\n";
2121
}
2222
$a->setSize(10);
2323

@@ -45,9 +45,9 @@ $a[0] = "valueNew";
4545
var_dump($b[0]);
4646
?>
4747
--EXPECT--
48-
Exception: Index invalid or out of range
49-
Exception: Index invalid or out of range
50-
Exception: Index invalid or out of range
48+
RuntimeException: Index invalid or out of range
49+
TypeError: Illegal offset type
50+
RuntimeException: Index invalid or out of range
5151
string(6) "value0"
5252
string(6) "value2"
5353
string(6) "value3"

ext/spl/tests/fixedarray_002.phpt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@ $a = new A;
3434
try {
3535
$a[0] = "value1";
3636
} catch (RuntimeException $e) {
37-
echo "Exception: ".$e->getMessage()."\n";
37+
echo $e::class, ': ', $e->getMessage(), "\n";
3838
}
3939
try {
4040
var_dump($a["asdf"]);
41-
} catch (RuntimeException $e) {
42-
echo "Exception: ".$e->getMessage()."\n";
41+
} catch (\TypeError $e) {
42+
echo $e::class, ': ', $e->getMessage(), "\n";
4343
}
4444
try {
4545
unset($a[-1]);
4646
} catch (RuntimeException $e) {
47-
echo "Exception: ".$e->getMessage()."\n";
47+
echo $e::class, ': ', $e->getMessage(), "\n";
4848
}
4949
$a->setSize(10);
5050

@@ -69,11 +69,11 @@ var_dump(count($a), $a->getSize(), count($a) == $a->getSize());
6969
?>
7070
--EXPECT--
7171
A::offsetSet
72-
Exception: Index invalid or out of range
72+
RuntimeException: Index invalid or out of range
7373
A::offsetGet
74-
Exception: Index invalid or out of range
74+
TypeError: Illegal offset type
7575
A::offsetUnset
76-
Exception: Index invalid or out of range
76+
RuntimeException: Index invalid or out of range
7777
A::offsetSet
7878
A::offsetSet
7979
A::offsetSet

0 commit comments

Comments
 (0)