Skip to content

Commit 353d28f

Browse files
handle special printf() case
1 parent 40e2a53 commit 353d28f

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

Zend/zend_compile.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4956,6 +4956,45 @@ static zend_result zend_compile_func_sprintf(znode *result, zend_ast_list *args)
49564956

49574957
static zend_result zend_compile_func_printf(znode *result, zend_ast_list *args) /* {{{ */
49584958
{
4959+
/* Special case: printf with a single constant string argument and no format specifiers.
4960+
* In this case, just emit ECHO and return the string length if needed. */
4961+
if (args->children == 1) {
4962+
zend_eval_const_expr(&args->child[0]);
4963+
if (args->child[0]->kind == ZEND_AST_ZVAL) {
4964+
zval *format_string = zend_ast_get_zval(args->child[0]);
4965+
if (Z_TYPE_P(format_string) == IS_STRING) {
4966+
/* Check if there are any format specifiers */
4967+
char *p = Z_STRVAL_P(format_string);
4968+
char *end = p + Z_STRLEN_P(format_string);
4969+
bool has_format_specs = false;
4970+
4971+
while (p < end) {
4972+
if (*p == '%') {
4973+
p++;
4974+
if (p < end && *p != '%') {
4975+
has_format_specs = true;
4976+
break;
4977+
}
4978+
}
4979+
p++;
4980+
}
4981+
4982+
if (!has_format_specs) {
4983+
/* No format specifiers - just emit ECHO and return string length */
4984+
znode format_node;
4985+
zend_compile_expr(&format_node, args->child[0]);
4986+
zend_emit_op(NULL, ZEND_ECHO, &format_node, NULL);
4987+
4988+
/* Return the string length as a constant if the result is used */
4989+
result->op_type = IS_CONST;
4990+
ZVAL_LONG(&result->u.constant, Z_STRLEN_P(format_string));
4991+
return SUCCESS;
4992+
}
4993+
}
4994+
}
4995+
}
4996+
4997+
/* Fall back to sprintf optimization for format strings with specifiers */
49594998
znode rope_result;
49604999
if (zend_compile_func_sprintf(&rope_result, args) != SUCCESS) {
49615000
return FAILURE;
@@ -4964,7 +5003,7 @@ static zend_result zend_compile_func_printf(znode *result, zend_ast_list *args)
49645003
/* printf() returns the amount of bytes written, so just an ECHO of the resulting sprintf()
49655004
* optimisation might not be enough. At this early stage we can't detect if the result is
49665005
* actually used, so we just emit the opcodes and cleanup if they are not used in the
4967-
* optimizer later. */
5006+
* optimizers block pass later. */
49685007
znode copy;
49695008
zend_emit_op_tmp(&copy, ZEND_COPY_TMP, &rope_result, NULL);
49705009
zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL);

0 commit comments

Comments
 (0)