Opened 16 years ago
Closed 14 years ago
#3145 closed bug (fixed)
fseek does not discard ungetc buffer
Reported by: | bhaible | Owned by: | zooey |
---|---|---|---|
Priority: | normal | Milestone: | R1 |
Component: | System/libroot.so | Version: | R1/pre-alpha1 |
Keywords: | Cc: | haiku@… | |
Blocked By: | Blocking: | ||
Platform: | All |
Description
ISO C 99 section 7.19.9.2 specifies that "a successful call to the fseek function undoes any effects of the ungetc function on the stream". Same in POSIX, see
Attached is a test case showing that this is not fulfilled in Haiku.
Attachments (5)
Change History (15)
by , 16 years ago
Attachment: | fseek-bug.c added |
---|
by , 16 years ago
Attachment: | haiku-fseek-ftell-bug.png added |
---|
screenshot of execution of the second test case
comment:1 by , 16 years ago
Perhaps a newer fseek has fixed this? http://svn.freebsd.org/viewvc/base/head/lib/libc/stdio/fseek.c?view=log
comment:2 by , 15 years ago
Cc: | added |
---|
follow-up: 5 comment:3 by , 14 years ago
patch: | 0 → 1 |
---|
With these changes, both tests work fine. I observed no repercussions elsewhere, but more testing is recommended.
comment:4 by , 14 years ago
Owner: | changed from | to
---|---|
Status: | new → in-progress |
comment:5 by , 14 years ago
Replying to hamish:
With these changes, both tests work fine. I observed no repercussions elsewhere, but more testing is recommended.
Hm, is there some reasoning behind this patch, or did you get there by trial and error?
Please elaborate, as I don't quite understand the patch.
follow-up: 7 comment:6 by , 14 years ago
_IO_buf_base points to the start of the entire stream buffer, while _IO_read_base points to the start of the read part of the stream buffer. ungetc() and friends store characters in the bytes between _IO_buf_base and _IO_read_base, so the seek function must take these into account and skip them.
comment:7 by , 14 years ago
Replying to hamish:
_IO_buf_base points to the start of the entire stream buffer, while _IO_read_base points to the start of the read part of the stream buffer. ungetc() and friends store characters in the bytes between _IO_buf_base and _IO_read_base, so the seek function must take these into account and skip them.
Not quite, no: ungetc() invokes _IO_sputbackc(), which puts back characters between _IO_read_ptr and _IO_read_base - _IO_buf_base doesn't play any role there.
That's why I still fail to understand what exactly your patch does that causes the good effect. More importantly, I'm not at all sure it doesn't actually break other use cases. Have you tried running all gnulib tests to see if applying your patch doesn't introduce new problems?
comment:8 by , 14 years ago
I got tst-fseek.c from the latest glibc. After disabling all the stats-related tests (stat64 stuff missing), one fread test fails. Without my patch, four fseek tests also fail.
Yes, I was wrong about why it worked. I think I've figured it out now.
The main read area starts at _IO_buf_base (see _IO_switch_to_get_mode). The put-back read area actually exists elsewhere in memory and isn't contiguous with the main read area. When the two areas are switched between, _IO_read_base is moved. After an ungetc(), _IO_read_base points to the put-back area, so any subsequent call to fseek() seeks in there, which it shouldn't.
Given that fseek() should ignore put-back characters, it makes sense to seek relative to the position of the normal read buffer, which is _IO_buf_base.
comment:9 by , 14 years ago
The proposed patch indeed fixes the problem and I have been unable to find any negative side effects.
Applied in hrev40055 - thanks a lot!
comment:10 by , 14 years ago
Resolution: | → fixed |
---|---|
Status: | in-progress → closed |
test case