diff --git a/Zend/tests/oss_fuzz_454273637.phpt b/Zend/tests/oss_fuzz_454273637.phpt new file mode 100644 index 0000000000000..fbcdb57ed2a16 --- /dev/null +++ b/Zend/tests/oss_fuzz_454273637.phpt @@ -0,0 +1,8 @@ +--TEST-- +OSS-Fuzz #454273637 (UAF with printf optimization and const output) +--FILE-- + +--EXPECT-- +% diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 97e36d6b2498a..8f10f1577ca72 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5009,9 +5009,17 @@ static zend_result zend_compile_func_printf(znode *result, zend_ast_list *args) * pass in the Zend Optimizer if the result of the printf() is in fact * unused */ znode copy; - zend_emit_op_tmp(©, ZEND_COPY_TMP, &rope_result, NULL); - zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL); - zend_emit_op_tmp(result, ZEND_STRLEN, ©, NULL); + if (rope_result.op_type != IS_CONST) { + /* Note: ZEND_COPY_TMP is only valid for TMPVAR. */ + ZEND_ASSERT(rope_result.op_type == IS_TMP_VAR); + zend_emit_op_tmp(©, ZEND_COPY_TMP, &rope_result, NULL); + zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL); + zend_emit_op_tmp(result, ZEND_STRLEN, ©, NULL); + } else { + zend_emit_op(NULL, ZEND_ECHO, &rope_result, NULL); + result->op_type = IS_CONST; + ZVAL_LONG(&result->u.constant, Z_STRLEN(rope_result.u.constant)); + } return SUCCESS; }