|
32 | 32 | #include "zend_multibyte.h" |
33 | 33 | #include "zend_language_scanner.h" |
34 | 34 | #include "zend_inheritance.h" |
| 35 | +#include "zend_smart_str.h" |
35 | 36 | #include "zend_vm.h" |
36 | 37 |
|
37 | 38 | #define SET_NODE(target, src) do { \ |
@@ -7315,16 +7316,46 @@ void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */ |
7315 | 7316 |
|
7316 | 7317 | void zend_compile_exception_coalesce(znode *result, zend_ast *ast) /* {{{ */ |
7317 | 7318 | { |
7318 | | - zend_ast *expr = ast->child[0]; |
| 7319 | + zend_ast *lhs = ast->child[0]; |
| 7320 | + zend_ast *rhs = ast->child[1]; |
7319 | 7321 |
|
7320 | | - zend_ast *hack = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, |
7321 | | - zend_ast_create_zval_from_str( |
7322 | | - zend_ast_export("try { return ", expr, "; } catch(\\Throwable $e) {}"))); |
| 7322 | + char idstr[20]; |
| 7323 | + sprintf(idstr, "EXCO???%013d", rand()); |
7323 | 7324 |
|
7324 | | - ast->child[0] = hack; |
7325 | | - zend_ast_destroy(expr); |
| 7325 | + const char *prefix = "try { return "; |
| 7326 | + char suffix[60]; |
| 7327 | + sprintf(suffix, "; } catch (\\Throwable $e) { return '%s'; }", idstr); |
7326 | 7328 |
|
7327 | | - zend_compile_coalesce(result, ast); |
| 7329 | + zend_ast *eval = zend_ast_create_ex(ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, |
| 7330 | + zend_ast_create_zval_from_str( |
| 7331 | + zend_ast_export(prefix, lhs, suffix))); |
| 7332 | + zend_ast_destroy(lhs); |
| 7333 | + |
| 7334 | + zend_string *idzendstring = zend_string_init(idstr, strlen(idstr), 0); |
| 7335 | + zend_ast *idstring = zend_ast_create_zval_from_str(idzendstring); |
| 7336 | + |
| 7337 | + zend_ast *var = zend_ast_create(ZEND_AST_VAR, "_exco"); |
| 7338 | + zend_ast *assign = zend_ast_create(ZEND_AST_ASSIGN, var, eval); |
| 7339 | + zend_ast *equal = zend_ast_create_binary_op(ZEND_IS_IDENTICAL, var, idstring); |
| 7340 | + zend_ast *and = zend_ast_create_binary_op(ZEND_AST_AND, assign, equal); |
| 7341 | + zend_ast *ternary = zend_ast_create(ZEND_AST_CONDITIONAL, and, rhs, var); |
| 7342 | + |
| 7343 | + /* |
| 7344 | + TERNARY( |
| 7345 | + AND( |
| 7346 | + ASSIGN(VAR, EVAL(LHS expr)), |
| 7347 | + EQUAL(VAR, idstring) |
| 7348 | + ), |
| 7349 | + RHS expr, |
| 7350 | + VAR |
| 7351 | + ) |
| 7352 | +
|
| 7353 | + or: ($_exco = eval(...) && $_exco == idstring) ? RHS : $_exco; |
| 7354 | + */ |
| 7355 | + |
| 7356 | + zend_compile_coalesce(result, ternary); |
| 7357 | + // free(prefix); |
| 7358 | + // free(suffix); |
7328 | 7359 | } |
7329 | 7360 | /* }}} */ |
7330 | 7361 |
|
|
0 commit comments