Fix GH-21639: Keep frameless CV args alive during __toString()#21815
Fix GH-21639: Keep frameless CV args alive during __toString()#21815prateekbhujel wants to merge 3 commits intophp:PHP-8.4from
Conversation
|
Thanks for the PR.
I'm afraid this will need a more general solution. My hope was to avoid overhead in the VM, but it might be unavoidable for a proper fix, even if this is a largely artificial issue. |
35148db to
15ec47b
Compare
15ec47b to
c818fa7
Compare
c818fa7 to
08cc08f
Compare
08cc08f to
38e2314
Compare
|
The other alternative would be checking inside the tostring handler whether the parent frame is currently at a frameless opcode and then safely copy its CV args to a buffer, set EG(vm_interrupt) and free them on the next EG(vm_interrupt), completely moving the overhead off the main paths and be a truly generic solution. Obviously comes at a small tostring handler cost, but I'd really rather see overhead there...? |
38e2314 to
163b9ef
Compare
163b9ef to
9ae220f
Compare
|
@bwoebi Yeah, agreed. That cost belongs on the I pushed a follow-up in that direction. It checks from I did not keep the cleanup on So the copy/dtor work is on actual |
Fixes GH-21639.
Frameless internal calls can borrow CV operands from the caller frame. If one of those operands is converted through
__toString(), userland can overwrite the original CV while the handler is still using the borrowed value.This protects that case from the reentry side. Before calling
__toString(), the engine checks whether the current frame is executing a frameless call and keeps copies of any string/array CV operands for that opcode. The copies are released when the frameless handler returns; executor shutdown still force-cleans anything left during unwinding.That keeps the copy/dtor work off ordinary frameless calls. The normal path only has the cold pending-copy cleanup check after a frameless handler returns, including the JIT frameless path.
Tests run: