Blame SOURCES/00236-use-Py_ssize_t-for-file-offset-and-length-computations-in-iteration.patch

04a680
From 6bebd55022c82829c0b15d24d2ca99edd22562df Mon Sep 17 00:00:00 2001
04a680
From: Charalampos Stratakis <cstratak@redhat.com>
04a680
Date: Wed, 4 May 2016 10:39:40 +0200
04a680
Subject: [PATCH] use Py_ssize_t for file offset and length computations in
04a680
 iteration
04a680
04a680
---
04a680
 Lib/test/test_file2k.py | 16 +++++++++++++++-
04a680
 Objects/fileobject.c    | 15 +++++++--------
04a680
 2 files changed, 22 insertions(+), 9 deletions(-)
04a680
04a680
diff --git a/Lib/test/test_file2k.py b/Lib/test/test_file2k.py
04a680
index 5a3c354..8f94cee 100644
04a680
--- a/Lib/test/test_file2k.py
04a680
+++ b/Lib/test/test_file2k.py
04a680
@@ -14,7 +14,7 @@ except ImportError:
04a680
     threading = None
04a680
04a680
 from test import test_support
04a680
-from test.test_support import TESTFN, run_unittest
04a680
+from test.test_support import TESTFN, run_unittest, requires
04a680
 from UserList import UserList
04a680
04a680
 class AutoFileTests(unittest.TestCase):
04a680
@@ -416,6 +416,20 @@ class OtherFileTests(unittest.TestCase):
04a680
         finally:
04a680
             os.unlink(TESTFN)
04a680
04a680
+    @test_support.precisionbigmemtest(2**31, 2.5, dry_run=False)
04a680
+    def test_very_long_line(self, size):
04a680
+        # Issue #22526
04a680
+        requires('largefile')
04a680
+        with open(TESTFN, "wb") as fp:
04a680
+            fp.seek(size - 1)
04a680
+            fp.write("\0")
04a680
+            with open(TESTFN, "rb") as fp:
04a680
+                for l in fp:
04a680
+                    pass
04a680
+            self.assertEqual(len(l), size)
04a680
+            self.assertEqual(l.count("\0"), size)
04a680
+            l = None
04a680
+
04a680
 class FileSubclassTests(unittest.TestCase):
04a680
04a680
     def testExit(self):
04a680
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
04a680
index 76cdf74..fabe207 100644
04a680
--- a/Objects/fileobject.c
04a680
+++ b/Objects/fileobject.c
04a680
@@ -2230,7 +2230,7 @@ drop_readahead(PyFileObject *f)
04a680
    (unless at EOF) and no more than bufsize.  Returns negative value on
04a680
    error, will set MemoryError if bufsize bytes cannot be allocated. */
04a680
 static int
04a680
-readahead(PyFileObject *f, int bufsize)
04a680
+readahead(PyFileObject *f, Py_ssize_t bufsize)
04a680
 {
04a680
     Py_ssize_t chunksize;
04a680
04a680
@@ -2268,7 +2268,7 @@ readahead(PyFileObject *f, int bufsize)
04a680
    logarithmic buffer growth to about 50 even when reading a 1gb line. */
04a680
04a680
 static PyStringObject *
04a680
-readahead_get_line_skip(PyFileObject *f, int skip, int bufsize)
04a680
+readahead_get_line_skip(PyFileObject *f, Py_ssize_t skip, Py_ssize_t bufsize)
04a680
 {
04a680
     PyStringObject* s;
04a680
     char *bufptr;
04a680
@@ -2288,10 +2288,10 @@ readahead_get_line_skip(PyFileObject *f, int skip, int bufsize)
04a680
         bufptr++;                               /* Count the '\n' */
04a680
         len = bufptr - f->f_bufptr;
04a680
         s = (PyStringObject *)
04a680
-            PyString_FromStringAndSize(NULL, skip+len);
04a680
+            PyString_FromStringAndSize(NULL, skip + len);
04a680
         if (s == NULL)
04a680
             return NULL;
04a680
-        memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
04a680
+        memcpy(PyString_AS_STRING(s) + skip, f->f_bufptr, len);
04a680
         f->f_bufptr = bufptr;
04a680
         if (bufptr == f->f_bufend)
04a680
             drop_readahead(f);
04a680
@@ -2299,14 +2299,13 @@ readahead_get_line_skip(PyFileObject *f, int skip, int bufsize)
04a680
         bufptr = f->f_bufptr;
04a680
         buf = f->f_buf;
04a680
         f->f_buf = NULL;                /* Force new readahead buffer */
04a680
-        assert(skip+len < INT_MAX);
04a680
-        s = readahead_get_line_skip(
04a680
-            f, (int)(skip+len), bufsize + (bufsize>>2) );
04a680
+        assert(len <= PY_SSIZE_T_MAX - skip);
04a680
+        s = readahead_get_line_skip(f, skip + len, bufsize + (bufsize>>2));
04a680
         if (s == NULL) {
04a680
             PyMem_Free(buf);
04a680
             return NULL;
04a680
         }
04a680
-        memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
04a680
+        memcpy(PyString_AS_STRING(s) + skip, bufptr, len);
04a680
         PyMem_Free(buf);
04a680
     }
04a680
     return s;
04a680
--
04a680
2.5.5
04a680