Commit cebf67e
committed
Fix GH-20482: heap use-after-free in ZEND_ASSIGN_DIM via re-entrant user output handler
When ZEND_ASSIGN_DIM evaluates an undefined CV as the RHS, the warning
emitted by zval_undefined_cv() can be routed through a user output
handler (e.g. via ob_start with a small chunk size). The handler runs
arbitrary PHP code, which may free, unset or rehash the array we are
writing to, leaving the previously-fetched variable_ptr pointing into
freed/relocated memory. The next zend_assign_to_variable_ex then
performs a heap use-after-free.
In the OP2_TYPE != IS_UNUSED branch:
- Switch GET_OP_DATA_ZVAL_PTR to GET_OP_DATA_ZVAL_PTR_UNDEF so we no
longer auto-emit the warning. Detect IS_UNDEF explicitly and call
zval_undefined_cv around a temporary GC_ADDREF / GC_DELREF on the
target HashTable, mirroring the IS_UNUSED branch and the previous
fix in slow_index_convert (b594a95).
- Reorder the pipeline: fetch the data value (and emit the warning)
*before* resolving variable_ptr. Resolving the dim address only
afterwards guarantees a fresh bucket pointer that cannot have been
invalidated by reentrant user code freeing the array, rehashing it
or unsetting keys.
Includes phpt regressions covering the three reentrancy paths:
- output handler reassigns the array,
- output handler unsets the array,
- output handler rehashes the array (would invalidate any pre-fetched
bucket pointer).1 parent 1462499 commit cebf67e
5 files changed
Lines changed: 1234 additions & 147 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
21 | 24 | | |
22 | 25 | | |
23 | 26 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
Lines changed: 29 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2730 | 2730 | | |
2731 | 2731 | | |
2732 | 2732 | | |
| 2733 | + | |
2733 | 2734 | | |
| 2735 | + | |
| 2736 | + | |
| 2737 | + | |
| 2738 | + | |
| 2739 | + | |
| 2740 | + | |
| 2741 | + | |
| 2742 | + | |
| 2743 | + | |
| 2744 | + | |
| 2745 | + | |
| 2746 | + | |
| 2747 | + | |
| 2748 | + | |
| 2749 | + | |
| 2750 | + | |
| 2751 | + | |
| 2752 | + | |
| 2753 | + | |
| 2754 | + | |
| 2755 | + | |
2734 | 2756 | | |
2735 | | - | |
| 2757 | + | |
2736 | 2758 | | |
2737 | | - | |
| 2759 | + | |
2738 | 2760 | | |
2739 | 2761 | | |
2740 | 2762 | | |
2741 | 2763 | | |
2742 | | - | |
2743 | 2764 | | |
2744 | 2765 | | |
2745 | 2766 | | |
| |||
0 commit comments