The readline extension links both libreadline and libhistory. This is
unnecessary, and inspection of the readline example programs since
version 2.0 implies that it has always been unnecessary. Both libraries
include history.o, so linking to both gives you two copies of that module.
The bug occurs when, due to operating system vagaries, libhistory loads
before libreadline. This causes PHP's readline_add_history() to add
history entries to libhistory's copy of the_history. Then when
readline() is called, libreadline attempts to read the other copy of
the_history. The result is a null pointer dereference in libreadline's
previous_history() function.
The solution is to remove all references to libhistory in
ext/readline/config.m4. I have patched this in and tested it.
This bug was closed as "bogus" on bugs.php.net due to some temporary
short-circuit in the mind of a bug tracker admin. It's totally PHP's
fault and there's nothing any distro can do to fix it.
-- Tim Starling
Tim Starling kirjoitti:
The readline extension links both libreadline and libhistory. This is
unnecessary, and inspection of the readline example programs since
version 2.0 implies that it has always been unnecessary. Both libraries
include history.o, so linking to both gives you two copies of that module.
I'd be quite worried about this what you mentioned in that report:
"The libraries are loaded in the problematic order in Ubuntu 9.04,
previous versions of Ubuntu appeared to work.
WHY does newer Ubuntu load some lib before the other? I'd find that out to
prevent other similar problems.
The bug occurs when, due to operating system vagaries, libhistory loads
before libreadline. This causes PHP's readline_add_history() to add
history entries to libhistory's copy of the_history. Then when
readline() is called, libreadline attempts to read the other copy of
the_history. The result is a null pointer dereference in libreadline's
previous_history() function.The solution is to remove all references to libhistory in
ext/readline/config.m4. I have patched this in and tested it.
Apparently there are other OSes with some problems as well with it.
I removed the stuff in CVS now.
This bug was closed as "bogus" on bugs.php.net due to some temporary
short-circuit in the mind of a bug tracker admin. It's totally PHP's
fault and there's nothing any distro can do to fix it.
Heh..I have short temper but definately no short-circuits. Rather "long cabling"
maybe. :D
--Jani
Jani Taskinen wrote:
Tim Starling kirjoitti:
The readline extension links both libreadline and libhistory. This is
unnecessary, and inspection of the readline example programs since
version 2.0 implies that it has always been unnecessary. Both libraries
include history.o, so linking to both gives you two copies of that
module.I'd be quite worried about this what you mentioned in that report:
"The libraries are loaded in the problematic order in Ubuntu 9.04,
previous versions of Ubuntu appeared to work.WHY does newer Ubuntu load some lib before the other? I'd find that
out to prevent other similar problems.
Well, I don't really want to spend days tracking down what I'd consider
a point of trivia, but it was an interesting enough question for me to
fire up an old debian VM and check out the differences.
I had assumed that the difference between the OS's was in link order,
but I hadn't checked that. Actually it's not, the difference is in
relocation. Disassembly showed that pointers to globals were fetched
from a table pointed to by ebx, presumably this is the PLT. In the old
VM, ebx was the same in previous_history() and add_history(), despite
them coming from different libraries. In the new Ubuntu, ebx was
different in the two functions. So the old OS is using the same set of
globals for the two copies of the object, whereas the new OS is using
two different sets.
I checked the instruction pointer in add_history() against /proc/*/maps
to confirm that it is indeed the one from libhistory that is being
called, in the non-crash case.
That's as far as I'm going today. Smells like a glibc bugfix.
In any case, to prevent similar problems, we really need a tool that can
check all the libraries php links to for symbol conflicts. The fact that
two different libraries were exporting add_history() could have been
detected.
-- Tim Starling