Skip to content

Commit 6b67106

Browse files
committed
is_literal
1 parent 7bc0dd2 commit 6b67106

33 files changed

+1536
-557
lines changed

Zend/zend_compile.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,13 @@ static int lookup_cv(zend_string *name) /* {{{ */{
504504
static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */
505505
{
506506
ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
507+
508+
if (ZSTR_IS_LITERAL_CHAR(Z_STR_P(zv))) {
509+
Z_TYPE_FLAGS_P(zv) = 0;
510+
511+
return Z_STR_P(zv);
512+
}
513+
507514
Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
508515
if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
509516
Z_TYPE_FLAGS_P(zv) = 0;
@@ -833,10 +840,12 @@ uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
833840
/* }}} */
834841

835842
ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name) {
836-
return zend_string_concat3(
843+
zend_string* string = zend_string_concat3(
837844
ZSTR_VAL(class_name), ZSTR_LEN(class_name),
838845
"::", sizeof("::") - 1,
839846
ZSTR_VAL(member_name), ZSTR_LEN(member_name));
847+
ZSTR_SET_LITERAL_FAST(string);
848+
return string;
840849
}
841850

842851
zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
@@ -846,7 +855,11 @@ zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_
846855
zend_string *zend_prefix_with_ns(zend_string *name) {
847856
if (FC(current_namespace)) {
848857
zend_string *ns = FC(current_namespace);
849-
return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
858+
zend_string *prefixed =
859+
zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
860+
861+
ZSTR_SET_LITERAL_FAST(prefixed);
862+
return prefixed;
850863
} else {
851864
return zend_string_copy(name);
852865
}
@@ -3819,7 +3832,21 @@ static zend_result zend_compile_func_is_scalar(znode *result, zend_ast_list *arg
38193832
opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
38203833
opline->extended_value = (1 << IS_FALSE | 1 << IS_TRUE | 1 << IS_DOUBLE | 1 << IS_LONG | 1 << IS_STRING);
38213834
return SUCCESS;
3822-
}
3835+
} /* }}} */
3836+
3837+
static zend_result zend_compile_func_is_literal(znode *result, zend_ast_list *args) /* {{{ */
3838+
{
3839+
znode arg_node;
3840+
3841+
if (args->children != 1) {
3842+
return FAILURE;
3843+
}
3844+
3845+
zend_compile_expr(&arg_node, args->child[0]);
3846+
zend_emit_op(result, ZEND_LITERAL_CHECK, &arg_node, NULL);
3847+
3848+
return SUCCESS;
3849+
} /* }}} */
38233850

38243851
zend_result zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
38253852
{
@@ -4350,6 +4377,8 @@ zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, ze
43504377
return zend_compile_func_typecheck(result, args, IS_RESOURCE);
43514378
} else if (zend_string_equals_literal(lcname, "is_scalar")) {
43524379
return zend_compile_func_is_scalar(result, args);
4380+
} else if (zend_string_equals_literal(lcname, "is_literal")) {
4381+
return zend_compile_func_is_literal(result, args);
43534382
} else if (zend_string_equals_literal(lcname, "boolval")) {
43544383
return zend_compile_func_cast(result, args, _IS_BOOL);
43554384
} else if (zend_string_equals_literal(lcname, "intval")) {

Zend/zend_language_scanner.l

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,15 @@ ZEND_API void zend_prepare_string_for_scanning(zval *str, zend_string *filename)
760760
RESET_DOC_COMMENT();
761761
}
762762

763+
zend_ast* zend_get_scanned_string_ast(zval *zendlval, uint32_t start_line) {
764+
if (Z_TYPE_P(zendlval) == IS_STRING && Z_STRLEN_P(zendlval) > 1) {
765+
zend_string *string =
766+
Z_STR_P(zendlval);
767+
768+
GC_TYPE_INFO(string) |= IS_STR_LITERAL;
769+
}
770+
return zend_ast_create_zval_with_lineno(zendlval, start_line);
771+
}
763772

764773
ZEND_API size_t zend_get_scanned_file_offset(void)
765774
{
@@ -895,7 +904,7 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
895904
ZVAL_STRINGL(zendlval, s, sz); \
896905
efree(s); \
897906
} else if (yyleng == 1) { \
898-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext))); \
907+
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR((zend_uchar)*(yytext))); \
899908
} else { \
900909
ZVAL_STRINGL(zendlval, yytext, yyleng); \
901910
}
@@ -907,13 +916,13 @@ static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, c
907916

908917
if (len <= 1) {
909918
if (len < 1) {
910-
ZVAL_EMPTY_STRING(zendlval);
919+
ZVAL_INTERNED_STR(zendlval, ZSTR_EMPTY_LITERAL_ALLOC());
911920
} else {
912921
zend_uchar c = (zend_uchar)*str;
913922
if (c == '\n' || c == '\r') {
914923
CG(zend_lineno)++;
915924
}
916-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c));
925+
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
917926
}
918927
goto skip_escape_conversion;
919928
}
@@ -1121,6 +1130,14 @@ skip_escape_conversion:
11211130
ZVAL_STRINGL(zendlval, (char *) str, sz);
11221131
efree(str);
11231132
}
1133+
1134+
if (UNEXPECTED(Z_STRLEN_P(zendlval) == 1)) {
1135+
zend_uchar c = (zend_uchar)*Z_STRVAL_P(zendlval);
1136+
1137+
zend_string_release(Z_STR_P(zendlval));
1138+
1139+
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
1140+
}
11241141
return SUCCESS;
11251142
}
11261143

@@ -2121,7 +2138,7 @@ string:
21212138

21222139
<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM}|{ONUM} { /* Offset must be treated as a string */
21232140
if (yyleng == 1) {
2124-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext)));
2141+
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR((zend_uchar)*(yytext)));
21252142
} else {
21262143
ZVAL_STRINGL(zendlval, yytext, yyleng);
21272144
}
@@ -2276,7 +2293,7 @@ inline_char_handler:
22762293
yyless(readsize);
22772294
}
22782295
} else if (yyleng == 1) {
2279-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*yytext));
2296+
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR((zend_uchar)*yytext));
22802297
} else {
22812298
ZVAL_STRINGL(zendlval, yytext, yyleng);
22822299
}
@@ -2451,13 +2468,13 @@ inline_char_handler:
24512468

24522469
if (yyleng-bprefix-2 <= 1) {
24532470
if (yyleng-bprefix-2 < 1) {
2454-
ZVAL_EMPTY_STRING(zendlval);
2471+
ZVAL_INTERNED_STR(zendlval, ZSTR_EMPTY_LITERAL_ALLOC());
24552472
} else {
24562473
zend_uchar c = (zend_uchar)*(yytext+bprefix+1);
24572474
if (c == '\n' || c == '\r') {
24582475
CG(zend_lineno)++;
24592476
}
2460-
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c));
2477+
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
24612478
}
24622479
goto skip_escape_conversion;
24632480
}
@@ -2515,6 +2532,15 @@ skip_escape_conversion:
25152532
zend_string_release_ex(Z_STR_P(zendlval), 0);
25162533
ZVAL_STR(zendlval, new_str);
25172534
}
2535+
2536+
if (UNEXPECTED(Z_STRLEN_P(zendlval) == 1)) {
2537+
zend_uchar c = (zend_uchar)*Z_STRVAL_P(zendlval);
2538+
2539+
zend_string_release(Z_STR_P(zendlval));
2540+
2541+
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
2542+
}
2543+
25182544
RETURN_TOKEN_WITH_VAL(T_CONSTANT_ENCAPSED_STRING);
25192545
}
25202546

@@ -3081,7 +3107,7 @@ emit_token_with_str:
30813107
emit_token_with_val:
30823108
if (PARSER_MODE()) {
30833109
ZEND_ASSERT(Z_TYPE_P(zendlval) != IS_UNDEF);
3084-
elem->ast = zend_ast_create_zval_with_lineno(zendlval, start_line);
3110+
elem->ast = zend_get_scanned_string_ast(zendlval, start_line);
30853111
}
30863112
30873113
emit_token:

Zend/zend_operators.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,10 +1870,15 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
18701870
{
18711871
zval *orig_op1 = op1;
18721872
zval op1_copy, op2_copy;
1873+
bool literal = false;
18731874

18741875
ZVAL_UNDEF(&op1_copy);
18751876
ZVAL_UNDEF(&op2_copy);
18761877

1878+
if (UNEXPECTED(Z_IS_LITERAL_P(op1) && Z_IS_LITERAL_P(op2))) {
1879+
literal = true;
1880+
}
1881+
18771882
do {
18781883
if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
18791884
if (Z_ISREF_P(op1)) {
@@ -1950,12 +1955,18 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
19501955
if (result == op1 && Z_REFCOUNTED_P(result)) {
19511956
/* special case, perform operations on result */
19521957
result_str = zend_string_extend(Z_STR_P(result), result_len, 0);
1958+
if (UNEXPECTED(!literal && ZSTR_IS_LITERAL(result_str))) {
1959+
ZSTR_UNSET_LITERAL(&result_str);
1960+
}
19531961
} else {
19541962
result_str = zend_string_alloc(result_len, 0);
19551963
memcpy(ZSTR_VAL(result_str), Z_STRVAL_P(op1), op1_len);
19561964
if (result == orig_op1) {
19571965
i_zval_ptr_dtor(result);
19581966
}
1967+
if (UNEXPECTED(literal)) {
1968+
ZSTR_SET_LITERAL_FAST(result_str);
1969+
}
19591970
}
19601971

19611972
/* This has to happen first to account for the cases where result == op1 == op2 and

0 commit comments

Comments
 (0)