Skip to content

Commit e9e0627

Browse files
authored
Refactor SplFixedArray (#7168)
* Move spl_offset_convert_to_long() to spl_fixedarray.c It is only used there, which explains its weird offset semantics * Refactor SplFixedArray offset handling - Implement warning for resource type - Throw a proper TypeError instead of a RuntimeException * Use a proper Error to signal that [] cannot be used with SplFixedArray * Refactor SplFixedArray has_dimension helper * Drop some ZPP tests
1 parent ceb6fa6 commit e9e0627

15 files changed

+303
-171
lines changed

ext/spl/config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c, no,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
1+
PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c, no,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
22
PHP_INSTALL_HEADERS([ext/spl], [php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_dllist.h spl_heap.h spl_fixedarray.h])
33
PHP_ADD_EXTENSION_DEP(spl, pcre, true)
44
PHP_ADD_EXTENSION_DEP(spl, standard, true)

ext/spl/config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// vim:ft=javascript
22

3-
EXTENSION("spl", "php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c", false /*never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
3+
EXTENSION("spl", "php_spl.c spl_functions.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c", false /*never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
44
PHP_SPL="yes";
55
PHP_INSTALL_HEADERS("ext/spl", "php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_dllist.h spl_heap.h spl_fixedarray.h");

ext/spl/spl_engine.c

Lines changed: 0 additions & 59 deletions
This file was deleted.

ext/spl/spl_engine.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
#include "php_spl.h"
2222
#include "zend_interfaces.h"
2323

24-
PHPAPI zend_long spl_offset_convert_to_long(zval *offset);
25-
2624
static inline void spl_instantiate_arg_ex1(zend_class_entry *pce, zval *retval, zval *arg1)
2725
{
2826
object_init_ex(retval, pce);

ext/spl/spl_fixedarray.c

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -309,24 +309,56 @@ static zend_object *spl_fixedarray_object_clone(zend_object *old_object)
309309
return new_object;
310310
}
311311

312+
static zend_long spl_offset_convert_to_long(zval *offset) /* {{{ */
313+
{
314+
try_again:
315+
switch (Z_TYPE_P(offset)) {
316+
case IS_STRING: {
317+
zend_ulong index;
318+
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), index)) {
319+
return (zend_long) index;
320+
}
321+
break;
322+
}
323+
case IS_DOUBLE:
324+
return zend_dval_to_lval_safe(Z_DVAL_P(offset));
325+
case IS_LONG:
326+
return Z_LVAL_P(offset);
327+
case IS_FALSE:
328+
return 0;
329+
case IS_TRUE:
330+
return 1;
331+
case IS_REFERENCE:
332+
offset = Z_REFVAL_P(offset);
333+
goto try_again;
334+
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));
337+
return Z_RES_HANDLE_P(offset);
338+
}
339+
340+
zend_type_error("Illegal offset type");
341+
return 0;
342+
}
343+
312344
static zval *spl_fixedarray_object_read_dimension_helper(spl_fixedarray_object *intern, zval *offset)
313345
{
314346
zend_long index;
315347

316348
/* we have to return NULL on error here to avoid memleak because of
317349
* ZE duplicating uninitialized_zval_ptr */
318350
if (!offset) {
319-
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
351+
zend_throw_error(NULL, "[] operator not supported for SplFixedArray");
320352
return NULL;
321353
}
322354

323-
if (Z_TYPE_P(offset) != IS_LONG) {
324-
index = spl_offset_convert_to_long(offset);
325-
} else {
326-
index = Z_LVAL_P(offset);
355+
index = spl_offset_convert_to_long(offset);
356+
if (EG(exception)) {
357+
return NULL;
327358
}
328359

329360
if (index < 0 || index >= intern->array.size) {
361+
// TODO Change error message and use OutOfBound SPL Exception?
330362
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
331363
return NULL;
332364
} else {
@@ -368,17 +400,17 @@ static void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object *
368400

369401
if (!offset) {
370402
/* '$array[] = value' syntax is not supported */
371-
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
403+
zend_throw_error(NULL, "[] operator not supported for SplFixedArray");
372404
return;
373405
}
374406

375-
if (Z_TYPE_P(offset) != IS_LONG) {
376-
index = spl_offset_convert_to_long(offset);
377-
} else {
378-
index = Z_LVAL_P(offset);
407+
index = spl_offset_convert_to_long(offset);
408+
if (EG(exception)) {
409+
return;
379410
}
380411

381412
if (index < 0 || index >= intern->array.size) {
413+
// TODO Change error message and use OutOfBound SPL Exception?
382414
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
383415
return;
384416
} else {
@@ -410,13 +442,13 @@ static void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object *
410442
{
411443
zend_long index;
412444

413-
if (Z_TYPE_P(offset) != IS_LONG) {
414-
index = spl_offset_convert_to_long(offset);
415-
} else {
416-
index = Z_LVAL_P(offset);
445+
index = spl_offset_convert_to_long(offset);
446+
if (EG(exception)) {
447+
return;
417448
}
418449

419450
if (index < 0 || index >= intern->array.size) {
451+
// TODO Change error message and use OutOfBound SPL Exception?
420452
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
421453
return;
422454
} else {
@@ -439,28 +471,24 @@ static void spl_fixedarray_object_unset_dimension(zend_object *object, zval *off
439471
spl_fixedarray_object_unset_dimension_helper(intern, offset);
440472
}
441473

442-
static int spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *intern, zval *offset, int check_empty)
474+
static bool spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *intern, zval *offset, bool check_empty)
443475
{
444476
zend_long index;
445-
int retval;
446477

447-
if (Z_TYPE_P(offset) != IS_LONG) {
448-
index = spl_offset_convert_to_long(offset);
449-
} else {
450-
index = Z_LVAL_P(offset);
478+
index = spl_offset_convert_to_long(offset);
479+
if (EG(exception)) {
480+
return false;
451481
}
452482

453483
if (index < 0 || index >= intern->array.size) {
454-
retval = 0;
455-
} else {
456-
if (check_empty) {
457-
retval = zend_is_true(&intern->array.elements[index]);
458-
} else {
459-
retval = Z_TYPE(intern->array.elements[index]) != IS_NULL;
460-
}
484+
return false;
485+
}
486+
487+
if (check_empty) {
488+
return zend_is_true(&intern->array.elements[index]);
461489
}
462490

463-
return retval;
491+
return Z_TYPE(intern->array.elements[index]) != IS_NULL;
464492
}
465493

466494
static int spl_fixedarray_object_has_dimension(zend_object *object, zval *offset, int check_empty)

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)