diff options
author | 6t8k <58048945+6t8k@users.noreply.github.com> | 2024-02-17 11:16:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-17 11:16:06 (GMT) |
commit | 26800cf25a0970d46934fa9a881c0ef6881d642b (patch) | |
tree | 94787f4406c4ab79490877d58612437787fd2068 /Modules/_io | |
parent | d5a30a1777f04523c7b151b894e999f5714d8e96 (diff) | |
download | cpython-26800cf25a0970d46934fa9a881c0ef6881d642b.zip cpython-26800cf25a0970d46934fa9a881c0ef6881d642b.tar.gz cpython-26800cf25a0970d46934fa9a881c0ef6881d642b.tar.bz2 |
gh-95782: Fix io.BufferedReader.tell() etc. being able to return offsets < 0 (GH-99709)
lseek() always returns 0 for character pseudo-devices like
`/dev/urandom` (for other non-regular files, e.g. `/dev/stdin`, it
always returns -1, to which CPython reacts by raising appropriate
exceptions). They are thus technically seekable despite not having seek
semantics.
When calling read() on e.g. an instance of `io.BufferedReader` that
wraps such a file, `BufferedReader` reads ahead, filling its buffer,
creating a discrepancy between the number of bytes read and the internal
`tell()` always returning 0, which previously resulted in e.g.
`BufferedReader.tell()` or `BufferedReader.seek()` being able to return
positions < 0 even though these are supposed to be always >= 0.
Invariably keep the return value non-negative by returning
max(former_return_value, 0) instead, and add some corresponding tests.
Diffstat (limited to 'Modules/_io')
-rw-r--r-- | Modules/_io/bufferedio.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 8ebe9ec..b3450ee 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1325,7 +1325,11 @@ _io__Buffered_tell_impl(buffered *self) if (pos == -1) return NULL; pos -= RAW_OFFSET(self); - /* TODO: sanity check (pos >= 0) */ + + // GH-95782 + if (pos < 0) + pos = 0; + return PyLong_FromOff_t(pos); } @@ -1395,6 +1399,11 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) offset = target; if (offset >= -self->pos && offset <= avail) { self->pos += offset; + + // GH-95782 + if (current - avail + offset < 0) + return PyLong_FromOff_t(0); + return PyLong_FromOff_t(current - avail + offset); } } |