From owner-freebsd-bugs Fri Aug 10 12:29:56 2001 Delivered-To: freebsd-bugs@freebsd.org Received: from nagual.pp.ru (pobrecita.freebsd.ru [194.87.13.42]) by hub.freebsd.org (Postfix) with ESMTP id C8BFA37B406; Fri, 10 Aug 2001 12:29:44 -0700 (PDT) (envelope-from ache@nagual.pp.ru) Received: (from ache@localhost) by nagual.pp.ru (8.11.4/8.11.4) id f7AJTgx15085; Fri, 10 Aug 2001 23:29:42 +0400 (MSD) (envelope-from ache) Date: Fri, 10 Aug 2001 23:29:40 +0400 From: "Andrey A. Chernov" To: arch@freebsd.org Cc: bugs@freebsd.org Subject: CFR: fseek<0 + feof error (with fix) Message-ID: <20010810232939.A14964@nagual.pp.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.19i Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org According to POSIX fseek{o}() description, it must return [EINVAL] The whence argument is invalid. The resulting file-position indicator would be set to a negative value. which expicetly disallows seek beyond beginning of a file. Currently we not implement this. But this situation is worse due to additional feof() bug in that case. Try following program with zero-sized "test" file: #include main() { FILE *f; int i, c; f = fopen("test", "r"); c = fgetc(f); printf("c %d\n", c); printf("feof %d\n", feof(f)); i = fseek(f, -30, 0); printf("fseek %d\n", i); printf("feof %d\n", feof(f)); c = fgetc(f); printf("c %d\n", c); printf("feof %d\n", feof(f)); } Currently it produce following output: c -1 feof 1 fseek 0 (must be -1, per POSIX) feof 0 (if prev. one is 0, can be 0, but must be 1 otherwise) c -1 feof 0 (true bug, must be 1 !!!) I.e. if someone use while (!feof(f)) { c = fgetc(f); ... } loop after occasional negative seek, it loops forever since feof(f) will be always 0 despite the fact that returned c == EOF. I.e. broken fseek() broke feof() too forever (this is real life example from ARC archiver). Here is a patch which fix this situation and makes fseek() POSIXed in some obvious cases like regular files (other types of files require much more work, but partial problem fix for 99% cases is much better than no fix at all). I plan to commit it. Please comment. --- fseek.c.old Fri Aug 10 23:11:10 2001 +++ fseek.c Fri Aug 10 23:07:28 2001 @@ -133,11 +133,19 @@ curoff += fp->_p - fp->_bf._base; offset += curoff; + if (offset < 0) { + errno = EINVAL; + return (EOF); + } whence = SEEK_SET; havepos = 1; break; case SEEK_SET: + if (offset < 0) { + errno = EINVAL; + return (EOF); + } case SEEK_END: curoff = 0; /* XXX just to keep gcc quiet */ havepos = 0; @@ -181,6 +189,10 @@ if (_fstat(fp->_file, &st)) goto dumb; target = st.st_size + offset; + if (target < 0) { + errno = EINVAL; + return (EOF); + } } if (!havepos) { -- Andrey A. Chernov http://ache.pp.ru/ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message