Summary
An exception message built from a runtime-produced string is not persisted out of the concat scratch buffer: later concat/itoa activity in the same statement corrupts the message read back by getMessage().
Verified on
main (macOS ARM64). No try/catch involved.
Minimal reproduction
<?php
$e = new RuntimeException(str_repeat("m", 20));
echo strlen($e->getMessage()), "|", $e->getMessage(), "\n";
Actual
The length is right but the last byte of the message is overwritten by the rendering of 20 (the strlen result) — the message pointer stored in the exception object still points into the concat scratch buffer, and the integer-to-string conversion in the same echo stomps it.
Controls (work)
- A plain variable:
$s = str_repeat("m", 20); echo strlen($s), "|", $s; → correct (the local store persists the string).
- A literal message:
new RuntimeException("mmmm...") → correct (persistent literal).
echo 20, "|", $e->getMessage(); (literal int instead of strlen) → correct.
Notes
The exception constructor should persist a scratch-buffer message (__rt_str_persist) when storing it into the object, like ordinary local stores do. Found while stress-testing exception-message lifetimes for #448 (PR #477); unrelated to the catch lifecycle itself.
Summary
An exception message built from a runtime-produced string is not persisted out of the concat scratch buffer: later concat/itoa activity in the same statement corrupts the message read back by
getMessage().Verified on
main(macOS ARM64). No try/catch involved.Minimal reproduction
Actual
The length is right but the last byte of the message is overwritten by the rendering of
20(thestrlenresult) — the message pointer stored in the exception object still points into the concat scratch buffer, and the integer-to-string conversion in the sameechostomps it.Controls (work)
$s = str_repeat("m", 20); echo strlen($s), "|", $s;→ correct (the local store persists the string).new RuntimeException("mmmm...")→ correct (persistent literal).echo 20, "|", $e->getMessage();(literal int instead ofstrlen) → correct.Notes
The exception constructor should persist a scratch-buffer message (
__rt_str_persist) when storing it into the object, like ordinary local stores do. Found while stress-testing exception-message lifetimes for #448 (PR #477); unrelated to the catch lifecycle itself.