From 0cd9ab77550eada4def492a3a25286ead71a3b24 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky <pfalcon@users.sourceforge.net>
Date: Sun, 20 Aug 2017 21:32:17 +0300
Subject: [PATCH] py/objstringio: Fix regression with handling SEEK_SET.

For SEEK_SET, offset should be treated as unsigned, to allow full-width
stream sizes (e.g. 32-bit instead of 31-bit). This is now fully documented
in stream.h. Also, seek symbolic constants are added.
---
 py/objstringio.c | 8 +++++---
 py/stream.h      | 8 ++++++++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/py/objstringio.c b/py/objstringio.c
index cb8003bcd..61da0203e 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -118,15 +118,17 @@ STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
             struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg;
             mp_uint_t ref = 0;
             switch (s->whence) {
-                case 1: // SEEK_CUR
+                case MP_SEEK_CUR:
                     ref = o->pos;
                     break;
-                case 2: // SEEK_END
+                case MP_SEEK_END:
                     ref = o->vstr->len;
                     break;
             }
             mp_uint_t new_pos = ref + s->offset;
-            if (s->offset < 0) {
+
+            // For MP_SEEK_SET, offset is unsigned
+            if (s->whence != MP_SEEK_SET && s->offset < 0) {
                 if (new_pos > ref) {
                     // Negative offset from SEEK_CUR or SEEK_END went past 0.
                     // CPython sets position to 0, POSIX returns an EINVAL error
diff --git a/py/stream.h b/py/stream.h
index 401ae313c..fbe3d7d85 100644
--- a/py/stream.h
+++ b/py/stream.h
@@ -50,10 +50,18 @@
 
 // Argument structure for MP_STREAM_SEEK
 struct mp_stream_seek_t {
+    // If whence == MP_SEEK_SET, offset should be treated as unsigned.
+    // This allows dealing with full-width stream sizes (16, 32, 64,
+    // etc. bits). For other seek types, should be treated as signed.
     mp_off_t offset;
     int whence;
 };
 
+// seek ioctl "whence" values
+#define MP_SEEK_SET (0)
+#define MP_SEEK_CUR (1)
+#define MP_SEEK_END (2)
+
 MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj);
 MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj);
 MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj);
-- 
GitLab