[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: