Skip to content

Commit 09c39a8

Browse files
authored
Fix OSS-Fuzz #454273637: UAF with printf optimization and const output (php#20261)
Note that ZEND_COPY_TMP isn't even valid for CONSTs, and we would need to add a ref even if it were, so just add special handling instead to simplify it.
1 parent f8656fa commit 09c39a8

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

Zend/tests/oss_fuzz_454273637.phpt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
OSS-Fuzz #454273637 (UAF with printf optimization and const output)
3+
--FILE--
4+
<?php
5+
printf('%%');
6+
?>
7+
--EXPECT--
8+
%

Zend/zend_compile.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5009,9 +5009,17 @@ static zend_result zend_compile_func_printf(znode *result, zend_ast_list *args)
50095009
* pass in the Zend Optimizer if the result of the printf() is in fact
50105010
* unused */
50115011
znode copy;
5012-
zend_emit_op_tmp(&copy, ZEND_COPY_TMP, &rope_result, NULL);
5013-
zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL);
5014-
zend_emit_op_tmp(result, ZEND_STRLEN, &copy, NULL);
5012+
if (rope_result.op_type != IS_CONST) {
5013+
/* Note: ZEND_COPY_TMP is only valid for TMPVAR. */
5014+
ZEND_ASSERT(rope_result.op_type == IS_TMP_VAR);
5015+
zend_emit_op_tmp(&copy, ZEND_COPY_TMP, &rope_result, NULL);
5016+
zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL);
5017+
zend_emit_op_tmp(result, ZEND_STRLEN, &copy, NULL);
5018+
} else {
5019+
zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL);
5020+
result->op_type = IS_CONST;
5021+
ZVAL_LONG(&result->u.constant, Z_STRLEN(rope_result.u.constant));
5022+
}
50155023

50165024
return SUCCESS;
50175025
}

0 commit comments

Comments
 (0)