Skip to content

Commit 321fe88

Browse files
committed
Add Z_PARAM_NUMBER and use it for some functions
1 parent 8a0965e commit 321fe88

File tree

10 files changed

+144
-99
lines changed

10 files changed

+144
-99
lines changed

Zend/zend_API.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,36 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest) /
381381
}
382382
/* }}} */
383383

384+
ZEND_API int ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest) /* {{{ */
385+
{
386+
if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
387+
return 0;
388+
}
389+
if (Z_TYPE_P(arg) == IS_STRING) {
390+
zend_string *str = Z_STR_P(arg);
391+
zend_long lval;
392+
double dval;
393+
zend_uchar type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &lval, &dval, -1);
394+
if (type == IS_LONG) {
395+
ZVAL_LONG(arg, lval);
396+
} else if (type == IS_DOUBLE) {
397+
ZVAL_DOUBLE(arg, dval);
398+
} else {
399+
return 0;
400+
}
401+
zend_string_release(str);
402+
} else if (Z_TYPE_P(arg) < IS_TRUE) {
403+
ZVAL_LONG(arg, 0);
404+
} else if (Z_TYPE_P(arg) == IS_TRUE) {
405+
ZVAL_LONG(arg, 1);
406+
} else {
407+
return 0;
408+
}
409+
*dest = arg;
410+
return 1;
411+
}
412+
/* }}} */
413+
384414
ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest) /* {{{ */
385415
{
386416
if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {

Zend/zend_API.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
10981098
_(Z_EXPECTED_RESOURCE, "resource") \
10991099
_(Z_EXPECTED_PATH, "a valid path") \
11001100
_(Z_EXPECTED_OBJECT, "object") \
1101-
_(Z_EXPECTED_DOUBLE, "float")
1101+
_(Z_EXPECTED_DOUBLE, "float") \
1102+
_(Z_EXPECTED_NUMBER, "int or float") \
11021103

11031104
#define Z_EXPECTED_TYPE_ENUM(id, str) id,
11041105
#define Z_EXPECTED_TYPE_STR(id, str) str,
@@ -1343,6 +1344,22 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e
13431344
#define Z_PARAM_LONG(dest) \
13441345
Z_PARAM_LONG_EX(dest, _dummy, 0, 0)
13451346

1347+
1348+
/* no old equivalent */
1349+
#define Z_PARAM_NUMBER_EX(dest, check_null) \
1350+
Z_PARAM_PROLOGUE(0, 0); \
1351+
if (UNEXPECTED(!zend_parse_arg_number(_arg, &dest, check_null))) { \
1352+
_expected_type = Z_EXPECTED_NUMBER; \
1353+
_error_code = ZPP_ERROR_WRONG_ARG; \
1354+
break; \
1355+
}
1356+
1357+
#define Z_PARAM_NUMBER_OR_NULL(dest) \
1358+
Z_PARAM_NUMBER_EX(dest, 1)
1359+
1360+
#define Z_PARAM_NUMBER(dest) \
1361+
Z_PARAM_NUMBER_EX(dest, 0)
1362+
13461363
/* old "o" */
13471364
#define Z_PARAM_OBJECT_EX2(dest, check_null, deref, separate) \
13481365
Z_PARAM_PROLOGUE(deref, separate); \
@@ -1503,6 +1520,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest);
15031520
ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest);
15041521
ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest);
15051522
ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest);
1523+
ZEND_API int ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest);
15061524

15071525
static zend_always_inline int zend_parse_arg_bool(zval *arg, zend_bool *dest, zend_bool *is_null, int check_null)
15081526
{
@@ -1554,6 +1572,18 @@ static zend_always_inline int zend_parse_arg_double(zval *arg, double *dest, zen
15541572
return 1;
15551573
}
15561574

1575+
static zend_always_inline int zend_parse_arg_number(zval *arg, zval **dest, int check_null)
1576+
{
1577+
if (EXPECTED(Z_TYPE_P(arg) == IS_LONG || Z_TYPE_P(arg) == IS_DOUBLE)) {
1578+
*dest = arg;
1579+
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
1580+
*dest = NULL;
1581+
} else {
1582+
return zend_parse_arg_number_slow(arg, dest);
1583+
}
1584+
return 1;
1585+
}
1586+
15571587
static zend_always_inline int zend_parse_arg_str(zval *arg, zend_string **dest, int check_null)
15581588
{
15591589
if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {

ext/opcache/Optimizer/zend_func_info.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,9 @@ static const func_info_t func_infos[] = {
314314
F0("password_verify", MAY_BE_FALSE | MAY_BE_TRUE),
315315
F1("convert_uuencode", MAY_BE_FALSE | MAY_BE_STRING),
316316
F1("convert_uudecode", MAY_BE_FALSE | MAY_BE_STRING),
317-
F0("abs", MAY_BE_FALSE | MAY_BE_LONG | MAY_BE_DOUBLE),
318-
F0("ceil", MAY_BE_FALSE | MAY_BE_DOUBLE),
319-
F0("floor", MAY_BE_FALSE | MAY_BE_DOUBLE),
317+
F0("abs", MAY_BE_LONG | MAY_BE_DOUBLE),
318+
F0("ceil", MAY_BE_DOUBLE),
319+
F0("floor", MAY_BE_DOUBLE),
320320
F0("round", MAY_BE_FALSE | MAY_BE_DOUBLE),
321321
F0("sin", MAY_BE_DOUBLE),
322322
F0("cos", MAY_BE_DOUBLE),

ext/standard/array.c

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,24 +2725,11 @@ PHP_FUNCTION(range)
27252725
Z_PARAM_ZVAL(zlow)
27262726
Z_PARAM_ZVAL(zhigh)
27272727
Z_PARAM_OPTIONAL
2728-
Z_PARAM_ZVAL(zstep)
2729-
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
2728+
Z_PARAM_NUMBER(zstep)
2729+
ZEND_PARSE_PARAMETERS_END();
27302730

27312731
if (zstep) {
2732-
if (Z_TYPE_P(zstep) == IS_DOUBLE) {
2733-
is_step_double = 1;
2734-
} else if (Z_TYPE_P(zstep) == IS_STRING) {
2735-
int type = is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0);
2736-
if (type == IS_DOUBLE) {
2737-
is_step_double = 1;
2738-
}
2739-
if (type == 0) {
2740-
/* bad number */
2741-
php_error_docref(NULL, E_WARNING, "Invalid range string - must be numeric");
2742-
RETURN_FALSE;
2743-
}
2744-
}
2745-
2732+
is_step_double = Z_TYPE_P(zstep) == IS_DOUBLE;
27462733
step = zval_get_double(zstep);
27472734

27482735
/* We only want positive step values. */

ext/standard/math.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -283,18 +283,16 @@ static double php_expm1(double x)
283283
}
284284
/* }}}*/
285285

286-
/* {{{ proto int|float|false abs(int number)
286+
/* {{{ proto int|float abs(int number)
287287
Return the absolute value of the number */
288288
PHP_FUNCTION(abs)
289289
{
290290
zval *value;
291291

292292
ZEND_PARSE_PARAMETERS_START(1, 1)
293-
Z_PARAM_ZVAL(value)
293+
Z_PARAM_NUMBER(value)
294294
ZEND_PARSE_PARAMETERS_END();
295295

296-
convert_scalar_to_number_ex(value);
297-
298296
if (Z_TYPE_P(value) == IS_DOUBLE) {
299297
RETURN_DOUBLE(fabs(Z_DVAL_P(value)));
300298
} else if (Z_TYPE_P(value) == IS_LONG) {
@@ -303,50 +301,49 @@ PHP_FUNCTION(abs)
303301
} else {
304302
RETURN_LONG(Z_LVAL_P(value) < 0 ? -Z_LVAL_P(value) : Z_LVAL_P(value));
305303
}
304+
} else {
305+
ZEND_ASSERT(0 && "Unexpected type");
306306
}
307-
RETURN_FALSE;
308307
}
309308
/* }}} */
310309

311-
/* {{{ proto float|false ceil(float number)
310+
/* {{{ proto float ceil(float number)
312311
Returns the next highest integer value of the number */
313312
PHP_FUNCTION(ceil)
314313
{
315314
zval *value;
316315

317316
ZEND_PARSE_PARAMETERS_START(1, 1)
318-
Z_PARAM_ZVAL(value)
317+
Z_PARAM_NUMBER(value)
319318
ZEND_PARSE_PARAMETERS_END();
320319

321-
convert_scalar_to_number_ex(value);
322-
323320
if (Z_TYPE_P(value) == IS_DOUBLE) {
324321
RETURN_DOUBLE(ceil(Z_DVAL_P(value)));
325322
} else if (Z_TYPE_P(value) == IS_LONG) {
326323
RETURN_DOUBLE(zval_get_double(value));
324+
} else {
325+
ZEND_ASSERT(0 && "Unexpected type");
327326
}
328-
RETURN_FALSE;
329327
}
330328
/* }}} */
331329

332-
/* {{{ proto float|false floor(float number)
330+
/* {{{ proto float floor(float number)
333331
Returns the next lowest integer value from the number */
334332
PHP_FUNCTION(floor)
335333
{
336334
zval *value;
337335

338336
ZEND_PARSE_PARAMETERS_START(1, 1)
339-
Z_PARAM_ZVAL(value)
337+
Z_PARAM_NUMBER(value)
340338
ZEND_PARSE_PARAMETERS_END();
341339

342-
convert_scalar_to_number_ex(value);
343-
344340
if (Z_TYPE_P(value) == IS_DOUBLE) {
345341
RETURN_DOUBLE(floor(Z_DVAL_P(value)));
346342
} else if (Z_TYPE_P(value) == IS_LONG) {
347343
RETURN_DOUBLE(zval_get_double(value));
344+
} else {
345+
ZEND_ASSERT(0 && "Unexpected type");
348346
}
349-
RETURN_FALSE;
350347
}
351348
/* }}} */
352349

ext/standard/tests/array/range_errors.phpt

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,23 @@ var_dump( range(7.0, 1.0, 6.5) );
2323

2424
echo "\n-- Testing other conditions --";
2525
var_dump( range(-1, -2, 2) );
26-
var_dump( range("a", "j", "z") );
26+
try {
27+
var_dump( range("a", "j", "z") );
28+
} catch (TypeError $e) {
29+
echo $e->getMessage(), "\n";
30+
}
2731
var_dump( range(0, 1, "140962482048819216326.24") );
2832
var_dump( range(0, 1, "140962482048819216326.24.") );
2933

3034
echo "\n-- Testing Invalid steps --";
3135
$step_arr = array( "string", NULL, FALSE, "", "\0" );
3236

3337
foreach( $step_arr as $step ) {
34-
var_dump( range( 1, 5, $step ) );
38+
try {
39+
var_dump( range( 1, 5, $step ) );
40+
} catch (TypeError $e) {
41+
echo $e->getMessage(), "\n";
42+
}
3543
}
3644

3745
echo "Done\n";
@@ -67,29 +75,23 @@ bool(false)
6775
-- Testing other conditions --
6876
Warning: range(): step exceeds the specified range in %s on line %d
6977
bool(false)
70-
71-
Warning: range(): Invalid range string - must be numeric in %s on line %d
72-
bool(false)
78+
range() expects parameter 3 to be int or float, string given
7379

7480
Warning: range(): step exceeds the specified range in %s on line %d
7581
bool(false)
7682

77-
Warning: range(): Invalid range string - must be numeric in %s on line %d
78-
bool(false)
79-
80-
-- Testing Invalid steps --
81-
Warning: range(): Invalid range string - must be numeric in %s on line %d
82-
bool(false)
83+
Notice: A non well formed numeric value encountered in %s on line %d
8384

8485
Warning: range(): step exceeds the specified range in %s on line %d
8586
bool(false)
8687

87-
Warning: range(): step exceeds the specified range in %s on line %d
88-
bool(false)
88+
-- Testing Invalid steps --range() expects parameter 3 to be int or float, string given
8989

90-
Warning: range(): Invalid range string - must be numeric in %s on line %d
90+
Warning: range(): step exceeds the specified range in %s on line %d
9191
bool(false)
9292

93-
Warning: range(): Invalid range string - must be numeric in %s on line %d
93+
Warning: range(): step exceeds the specified range in %s on line %d
9494
bool(false)
95+
range() expects parameter 3 to be int or float, string given
96+
range() expects parameter 3 to be int or float, string given
9597
Done

ext/standard/tests/array/range_variation.phpt

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ for( $i = 0; $i < count($low_arr); $i++) {
1818

1919
echo "\n*** Possible variatins with steps ***\n";
2020
var_dump( range( 1, 5, TRUE ) );
21-
var_dump( range( 1, 5, array(1, 2) ) );
21+
try {
22+
var_dump( range( 1, 5, array(1, 2) ) );
23+
} catch (TypeError $e) {
24+
echo $e->getMessage(), "\n";
25+
}
2226

2327
echo "Done\n";
2428
?>
@@ -611,16 +615,5 @@ array(5) {
611615
[4]=>
612616
int(5)
613617
}
614-
array(5) {
615-
[0]=>
616-
int(1)
617-
[1]=>
618-
int(2)
619-
[2]=>
620-
int(3)
621-
[3]=>
622-
int(4)
623-
[4]=>
624-
int(5)
625-
}
618+
range() expects parameter 3 to be int or float, array given
626619
Done

ext/standard/tests/math/abs_variation.phpt

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,18 @@ $inputs = array(
7373
$iterator = 1;
7474
foreach($inputs as $input) {
7575
echo "\n-- Iteration $iterator --\n";
76-
var_dump(abs($input) );
76+
try {
77+
var_dump(abs($input));
78+
} catch (TypeError $e) {
79+
echo $e->getMessage(), "\n";
80+
}
7781
$iterator++;
7882
};
7983

8084
fclose($fp);
8185
?>
8286
===Done===
83-
--EXPECTF--
87+
--EXPECT--
8488
*** Testing abs() : usage variations ***
8589

8690
-- Iteration 1 --
@@ -102,27 +106,25 @@ int(1)
102106
int(0)
103107

104108
-- Iteration 7 --
105-
int(0)
109+
abs() expects parameter 1 to be int or float, string given
106110

107111
-- Iteration 8 --
108-
int(0)
112+
abs() expects parameter 1 to be int or float, string given
109113

110114
-- Iteration 9 --
111-
bool(false)
115+
abs() expects parameter 1 to be int or float, array given
112116

113117
-- Iteration 10 --
114-
int(0)
118+
abs() expects parameter 1 to be int or float, string given
115119

116120
-- Iteration 11 --
117-
int(0)
121+
abs() expects parameter 1 to be int or float, string given
118122

119123
-- Iteration 12 --
120-
int(0)
124+
abs() expects parameter 1 to be int or float, string given
121125

122126
-- Iteration 13 --
123-
124-
Notice: Object of class classA could not be converted to number in %s on line %d
125-
int(1)
127+
abs() expects parameter 1 to be int or float, object given
126128

127129
-- Iteration 14 --
128130
int(0)
@@ -131,5 +133,5 @@ int(0)
131133
int(0)
132134

133135
-- Iteration 16 --
134-
int(%d)
136+
abs() expects parameter 1 to be int or float, resource given
135137
===Done===

0 commit comments

Comments
 (0)