bin/127335: fwrite fails to generate error when applied to a
read-only file
Ronald F.Guilmette
rfg at tristatelogic.com
Fri Sep 12 22:10:04 UTC 2008
>Number: 127335
>Category: bin
>Synopsis: fwrite fails to generate error when applied to a read-only file
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Sep 12 22:10:04 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator: Ronald F. Guilmette
>Release: FreeBSD 7.0-RELEASE i386
>Organization:
Infinite Monkeys & Co. LLC
>Environment:
System: FreeBSD segfault.tristatelogic.com 7.0-RELEASE FreeBSD 7.0-RELEASE #0: Tue Aug 5 02:38:40 PDT 2008 root at segfault.monkeys.com:/usr/src/sys/i386/compile/rfg20080805 i386
>Description:
It the fwrite() stdio library function is called and passed a file
which has been opened read-only, then a return value of zero will
be generated, but the error flag for the file will NOT be properly
set. This affects subsequent calls to ferror(file) where `file'
was the read-only file upon which an incorrect attempt was made to
write.
The failure of fwrite() to properly set the error flag for the file
causes fwrite() to arguably violate its own documentation. The
relevant quote from the man page is as follows:
The function fwrite() returns a value less than nmemb only
if a write error has occurred.
Zero is returned, and a write error _does_ occur when fwrite is asked
to write to a read-only file, but subsequent calls to ferror() do not
properly reflect that fact.
>How-To-Repeat:
Consider the two trivial programs below which test the effects of
passing the Wrong Type of file to fread() and fwrite() respectively.
The first one correctly prints "Error reading from stdout", but the
second one prints "This shouldn't happen!" because of the failure
to properly set the file's error flag when fwrite() is called on a
read-only file.
Prog #1:
=====================================================================
#include <stdio.h>
int
main (void)
{
char buf[1024];
fread (buf, 1, 12, stdout);
if (ferror (stdout))
printf ("Error reading from stdout\n");
else if (feof (stdout))
printf ("EOF detected while reading from stdout\n");
else
printf ("This shouldn't happen!\n");
return 0;
}
=====================================================================
Prog #2:
=====================================================================
#include <stdio.h>
int
main (void)
{
fwrite ("Hello world!", 1, 12, stdin);
if (ferror (stdin))
printf ("Error writing to stdin\n");
else if (feof (stdin))
printf ("EOF detected while writing to stdin\n");
else
printf ("This shouldn't happen!\n");
return 0;
}
=====================================================================
>Fix:
I don't know for sure how to fix this, but I do know it ought to be
pretty trivial to do. I looked at the relevant stdio library code
for awhile, but some of these macros are just too too ugly to even
make sense of. I suspect that the problem is either in the definition
of the macro "prepwrite(fp)" in /usr/src/lib/libc/stdio/local.h or
else it is in the function called __swsetup(fp).
The comment just before the definition of the prepwrite() macro sez:
/*
* Prepare the given FILE for writing, and return 0 iff it
* can be written now. Otherwise, return EOF and set errno.
*/
Well, apparently, it doesn't actually set errno when it should, let
alone the file's error flag.
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list