The following code:
<?php
function e($m, $n) {
return eval(
'return new class() {
// '. str_repeat('a', $m). '
public function test() {
return "'. $n. '";
}
};'
);
}
for ($i = 131; $i < 140; $i++) {
printf("%d: %d, %d, %d, %d, %d, %dn",
$i,
e($i, 1)->test(),
e($i, 2)->test(),
e($i, 1)->test(),
e($i, 2)->test(),
e($i + 1, 1)->test(),
e($i + 1, 2)->test()
);
}
When run using php 7.4 or 8.* it prints
131: 1, 2, 1, 2, 1, 2
132: 1, 2, 1, 2, 1, 2
133: 1, 2, 1, 2, 1, 2
134: 1, 2, 1, 2, 1, 2
135: 1, 2, 1, 2, 1, 2
136: 1, 2, 1, 2, 1, 2
137: 1, 2, 1, 2, 1, 2
138: 1, 2, 1, 2, 1, 2
139: 1, 2, 1, 2, 1, 2
which is expected. When run using php 7.3 – 7.0 it prints
131: 1, 2, 2, 2, 1, 1
132: 1, 1, 1, 1, 1, 2
133: 1, 2, 1, 2, 1, 2
134: 1, 2, 1, 2, 1, 2
135: 1, 2, 1, 2, 1, 1
136: 1, 1, 1, 1, 1, 1
137: 1, 1, 1, 1, 1, 1
138: 1, 1, 1, 1, 1, 1
139: 1, 1, 1, 1, 1, 1
which is quite unexpected. I haven’t found a workaround and I really need one!
Initially it seemed to be about the number of characters in the beginning of the eval’d code that are the same, but when the code is more complex this is no longer the case.
Please, help!
2
Answers
I am not sure what cause your problem, but usage of
eval()
must be avoided when it’s possible, and here it’s possible:Output:
While I have no concrete idea what is causing this bug, my gut says that it’s something to do with the object reference being returned from the eval’d code.
That said, while I was fiddling around with test cases it started working for some reason with the following code:
If anything it’s probably the array assignment, or merely having another actual operation between invocations of
eval()
code, or having an opportunity to GC the orphan eval object result and avoid pollution.Questionable if it will actually work in your actual code, but it’s something. You should still also file that bug.