Skip to content

Commit 1cdaaac

Browse files
committed
Use generic evalution mechanism for constant functions
1 parent 75bd92a commit 1cdaaac

File tree

1 file changed

+111
-131
lines changed

1 file changed

+111
-131
lines changed

ext/opcache/Optimizer/sccp.c

Lines changed: 111 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,11 @@ static inline void ct_eval_type_check(zval *result, uint32_t type, zval *op1) {
466466
* applications as well, of course). */
467467
static inline int ct_eval_func_call(
468468
zval *result, zend_string *name, uint32_t num_args, zval **args) {
469+
uint32_t i;
470+
zend_execute_data *execute_data;
471+
zend_function *func;
472+
int overflow;
473+
469474
if (zend_string_equals_literal(name, "chr")) {
470475
zend_long c;
471476
if (num_args != 1 || Z_TYPE_P(args[0]) != IS_LONG) {
@@ -475,177 +480,152 @@ static inline int ct_eval_func_call(
475480
c = Z_LVAL_P(args[0]) & 0xff;
476481
ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
477482
return SUCCESS;
478-
} else if (zend_string_equals_literal(name, "in_array")) {
479-
zval *val;
480-
if (num_args != 2 || Z_TYPE_P(args[1]) != IS_ARRAY) {
483+
} else if (zend_string_equals_literal(name, "count")) {
484+
if (num_args != 1 || Z_TYPE_P(args[0]) != IS_ARRAY) {
481485
return FAILURE;
482486
}
483487

484-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args[1]), val) {
485-
if (fast_equal_check_function(val, args[0])) {
486-
ZVAL_TRUE(result);
487-
return SUCCESS;
488-
}
489-
} ZEND_HASH_FOREACH_END();
490-
ZVAL_FALSE(result);
488+
ZVAL_LONG(result, zend_hash_num_elements(Z_ARRVAL_P(args[0])));
491489
return SUCCESS;
492-
} else if (zend_string_equals_literal(name, "strpos")) {
493-
const char *found;
494-
if (num_args != 2
495-
|| Z_TYPE_P(args[0]) != IS_STRING
496-
|| Z_TYPE_P(args[1]) != IS_STRING
497-
|| !Z_STRLEN_P(args[1])) {
490+
} else if (zend_string_equals_literal(name, "ini_get")) {
491+
zend_ini_entry *ini_entry;
492+
493+
if (num_args != 1 || Z_TYPE_P(args[0]) != IS_STRING) {
498494
return FAILURE;
499495
}
500496

501-
found = zend_memnstr(
502-
Z_STRVAL_P(args[0]), Z_STRVAL_P(args[1]), Z_STRLEN_P(args[1]),
503-
Z_STRVAL_P(args[0]) + Z_STRLEN_P(args[0]));
504-
if (found) {
505-
ZVAL_LONG(result, found - Z_STRVAL_P(args[0]));
506-
} else {
497+
ini_entry = zend_hash_find_ptr(EG(ini_directives), Z_STR_P(args[0]));
498+
if (!ini_entry) {
507499
ZVAL_FALSE(result);
500+
} else if (ini_entry->modifiable != ZEND_INI_SYSTEM) {
501+
return FAILURE;
502+
} else if (ini_entry->value) {
503+
ZVAL_STR_COPY(result, ini_entry->value);
504+
} else {
505+
ZVAL_EMPTY_STRING(result);
508506
}
509507
return SUCCESS;
510-
} else if (zend_string_equals_literal(name, "count")) {
511-
if (num_args != 1 || Z_TYPE_P(args[0]) != IS_ARRAY) {
508+
} else if (zend_string_equals_literal(name, "in_array")) {
509+
if (num_args != 2 || Z_TYPE_P(args[1]) != IS_ARRAY) {
512510
return FAILURE;
513511
}
514-
515-
ZVAL_LONG(result, zend_hash_num_elements(Z_ARRVAL_P(args[0])));
516-
return SUCCESS;
512+
/* pass */
513+
} else if (zend_string_equals_literal(name, "strpos")) {
514+
if (num_args != 2
515+
|| Z_TYPE_P(args[0]) != IS_STRING
516+
|| Z_TYPE_P(args[1]) != IS_STRING
517+
|| !Z_STRLEN_P(args[1])) {
518+
return FAILURE;
519+
}
520+
/* pass */
517521
} else if (zend_string_equals_literal(name, "array_key_exists")) {
518-
zval *value;
519522
if (num_args != 2 || Z_TYPE_P(args[1]) != IS_ARRAY ||
520523
(Z_TYPE_P(args[0]) != IS_LONG && Z_TYPE_P(args[0]) != IS_STRING
521524
&& Z_TYPE_P(args[0]) != IS_NULL)) {
522525
return FAILURE;
523526
}
524-
525-
if (fetch_array_elem(&value, args[1], args[0])) {
526-
return FAILURE;
527-
}
528-
ZVAL_BOOL(result, value != NULL);
529-
return SUCCESS;
527+
/* pass */
530528
} else if (zend_string_equals_literal(name, "trim")
531529
|| zend_string_equals_literal(name, "rtrim")
532530
|| zend_string_equals_literal(name, "ltrim")) {
533-
zend_string *str;
534-
int mode;
535531
if ((num_args < 1 || num_args > 2) || Z_TYPE_P(args[0]) != IS_STRING
536532
|| (num_args == 2 && Z_TYPE_P(args[1]) != IS_STRING)) {
537533
return FAILURE;
538534
}
539-
540-
mode = ZSTR_VAL(name)[0] == 'l' ? 1 : ZSTR_VAL(name)[0] == 'r' ? 2 : 3;
541-
if (num_args == 2) {
542-
str = php_trim(Z_STR_P(args[0]), Z_STRVAL_P(args[1]), Z_STRLEN_P(args[1]), mode);
543-
} else {
544-
str = php_trim(Z_STR_P(args[0]), NULL, 0, mode);
545-
}
546-
ZVAL_STR(result, str);
547-
return SUCCESS;
548-
} else if (zend_string_equals_literal(name, "ini_get")) {
549-
zend_ini_entry *ini_entry;
550-
551-
if (num_args != 1 || Z_TYPE_P(args[0]) != IS_STRING) {
535+
/* pass */
536+
} else if (zend_string_equals_literal(name, "array_keys")
537+
|| zend_string_equals_literal(name, "array_values")) {
538+
if (num_args != 1 || Z_TYPE_P(args[0]) != IS_ARRAY) {
552539
return FAILURE;
553540
}
541+
/* pass */
542+
} else if (zend_string_equals_literal(name, "array_flip")) {
543+
zval *entry;
554544

555-
ini_entry = zend_hash_find_ptr(EG(ini_directives), Z_STR_P(args[0]));
556-
if (!ini_entry) {
557-
ZVAL_FALSE(result);
558-
} else if (ini_entry->modifiable != ZEND_INI_SYSTEM) {
545+
if (num_args != 1 || Z_TYPE_P(args[0]) != IS_ARRAY) {
559546
return FAILURE;
560-
} else if (ini_entry->value) {
561-
ZVAL_STR_COPY(result, ini_entry->value);
562-
} else {
563-
ZVAL_EMPTY_STRING(result);
564547
}
565-
return SUCCESS;
566-
} else {
567-
uint32_t i;
568-
zend_execute_data *execute_data;
569-
zend_function *func;
570-
int overflow;
571-
572-
if ((zend_string_equals_literal(name, "array_keys")
573-
|| zend_string_equals_literal(name, "array_values")
574-
// TODO: array_flip may throw warnings if the array contains non-int/string values
575-
// || zend_string_equals_literal(name, "array_flip")
576-
) && num_args == 1
577-
&& Z_TYPE_P(args[0]) == IS_ARRAY) {
578-
/* pass */
579-
} else if (zend_string_equals_literal(name, "str_repeat")
580-
&& num_args == 2
581-
&& Z_TYPE_P(args[0]) == IS_STRING
582-
&& Z_TYPE_P(args[1]) == IS_LONG
583-
&& zend_safe_address(Z_STRLEN_P(args[0]), Z_LVAL_P(args[1]), 0, &overflow) < 64 * 1024
584-
&& !overflow) {
585-
/* pass */
586-
} else if ((zend_string_equals_literal(name, "array_merge")
587-
|| zend_string_equals_literal(name, "array_replace")
588-
|| zend_string_equals_literal(name, "array_merge_recursive")
589-
|| zend_string_equals_literal(name, "array_merge_recursive")
590-
|| zend_string_equals_literal(name, "array_diff")
591-
|| zend_string_equals_literal(name, "array_diff_assoc")
592-
|| zend_string_equals_literal(name, "array_diff_key"))
593-
&& num_args > 0) {
594-
for (i = 0; i < num_args; i++) {
595-
if (Z_TYPE_P(args[i]) != IS_ARRAY) {
596-
return FAILURE;
597-
}
598-
}
599-
/* pass */
600-
} else if (zend_string_equals_literal(name, "implode")
601-
&& ((num_args == 1 && Z_TYPE_P(args[0]) == IS_ARRAY)
602-
|| (num_args == 2 && Z_TYPE_P(args[0]) == IS_STRING && Z_TYPE_P(args[1]) == IS_ARRAY)
603-
|| (num_args == 2 && Z_TYPE_P(args[0]) == IS_ARRAY && Z_TYPE_P(args[1]) == IS_STRING))) {
604-
zval *entry;
605-
606-
if (Z_TYPE_P(args[0]) == IS_ARRAY) {
607-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args[0]), entry) {
608-
if (Z_TYPE_P(entry) > IS_STRING) {
609-
return FAILURE;
610-
}
611-
} ZEND_HASH_FOREACH_END();
612-
} else {
613-
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args[1]), entry) {
614-
if (Z_TYPE_P(entry) > IS_STRING) {
615-
return FAILURE;
616-
}
617-
} ZEND_HASH_FOREACH_END();
548+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args[0]), entry) {
549+
if (Z_TYPE_P(entry) != IS_LONG && Z_TYPE_P(entry) != IS_STRING) {
550+
return FAILURE;
618551
}
619-
/* pass */
620-
} else if (zend_string_equals_literal(name, "version_comapre")
621-
&& (num_args == 2 || (num_args == 3 && Z_TYPE_P(args[2]) == IS_STRING))
622-
&& Z_TYPE_P(args[0]) == IS_STRING
623-
&& Z_TYPE_P(args[1]) == IS_STRING) {
624-
/* pass */
625-
} else {
552+
} ZEND_HASH_FOREACH_END();
553+
/* pass */
554+
} else if (zend_string_equals_literal(name, "str_repeat")) {
555+
if (num_args != 2
556+
|| Z_TYPE_P(args[0]) != IS_STRING
557+
|| Z_TYPE_P(args[1]) != IS_LONG
558+
|| zend_safe_address(Z_STRLEN_P(args[0]), Z_LVAL_P(args[1]), 0, &overflow) > 64 * 1024
559+
|| overflow) {
626560
return FAILURE;
627561
}
562+
/* pass */
563+
} else if ((zend_string_equals_literal(name, "array_merge")
564+
|| zend_string_equals_literal(name, "array_replace")
565+
|| zend_string_equals_literal(name, "array_merge_recursive")
566+
|| zend_string_equals_literal(name, "array_merge_recursive")
567+
|| zend_string_equals_literal(name, "array_diff")
568+
|| zend_string_equals_literal(name, "array_diff_assoc")
569+
|| zend_string_equals_literal(name, "array_diff_key"))
570+
&& num_args > 0) {
571+
for (i = 0; i < num_args; i++) {
572+
if (Z_TYPE_P(args[i]) != IS_ARRAY) {
573+
return FAILURE;
574+
}
575+
}
576+
/* pass */
577+
} else if (zend_string_equals_literal(name, "implode")) {
578+
zval *entry;
628579

629-
func = zend_hash_find_ptr(CG(function_table), name);
630-
if (!func || func->type != ZEND_INTERNAL_FUNCTION) {
580+
if (!(num_args == 1 && Z_TYPE_P(args[0]) == IS_ARRAY)
581+
&& !(num_args == 2 && Z_TYPE_P(args[0]) == IS_STRING && Z_TYPE_P(args[1]) == IS_ARRAY)
582+
&& !(num_args == 2 && Z_TYPE_P(args[0]) == IS_ARRAY && Z_TYPE_P(args[1]) == IS_STRING)) {
631583
return FAILURE;
632584
}
633585

634-
execute_data = safe_emalloc(num_args, sizeof(zval), ZEND_CALL_FRAME_SLOT * sizeof(zval));
635-
memset(execute_data, 0, sizeof(zend_execute_data));
636-
EX(func) = func;
637-
EX_NUM_ARGS() = num_args;
638-
for (i = 0; i < num_args; i++) {
639-
ZVAL_COPY(EX_VAR_NUM(i), args[i]);
586+
if (Z_TYPE_P(args[0]) == IS_ARRAY) {
587+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args[0]), entry) {
588+
if (Z_TYPE_P(entry) > IS_STRING) {
589+
return FAILURE;
590+
}
591+
} ZEND_HASH_FOREACH_END();
592+
} else {
593+
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args[1]), entry) {
594+
if (Z_TYPE_P(entry) > IS_STRING) {
595+
return FAILURE;
596+
}
597+
} ZEND_HASH_FOREACH_END();
640598
}
641-
func->internal_function.handler(execute_data, result);
642-
for (i = 0; i < num_args; i++) {
643-
zval_ptr_dtor_nogc(EX_VAR_NUM(i));
599+
/* pass */
600+
} else if (zend_string_equals_literal(name, "version_comapre")) {
601+
if ((num_args != 2 && (num_args != 3 || Z_TYPE_P(args[2]) != IS_STRING))
602+
|| Z_TYPE_P(args[0]) != IS_STRING
603+
|| Z_TYPE_P(args[1]) != IS_STRING) {
604+
return FAILURE;
644605
}
645-
efree(execute_data);
646-
return SUCCESS;
606+
/* pass */
607+
} else {
608+
return FAILURE;
647609
}
648-
return FAILURE;
610+
611+
func = zend_hash_find_ptr(CG(function_table), name);
612+
if (!func || func->type != ZEND_INTERNAL_FUNCTION) {
613+
return FAILURE;
614+
}
615+
616+
execute_data = safe_emalloc(num_args, sizeof(zval), ZEND_CALL_FRAME_SLOT * sizeof(zval));
617+
memset(execute_data, 0, sizeof(zend_execute_data));
618+
EX(func) = func;
619+
EX_NUM_ARGS() = num_args;
620+
for (i = 0; i < num_args; i++) {
621+
ZVAL_COPY(EX_VAR_NUM(i), args[i]);
622+
}
623+
func->internal_function.handler(execute_data, result);
624+
for (i = 0; i < num_args; i++) {
625+
zval_ptr_dtor_nogc(EX_VAR_NUM(i));
626+
}
627+
efree(execute_data);
628+
return SUCCESS;
649629
}
650630

651631
#define SET_RESULT(op, zv) do { \

0 commit comments

Comments
 (0)