🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.g++.lib.bug
Article #450

Re: 2.3: width(x) off by 1 for istreams

#450
From: bothner
Date: Thu, 21 Jan 1993 23:22
186 lines
5645 bytes
> 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;
  }
Technical Details
Message-ID: <9301212244.AA18937@cygnus.com>
Path: arc1-ca.pugleaf.net!sparky!uunet!paladin.american.edu!howland.reston.ans.net!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!cis.ohio-state.edu!cygnus.com!bothner
References: <9301201947.AA01121@cs.rice.edu>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!paladin.american.edu!howland.reston.ans.net!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!cis.ohio-state.edu!cygnus.com!bothner
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
Lines: 187
Sender: daemon@cis.ohio-state.edu
Approved: bug-lib-g++@prep.ai.mit.edu
Distribution: gnu
Message-ID: <9301212244.AA18937@cygnus.com>
References: <9301201947.AA01121@cs.rice.edu>