The APT problem
When glibc 2.1 was introduced in potato, apt stopped working. Recompiling
fixed it, but I figured this indicated a bug in the compat code, so today
I found time to investigate it. Jason Gunthorpe had provided me with
a test case:
#include <iostream>
#include <fstream>
void die(const char *S)
{
cerr << S << endl;
exit(1);
}
int main(int argc,const char *argv[])
{
ifstream F(argv[1],ios::in | ios::nocreate);
if (!F != 0)
die("!F #1");
streampos Off = F.tellg();
if (!F != 0)
die("!F #2");
return 0;
}
(This has to be run with the name of an existing file as argument.)
When run on a glibc2.1 system, a version compiled with libstdc++2.9
will die with "!F #2". A version compiled with libstdc++2.9-glibc2.1
will exit successfully.
The problem turns out to be rather simple. istream:tellg() contains
this code:
streampos istream::tellg()
{
#if 0
streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::in);
#else
streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_INPUT);
#endif
if (pos == streampos(EOF))
set(ios::badbit);
return pos;
}
(This is taken from egcs 1.1.2/libio, a different version than what
generated libstdc++2.9, but I can tell from the disassembly that the
significant part didn't change.)
This code calls _IO_seekoff directly, expecting that it takes a 32-bit
offset. But _IO_seekoff in glibc2.1 takes a 64-bit offset, and ends
up trying to seek to 0x100000000 and failing.
egcs's libio appears to be full of references to glibc's libio.
I checked some others at random (_IO_proc_open, _IO_file_close,
_IO_adjust_column), and found that filebuf::seekoff probably
has the same problem when it calls _IO_file_seekoff, because both
_IO_old_file_seekoff and _IO_new_file_seekoff now take a 64-bit offset.
Richard Braakman
Reply to: