From: bothner@cygnus.com
Newsgroups: gnu.g++.lib.bug
Subject: Re: 2.3: width(x) off by 1 for istreams
Date: 21 Jan 1993 18:22:51 -0500
Organization: GNUs Not Usenet
Distribution: gnu

> The width attribute of an istream is supposed to limit the number of
> characters read into a char* variable to prevent overflowing a buffer.

The following patch should fix this.  It also should suppress
print of '+' for unsigned values.

	--Per Bothner
Cygnus Support     bothner@cygnus.com

===================================================================
RCS file: /rel/cvsfiles/devo/libg++/iostream/iostream.C,v
retrieving revision 1.34
diff -c -r1.34 iostream.C
*** 1.34	1993/01/17 02:08:11
--- iostream.C	1993/01/21 22:33:33
***************
*** 157,163 ****
  	    set(ios::eofbit|ios::failbit);
  	else {
  	    int w = width(0);
! 	    *ptr++ = ch;
  	    for (;;) {
  		ch = sb->sbumpc();
  		if (ch == EOF) {
--- 157,163 ----
  	    set(ios::eofbit|ios::failbit);
  	else {
  	    int w = width(0);
! 	    sb->sputbackc(ch);
  	    for (;;) {
  		ch = sb->sbumpc();
  		if (ch == EOF) {
***************
*** 342,348 ****
      return *this;
  }
  
! static void write_int(ostream& stream, unsigned LONGEST val, int neg)
  {
  #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
      char buf[WRITE_BUF_SIZE];
--- 342,353 ----
      return *this;
  }
  
! /* Write VAL on STREAM.
!    If SIGN<0, val is the absolute value of a negative number.
!    If SIGN>0, val is a signed non-negative number.
!    If SIGN==0, val is unsigned. */
! 
! static void write_int(ostream& stream, unsigned LONGEST val, int sign)
  {
  #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
      char buf[WRITE_BUF_SIZE];
***************
*** 349,354 ****
--- 354,360 ----
      register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf.
      char *show_base = "";
      int show_base_len = 0;
+     int show_pos = 0; // If 1, print a '+'.
  
      // Now do the actual conversion, placing the result at the *end* of buf.
      // Note that we use separate code for decimal, octal, and hex,
***************
*** 374,379 ****
--- 380,387 ----
  	}
      }
      else { // Decimal
+ 	if (val != 0 && sign > 0 && (stream.flags() & ios::showpos))
+ 	    show_pos=1;
  #ifdef __GNUC__
  	// Optimization:  Only use long long when we need to.
  	while (val > UINT_MAX) {
***************
*** 393,404 ****
  
      int buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
      int w = stream.width(0);
-     int show_pos = 0;
  
      // Calculate padding.
!     int len = buf_len;
!     if (neg) len++;
!     else if (val != 0 && (stream.flags() & ios::showpos)) len++, show_pos=1;
      len += show_base_len;
      int padding = len > w ? 0 : w - len;
  
--- 401,410 ----
  
      int buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
      int w = stream.width(0);
  
      // Calculate padding.
!     int len = buf_len+show_pos;
!     if (sign < 0) len++;
      len += show_base_len;
      int padding = len > w ? 0 : w - len;
  
***************
*** 411,417 ****
  	&& pad_kind != (ios::fmtflags)ios::left
  	&& pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
  	sbuf->padn(fill_char, padding);
!     if (neg) sbuf->sputc('-');
      else if (show_pos) sbuf->sputc('+');
      if (show_base_len)
  	sbuf->sputn(show_base, show_base_len);
--- 417,423 ----
  	&& pad_kind != (ios::fmtflags)ios::left
  	&& pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
  	sbuf->padn(fill_char, padding);
!     if (sign < 0) sbuf->sputc('-');
      else if (show_pos) sbuf->sputc('+');
      if (show_base_len)
  	sbuf->sputn(show_base, show_base_len);
***************
*** 426,435 ****
  ostream& ostream::operator<<(int n)
  {
      if (opfx()) {
! 	int neg = 0;
  	if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
! 	    n = -n, neg = 1;
! 	write_int(*this, n, neg);
      }
      return *this;
  }
--- 432,441 ----
  ostream& ostream::operator<<(int n)
  {
      if (opfx()) {
! 	int sign = 1;
  	if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
! 	    n = -n, sign = -1;
! 	write_int(*this, n, sign);
      }
      return *this;
  }
***************
*** 445,454 ****
  ostream& ostream::operator<<(long n)
  {
      if (opfx()) {
! 	int neg = 0;
  	if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
! 	    n = -n, neg = 1;
! 	write_int(*this, n, neg);
      }
      return *this;
  }
--- 451,460 ----
  ostream& ostream::operator<<(long n)
  {
      if (opfx()) {
! 	int sign = 1;
  	if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
! 	    n = -n, sign = -1;
! 	write_int(*this, n, sign);
      }
      return *this;
  }
***************
*** 464,473 ****
  ostream& ostream::operator<<(long long n)
  {
      if (opfx()) {
! 	int neg = 0;
  	if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
! 	    n = -n, neg = 1;
! 	write_int(*this, n, neg);
      }
      return *this;
  }
--- 470,479 ----
  ostream& ostream::operator<<(long long n)
  {
      if (opfx()) {
! 	int sign = 1;
  	if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
! 	    n = -n, sign = -1;
! 	write_int(*this, n, sign);
      }
      return *this;
  }