Skip to content

AOT: string concat result is freed too early — empty when passed to a function, free(): invalid pointer on reuse #23798

Description

@PurHur

Summary

In AOT binaries, the result of a string concatenation does not survive. Passing it to a function
yields an empty string; concatenating from the same variable a second time aborts with
free(): invalid pointer. Both look like a premature free / double free of the concat result.

VM is unaffected — script/differential-sweep.sh (VM) is 53/53. This is AOT-only.

Minimal reproducers

1 — concat result passed to a function arrives empty

<?php function f($a){ echo $a, "\n"; } $s='s'; f($s.'1');
zend: s1
aot :            <- empty

2 — second concat from the same variable corrupts the heap

<?php $s='s'; echo $s.'1', "\n"; echo $s.'2', "\n";
zend: s1
      s2
aot : s1
      free(): invalid pointer

Note the first concat prints correctly and the second one dies — consistent with the backing
buffer being released after the first use and then freed again.

What it is not

Deliberately bounded with a control set. These all pass in AOT, so it is not about arguments,
arity, or interpolation:

case result
function f($a,$b){...} f('x','y') — literal args ok
function f($a,$b){ echo "$a $b\n"; } f('x','y') — interpolation ok
function f($a){...} $x=1; f($x+1) — arithmetic arg ok
function f($a,$b){...} $x=1; f($x+1,$x+2) — two arithmetic args ok
function f($a){...} $s='s'; f($s.'1')concat arg empty
function f($a,$b){...} $s='s'; f($s.'1',$s.'2')two concat args empty
$s='s'; echo $s.'1'; echo $s.'2';concat, no call at all free(): invalid pointer

Arithmetic results as arguments are fine; only string concat is affected. And reproducer 2 has no
function call in it, so this is not argument passing — it is the lifetime of the concat result
itself.

It is also not the #579 external-stub class. Built with PHP_COMPILER_WARN_EXTERNAL_STUBS=1,
the only warning emitted is phpcompiler\ext\dom\builtinclasses::register, which is incidental and
also present in binaries that run correctly.

Likely blast radius

This probably accounts for most of the string cluster in #23779: c04_concat, c11_strcmp,
d04_concat_dim, e15_str_fns (which dies with the same free(): invalid pointer), and possibly
e23_implode.

Environment

php-compiler:22.04-dev, PHP 8.2.32, LLVM 9. Reproduced on clean master 544d1dca9 (no local
lib/ modifications — verified). Built with php bin/compile.php -o <bin> <file>.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:compilerCompiler / CFG / JITbugSomething isn't workingimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-3:aotPhase 3 – AOT deployment

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions