This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/2074] _IO_new_file_xsputn() in fileops.c not checking for EOF


------- Additional Comments From jfardo at laurelnetworks dot com  2006-08-03 18:54 -------
(In reply to comment #0)
> In glibc 2.3.4, the function new_do_write() in libio/fileops.c returns an 
> unsigned
> value (an _IO_size_t). If the underlying write system call in new_do_write()
> returns EOF (-1), new_do_write() will return 0xffffffff rather than -1.
> The function IO_new_file_xsputn() in libio/fileops.c appears to have
> 2 problems if the call to new_do_write() returns 0xffffffff. Here's
> the specific snippet of code from IO_new_file_xsputn():
>       if (do_write)
>         {
>           count = new_do_write (f, s, do_write);
>           to_do -= count;
>           if (count < do_write)
>             return n - to_do;
>         }
>       /* Now write out the remainder.  Normally, this will fit in the
> 	 buffer, but it's somewhat messier for line-buffered files,
> 	 so we let _IO_default_xsputn handle the general case. */
>       if (to_do)
> 	to_do -= INTUSE(_IO_default_xsputn) (f, s+do_write, to_do);
>     }
>   return n - to_do;
> If new_do_write() returns 0xffffffff, 'to_do' will actually
> be incremented by 1. Also, since 'count' is an unsigned quantity,
> the if statement 'if (count < do_write)' will evaluate to false,
> and the code will incorrectly fall through to the call to
> IO_default_xsputn().

(In reply to comment #3)

_IO_new_file_xsputn() calls new_do_write() which in turn calls _IO_SYSWRITE(). 
The call to _IO_SYSWRITE() may return -1 (EOF). When this happens, new_do_write
() returns this value as the 'count'.

I've highlighted this in the following piece of code in fileops.c.

static
int
new_do_write (fp, data, to_do)
     _IO_FILE *fp;
     const char *data;
     _IO_size_t to_do;
{
  _IO_size_t count;
  if (fp->_flags & _IO_IS_APPENDING)
    /* On a system without a proper O_APPEND implementation,
       you would need to sys_seek(0, SEEK_END) here, but is
       is not needed nor desirable for Unix- or Posix-like systems.
       Instead, just indicate that offset (before and after) is
       unpredictable. */
    fp->_offset = _IO_pos_BAD;
  else if (fp->_IO_read_end != fp->_IO_write_base)
    {
      _IO_off64_t new_pos
	= _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
      if (new_pos == _IO_pos_BAD)
	return 0;
      fp->_offset = new_pos;
    }

********** THIS CALL MAY RETURN -1 ***************
  count = _IO_SYSWRITE (fp, data, to_do);
*************************************************

  if (fp->_cur_column && count)
    fp->_cur_column = INTUSE(_IO_adjust_column) (fp->_cur_column - 1, data,
						 count) + 1;
  _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
  fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
  fp->_IO_write_end = (fp->_mode <= 0
		       && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
		       ? fp->_IO_buf_base : fp->_IO_buf_end);
  return count;
}



-- 


http://sourceware.org/bugzilla/show_bug.cgi?id=2074

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]