From e3383e9352ca7704e650b07038207719c60b56fb Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky <pfalcon@users.sourceforge.net>
Date: Sun, 20 Aug 2017 21:57:36 +0300
Subject: [PATCH] py/stream: seek: Consistently handle negative offset for
 SEEK_SET.

Per POSIX, this is EINVAL, so raises OSError(EINVAL).
---
 py/stream.c                  |  7 ++++++-
 tests/io/bytesio_ext2.py     | 13 +++++++++++++
 tests/io/bytesio_ext2.py.exp |  1 +
 3 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 tests/io/bytesio_ext2.py
 create mode 100644 tests/io/bytesio_ext2.py.exp

diff --git a/py/stream.c b/py/stream.c
index 5d1868153..0029a59a7 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -448,11 +448,16 @@ STATIC mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) {
     struct mp_stream_seek_t seek_s;
     // TODO: Could be uint64
     seek_s.offset = mp_obj_get_int(args[1]);
-    seek_s.whence = 0;
+    seek_s.whence = SEEK_SET;
     if (n_args == 3) {
         seek_s.whence = mp_obj_get_int(args[2]);
     }
 
+    // In POSIX, it's error to seek before end of stream, we enforce it here.
+    if (seek_s.whence == SEEK_SET && seek_s.offset < 0) {
+        mp_raise_OSError(MP_EINVAL);
+    }
+
     int error;
     mp_uint_t res = stream_p->ioctl(args[0], MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error);
     if (res == MP_STREAM_ERROR) {
diff --git a/tests/io/bytesio_ext2.py b/tests/io/bytesio_ext2.py
new file mode 100644
index 000000000..c07ad900c
--- /dev/null
+++ b/tests/io/bytesio_ext2.py
@@ -0,0 +1,13 @@
+try:
+    import uio as io
+except ImportError:
+    import io
+
+a = io.BytesIO(b"foobar")
+try:
+    a.seek(-10)
+except Exception as e:
+    # CPython throws ValueError, but MicroPython has consistent stream
+    # interface, so BytesIO raises the same error as a real file, which
+    # is OSError(EINVAL).
+    print(repr(e))
diff --git a/tests/io/bytesio_ext2.py.exp b/tests/io/bytesio_ext2.py.exp
new file mode 100644
index 000000000..b52e4978a
--- /dev/null
+++ b/tests/io/bytesio_ext2.py.exp
@@ -0,0 +1 @@
+OSError(22,)
-- 
GitLab