Topic: strstream bug found!!


Author: mee@turtle.mrj.com (Mark Everline)
Date: 4 Sep 1993 14:44:11 -0400
Raw View
The following Is a copy of a bug report sent the Centerline about a
bug/problem found in using the CFRONT strstreambuf:

I may have found an important bug in strstreambuf (or streambuf). The
problem briefly stated, is as follows the put-pointer-base, pbase, is
being moved when a new buffer segments is dynamically allocated. This
causes a loss of data from the front of the buffer. Only the last
part of a line will appear on the output stream.

This error is not consistant, is occurs less the 1% of the time for
everay output line. The program following the post shows the symptoms.
Also, the pcount() and out_waiting() calls will produce different
results. Source code for the original is approximately 2000 lines of
code uses Rogue Wave Tools++ and IPC_SAP (Wrappers around all of UNIX
IPC stuff).

I do not see any descrepencies in the my code after extensive review.
I belive this problem to be a CFRONT library error. The Sun CC and
CenterLine CC compilers produce the same result. I was unable to test
g++ beacuse it was unable to compile the programe that follows.

Graphical explantation:

pointers before the malloc:

  base()                              pptr()
  V                                   V
  -------------------------------------
  ^
  pbase()

pointers after a malloc:

  base()                              pptr()
  V                                   V
  -------------------------------------------------------------------------
  |  lost data                       |^
                                      pbase()

The pbase() pointer is wrong it should be equal to base() Everything from
base() to pbase() will be lost.

Sample Program:

Class RDStringBuf : public strstreambuf {
   public:
                  RDStringBuf();
    virtual      ~RDStringBuf();

    virtual int   sync();
    virtual void  setForGet();
    virtual void  setForPut();
    virtual void  dumpBuffer();
    int           amt();
};

int RDStringBuf::sync()
{
    this->freeze(0);
    if (gptr() && eptr() > gptr() )
       setg(base(), base(), base());
    else if (pptr() && pptr() > pbase())
       setp(base(), ebuf() -1 );
    return 0;
}

void RDStringBuf::setForPut()

{
    this->freeze(0);
    setp(base(), base() + in_avail() -1);
    return;
}

void RDStringBuf::setForGet()

{
    this->freeze(0);
    setg(base(), base(), base()+out_waiting()+1);
 // or
 // setg(base(), base(), base()+pcout()+1);
 //   since pcount() and out_waiting() don't agree you
 //   screwed either way.
 //
}

RDStringBuf::RDStringBuf()

{
}

RDStringBuf::~RDStringBuf()
{
   return;
}

void RDStringBuf::dumpBuffer()

{
   int j, length = pptr() - pbase());
   char *ptr = pbase();

   cerr << ">>=======================================================<<"
        << endl;

   cerr << ">>-- length: pptr()-pbase(): << length << endl
        << " --- pcount(): " << pcount() << " - dump from pbase() ---- <<"
        << endl;

   for (j = 0; j < length; j++) cerr << *ptr++;
   cerr << endl;
   cerr << ">>----- pbase() = 0x" << hex << (int) pbase()
        << " ---- base() = 0x" << (int) base() << "-----------------<<"
        << dec << endl;

   cerr << ">> ----- dump from base() ---------------------------------<<"
        << endl;
   ptr = base();
   length = pptr() - base();
   for (j = 0; j < length; j++) cerr << *pptr++;

   cerr << endl
        << ">>---- length = ppt() - base(): " << length << endl
        << ">>========================================================<<"
        << endl;
   return;
};

int RDStringBuf::amt()
{
   return (int) (pptr() - pbase());
}

main()
{
    RDStringBuf s;
    ostream out(streambuf *) &s);

    static char ss[] = ": The quick brown fox jumped over the lazy dog. ";
    for ( int n = 0; n < 10; n++) {
       out << n;
       for (int j = 0; j < strlen(ss); j++)
         out << ss[j];
       s.dumpBuffer();
    }
    cerr << s.str();
}

A Quick explantion. I needed a strstream that I could read data into,
data could be from a pipe, socket, rpc or fifo, which would then be
passed onto another object to read ie duplex in the data with out having
to error check anything but the data, the strstream is not duplex resulting.
in RDStringBuf subclass. This is a example of the input and ouput code:

  out << a << b << c;   ....     in >> a >> b >> c;

The RDStringBuf when created was used by a RWvistream or RWvostream to
fromat/read the data as binary, XDR, or ASCII for the object. The main
reason for the is I have access only to SUN's and would like to known
if other CFRONT compilers have the same problem.


     Mark Everline

P.S. I thought I was using a lanaguage to deliver a commercial product
     I guess I was wrong.

---------------------------------------------------------------------------
| W: 703-385-0897/202-863-3334    | Something cleaver I have not thought  |
| H: 703-729-4463                 | of.                                   |
| email: mee@mrj.com              | Standard Disclimer applyies.          |
|                                 |                                       |
---------------------------------------------------------------------------