| Summary: | fseek(f,o,SEEK_CUR) broken on large files | ||
|---|---|---|---|
| Product: | Base System | Reporter: | kientzle |
| Component: | misc | Assignee: | dt |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 3.1-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
State Changed From-To: open->feedback Could you try with a more recent release of FreeBSD? 3.2-RELEASE has bene out for a while now, and the code you're talking about has changed since 3.2-RELEASE. Responsible Changed From-To: freebsd-bugs->sheldonh Tim's going to try to whip up a small How-To-Repeat program for me, since he's not in a position to test with a more recent version at this time. State Changed From-To: feedback->closed Fixed in rev 1.8 of src/lib/libc/stdio/fseek.c, based on Dan Nelson's patch on PR 8637, and MFC'd. Responsible Changed From-To: sheldonh->dt Dmitrij committed the fix. |
fseek() does not properly handle SEEK_CUR if the resulting file position would exceed 2^31. (Remember that SEEK_CUR and SEEK_END can both be used to seek beyond 2^31 even though fseek only accepts a 32-bit signed long offset.) Fix: fseek() correctly uses 64-bit fpos_t arithmetic to compute the new file offset when converting SEEK_CUR to SEEK_SET, but then assigns the 64-bit result into the 32-bit 'offset' variable. This can be fixed by changing the variable 'offset' to a 64-bit fpos_t type, which in turn requires renaming the actual argument to maintain the ANSI-dictated interface. The three lines marked 'TBKK' below are the necessary changes. /usr/src/lib/libc/stdio/fseek.c: int fseek(fp, offset32, whence) /* TBKK: renamed 'offset' to 'offset32' */ register FILE *fp; long offset32; /* TBKK: renamed 'offset' to 'offset32' */ int whence; { register fpos_t (*seekfn) __P((void *, fpos_t, int)); fpos_t target, curoff; fpos_t offset = offset32; /* TBKK: added 64-bit offset variable */ How-To-Repeat: In a 4gig file, perform: fseek(f,0x7fffffffL, SEEK_SET); fseek(f,0x7fffffffL, SEEK_CUR); /* This seek silently fails */