Bug 16605

Summary: Invalid caching of file position in stdio streams
Product: glibc Reporter: Rich Felker <bugdal>
Component: stdioAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: siddhesh
Priority: P2 Flags: fweimer: security-
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Rich Felker 2014-02-19 05:46:58 UTC
Test case:

#include <stdio.h>
#include <unistd.h>

int main()
{
    FILE *f = tmpfile();
    printf("%ld\n", ftell(f));
    write(fileno(f), "abc", 3);
    printf("%ld\n", ftell(f));
}

Expected output:
0
3

glibc output:
0
0

The issue is that glibc is wrongly caching the file position when it does not have any guarantee that the stdio FILE stream is or will remain the "active handle" for the open file description (see POSIX XSH 2.5.1 Interaction of File Descriptors and Standard I/O Streams). While the exact semantics for active handle are complex (read the cited text), the basic situation is that you can only guarantee that the FILE remains the active handle once you've started reading from or writing to it, and up until an operation that allows the application to switch to a different active handle (a successful seek, explicit flush, newline-caused flush on line-buffered stream, reaching eof reading, etc.).

Note that the test case above only shows the issue for writing, but as far as I can tell it applies equally to reading, and applies to all possible open modes (read/write/update/append/etc.). I used tmpfile() for convenience but the same should work with fopen or fdopen.
Comment 1 Rich Felker 2014-02-19 06:01:01 UTC
One thing I misstated: a successful seek does not permit changing the active handle, so it seems to be valid to keep the cached offset across fseek/fseeko calls.
Comment 2 Siddhesh Poyarekar 2014-02-21 04:43:03 UTC
As discussed on list, this is a variant of bug 16532.

*** This bug has been marked as a duplicate of bug 16532 ***