Date: Fri, 10 Aug 2001 23:29:40 +0400 From: "Andrey A. Chernov" <ache@nagual.pp.ru> To: arch@freebsd.org Cc: bugs@freebsd.org Subject: CFR: fseek<0 + feof error (with fix) Message-ID: <20010810232939.A14964@nagual.pp.ru>
next in thread | raw e-mail | index | archive | help
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 <stdio.h> 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010810232939.A14964>