streambuf::underflow() bug in 2.10.0

AaronWL@aol.com AaronWL@aol.com
Sun Feb 4 02:11:00 GMT 2001


Hi..

  Following is source code that reproduces what is, as far as I can tell, a 
bug in stdlibc++ 2.10.0, appearing under gcc version 2.95.2-6 19991024 
(cygwin experimental), as well as various other gcc's on other operating 
systems.
  In short, the 'this' pointer being implicitly passed to a function derived 
from streambuf::underflow() is *wrong* because C++ typecasting is being 
circumvented by code in _IO_default_uflow (called by streambuf::uflow()) that 
appears to directly access the virtual function table and call the 
underflow() function directly with the this pointer, a this pointer that, in 
this particular situation, will be wrong because it points to the streambuf, 
NOT to the actual class, and will not be converted by C++.
  If this was not clear enough, the test program below will make the problem 
obvious.  I came across this bug when working on a C++ sockets library.  
Other compilers I tested (Borland C++ 5.5.1 on Windows 98, Compaq's C++ on 
Digital UNIX) passed the test program successfully, while all versions of gcc 
2.95.x I tried on Cygwin, DJGPP, Ming32, OpenBSD, and Linux failed.

(compiled with g++ -Wall -ansi -pedantic -O0 -g -o underflow underflow.cpp)

here is example bad gcc output:
$ ./underflow
dummy pointer= 0x255fccc
streambuf pointer= 0x255fcd0
mystreambuf pointer= 0x255fccc
mystreambuf::five= 5

underflow() this= 0x255fcd0
underflow() five= 2
-snip-
mystreambuf::underflow is clearly being called with the wrong pointer.  
notice underflow reports 'this' (0x255fcd0 should be 0x255fccc) incorrectly, 
resulting in incorrect 'five' giving an incorrect value.  gcc generates no 
warning.

correct behavior generated by Compaq's C++:
  dummy pointer= 0x11ffffb10
  streambuf pointer= 0x11ffffb18
  mystreambuf pointer= 0x11ffffb10
  mystreambuf::five= 5

  underflow() this= 0x11ffffb10
  underflow() five= 5


Here is the code for the test program:

// begin
#include <iostream>

using namespace std;

class dummy {
  int llama;
};

class mystreambuf : public dummy, public streambuf {
  public:
    mystreambuf()
      : five(5) {
      cout << "dummy pointer= " << (void *)(dummy *)this << endl;
      cout << "streambuf pointer= " << (void *)(streambuf *)this << endl;

      cout << "mystreambuf pointer= " << (void *)this << endl;
      cout << "mystreambuf::five= " << five << endl << endl;
    }
  protected:
    int underflow() {
      cout << "underflow() this= " << (void *)this << endl;
      cout << "underflow() five= " << five << endl;

      return EOF;
    }

    int five;
};

int main() {
  class mystreambuf strbuf;
  istream is(&strbuf);
  char ch;

  is >> ch;

  return 0;
}
// end

Thats it.  Sorry for the length and lack of technical detail.. im still a C++ 
newbie.  Are there are workarounds for this problem?  All gcc's appear to 
have it, which is exactly the target compiler for the program i am working 
on...

Aaron W. LaFramboise aaronwl@aol.com
Contact Info and PGP Key: http://members.aol.com/aaronwl/contact.txt




More information about the Libstdc++ mailing list