Skip to content

Commit dff4f5c

Browse files
committed
Fix OSS-Fuzz #454273637: UAF with printf optimization and const output
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 206395f commit dff4f5c

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

Zend/tests/oss_fuzz_454273637.phpt

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

Zend/zend_compile.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5009,9 +5009,16 @@ 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_emit_op_tmp(&copy, ZEND_COPY_TMP, &rope_result, NULL);
5015+
zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL);
5016+
zend_emit_op_tmp(result, ZEND_STRLEN, &copy, NULL);
5017+
} else {
5018+
zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL);
5019+
result->op_type = IS_CONST;
5020+
ZVAL_LONG(&result->u.constant, Z_STRLEN(rope_result.u.constant));
5021+
}
50155022

50165023
return SUCCESS;
50175024
}

0 commit comments

Comments
 (0)