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

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