Skip to content

Implementation of is_literal #7184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,10 +833,12 @@ uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
/* }}} */

ZEND_API zend_string *zend_create_member_string(zend_string *class_name, zend_string *member_name) {
return zend_string_concat3(
zend_string* string = zend_string_concat3(
ZSTR_VAL(class_name), ZSTR_LEN(class_name),
"::", sizeof("::") - 1,
ZSTR_VAL(member_name), ZSTR_LEN(member_name));
ZSTR_SET_LITERAL_FAST(string);
return string;
}

zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
Expand All @@ -846,7 +848,11 @@ zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_
zend_string *zend_prefix_with_ns(zend_string *name) {
if (FC(current_namespace)) {
zend_string *ns = FC(current_namespace);
return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
zend_string *prefixed =
zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));

ZSTR_SET_LITERAL_FAST(prefixed);
return prefixed;
} else {
return zend_string_copy(name);
}
Expand Down Expand Up @@ -3826,7 +3832,21 @@ static zend_result zend_compile_func_is_scalar(znode *result, zend_ast_list *arg
opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
opline->extended_value = (1 << IS_FALSE | 1 << IS_TRUE | 1 << IS_DOUBLE | 1 << IS_LONG | 1 << IS_STRING);
return SUCCESS;
}
} /* }}} */

static zend_result zend_compile_func_is_literal(znode *result, zend_ast_list *args) /* {{{ */
{
znode arg_node;

if (args->children != 1) {
return FAILURE;
}

zend_compile_expr(&arg_node, args->child[0]);
zend_emit_op(result, ZEND_LITERAL_CHECK, &arg_node, NULL);

return SUCCESS;
} /* }}} */

zend_result zend_compile_func_cast(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
{
Expand Down Expand Up @@ -4357,6 +4377,8 @@ zend_result zend_try_compile_special_func(znode *result, zend_string *lcname, ze
return zend_compile_func_typecheck(result, args, IS_RESOURCE);
} else if (zend_string_equals_literal(lcname, "is_scalar")) {
return zend_compile_func_is_scalar(result, args);
} else if (zend_string_equals_literal(lcname, "is_literal")) {
return zend_compile_func_is_literal(result, args);
} else if (zend_string_equals_literal(lcname, "boolval")) {
return zend_compile_func_cast(result, args, _IS_BOOL);
} else if (zend_string_equals_literal(lcname, "intval")) {
Expand Down
42 changes: 34 additions & 8 deletions Zend/zend_language_scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,15 @@ ZEND_API void zend_prepare_string_for_scanning(zval *str, zend_string *filename)
RESET_DOC_COMMENT();
}

zend_ast* zend_get_scanned_string_ast(zval *zendlval, uint32_t start_line) {
if (Z_TYPE_P(zendlval) == IS_STRING && Z_STRLEN_P(zendlval) > 1) {
zend_string *string =
Z_STR_P(zendlval);

GC_TYPE_INFO(string) |= IS_STR_LITERAL;
}
return zend_ast_create_zval_with_lineno(zendlval, start_line);
}

ZEND_API size_t zend_get_scanned_file_offset(void)
{
Expand Down Expand Up @@ -895,7 +904,7 @@ ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter
ZVAL_STRINGL(zendlval, s, sz); \
efree(s); \
} else if (yyleng == 1) { \
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext))); \
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR((zend_uchar)*(yytext))); \
} else { \
ZVAL_STRINGL(zendlval, yytext, yyleng); \
}
Expand All @@ -907,13 +916,13 @@ static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, c

if (len <= 1) {
if (len < 1) {
ZVAL_EMPTY_STRING(zendlval);
ZVAL_INTERNED_STR(zendlval, ZSTR_EMPTY_LITERAL_ALLOC());
} else {
zend_uchar c = (zend_uchar)*str;
if (c == '\n' || c == '\r') {
CG(zend_lineno)++;
}
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c));
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
}
goto skip_escape_conversion;
}
Expand Down Expand Up @@ -1121,6 +1130,14 @@ skip_escape_conversion:
ZVAL_STRINGL(zendlval, (char *) str, sz);
efree(str);
}

if (UNEXPECTED(Z_STRLEN_P(zendlval) == 1)) {
zend_uchar c = (zend_uchar)*Z_STRVAL_P(zendlval);

zend_string_release(Z_STR_P(zendlval));

ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
}
return SUCCESS;
}

Expand Down Expand Up @@ -2130,7 +2147,7 @@ string:

<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM}|{ONUM} { /* Offset must be treated as a string */
if (yyleng == 1) {
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext)));
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR((zend_uchar)*(yytext)));
} else {
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
Expand Down Expand Up @@ -2285,7 +2302,7 @@ inline_char_handler:
yyless(readsize);
}
} else if (yyleng == 1) {
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*yytext));
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR((zend_uchar)*yytext));
} else {
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
Expand Down Expand Up @@ -2460,13 +2477,13 @@ inline_char_handler:

if (yyleng-bprefix-2 <= 1) {
if (yyleng-bprefix-2 < 1) {
ZVAL_EMPTY_STRING(zendlval);
ZVAL_INTERNED_STR(zendlval, ZSTR_EMPTY_LITERAL_ALLOC());
} else {
zend_uchar c = (zend_uchar)*(yytext+bprefix+1);
if (c == '\n' || c == '\r') {
CG(zend_lineno)++;
}
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR(c));
ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
}
goto skip_escape_conversion;
}
Expand Down Expand Up @@ -2524,6 +2541,15 @@ skip_escape_conversion:
zend_string_release_ex(Z_STR_P(zendlval), 0);
ZVAL_STR(zendlval, new_str);
}

if (UNEXPECTED(Z_STRLEN_P(zendlval) == 1)) {
zend_uchar c = (zend_uchar)*Z_STRVAL_P(zendlval);

zend_string_release(Z_STR_P(zendlval));

ZVAL_INTERNED_STR(zendlval, ZSTR_LITERAL_CHAR(c));
}

RETURN_TOKEN_WITH_VAL(T_CONSTANT_ENCAPSED_STRING);
}

Expand Down Expand Up @@ -3090,7 +3116,7 @@ emit_token_with_str:
emit_token_with_val:
if (PARSER_MODE()) {
ZEND_ASSERT(Z_TYPE_P(zendlval) != IS_UNDEF);
elem->ast = zend_ast_create_zval_with_lineno(zendlval, start_line);
elem->ast = zend_get_scanned_string_ast(zendlval, start_line);
}

emit_token:
Expand Down
11 changes: 11 additions & 0 deletions Zend/zend_operators.c
Original file line number Diff line number Diff line change
Expand Up @@ -1870,10 +1870,15 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
{
zval *orig_op1 = op1;
zval op1_copy, op2_copy;
bool literal = false;

ZVAL_UNDEF(&op1_copy);
ZVAL_UNDEF(&op2_copy);

if (UNEXPECTED(Z_IS_LITERAL_P(op1) && Z_IS_LITERAL_P(op2))) {
literal = true;
}

do {
if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
if (Z_ISREF_P(op1)) {
Expand Down Expand Up @@ -1950,12 +1955,18 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
if (result == op1 && Z_REFCOUNTED_P(result)) {
/* special case, perform operations on result */
result_str = zend_string_extend(Z_STR_P(result), result_len, 0);
if (UNEXPECTED(!literal && ZSTR_IS_LITERAL(result_str))) {
ZSTR_UNSET_LITERAL(&result_str);
}
} else {
result_str = zend_string_alloc(result_len, 0);
memcpy(ZSTR_VAL(result_str), Z_STRVAL_P(op1), op1_len);
if (result == orig_op1) {
i_zval_ptr_dtor(result);
}
if (UNEXPECTED(literal)) {
ZSTR_SET_LITERAL_FAST(result_str);
}
}

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