[comp.bugs.4bsd] read returns EINVAL after 2^31 chars

das@eplunix.UUCP (David Steffens) (01/11/90)

Subject:
	Read/write return EINVAL after 2^31 chars have been read/written.

File:
	sys/sys_inode.c

Repeat-by:
	Try to read more than 2^31 characters from a character device.
	See read return EINVAL.  Fails with write, too.
	You may prefer inspection -- takes a few hours, even on a Sun4!

Discussion:
	This bug was first discovered in a SunOS4.0.3 binary
	and traced back to the 4.3bsd (and 4.2bsd) sources.
	It appears to have been introduced by a too-hasty
	translation of imprecise English logic into C.

	What seems to have been expressed in English was:
		IF the offset is negative AND
		it isn't a character device OR
		it isn't the memory device
		THEN return EINVAL.

	Unfortunately, when this was coded it became:
		IF the offset is negative AND EITHER
		NOT a character device OR
		NOT the memory device
		THEN return EINVAL.

	This causes EINVAL to be returned for EVERY character device
	EXCEPT the memory device.

	Seems to me what really should have been expressed (and coded) was:
		IF the offset is negative AND NEITHER
		a character device NOR
		the memory device
		THEN return EINVAL.

Fix:
*** sys/sys_inode.c0	Thu Jun  5 03:08:12 1986
--- sys/sys_inode.c	Wed Jan 10 14:18:55 1990
***************
*** 94,101 ****
  		panic("rwip");
  	if (rw == UIO_READ && uio->uio_resid == 0)
  		return (0);
  	if (uio->uio_offset < 0 &&
! 	    ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
  		return (EINVAL);
  	if (rw == UIO_READ)
  		ip->i_flag |= IACC;
--- 94,107 ----
  		panic("rwip");
  	if (rw == UIO_READ && uio->uio_resid == 0)
  		return (0);
+ /*
+  * The following is the correct logic:
+  *	if (uio->uio_offset < 0 &&
+  *	    !((ip->i_mode&IFMT) == IFCHR || major(dev) == mem_no))
+  * DeMorgan's therorem can be used to get a simpler expression, however.
+  */
  	if (uio->uio_offset < 0 &&
! 	    (ip->i_mode&IFMT) != IFCHR && major(dev) != mem_no)
  		return (EINVAL);
  	if (rw == UIO_READ)
  		ip->i_flag |= IACC;
-- 
{harvard,mit-eddie,think}!eplunix!das	David Allan Steffens
243 Charles St., Boston, MA 02114	Eaton-Peabody Laboratory
(617) 573-3748				Mass. Eye & Ear Infirmary