🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.bugs.4bsd
Article #1412

read returns EINVAL after 2^31 chars

#1412
From: David Steffens
Date: Wed, 10 Jan 1990 19:27
70 lines
2506 bytes
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
Technical Details
Message-ID: <827@eplunix.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!umich!samsung!think!eplunix!das

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!umich!samsung!think!eplunix!das
From: das@eplunix.UUCP (David Steffens)
Newsgroups: comp.bugs.4bsd
Subject: read returns EINVAL after 2^31 chars
Message-ID: <827@eplunix.UUCP>
Date: 10 Jan 90 19:27:11 GMT
Organization: Eaton-Peabody Lab, Boston, MA
Lines: 70