diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2013-02-09 13:47:43 +0200 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2013-02-09 13:47:43 +0200 |
commit | 276f1d513917bf47e3a9e333529f6b87302d6aaa (patch) | |
tree | 4cb9795c136552deded33f74dbf743ea02b2c8a5 /Modules/cStringIO.c | |
parent | beaa3adae954a4a85c7dd8e02340d92fd04a7855 (diff) | |
download | cpython-git-276f1d513917bf47e3a9e333529f6b87302d6aaa.tar.gz |
Issue #7358: cStringIO.StringIO now supports writing to and reading from
a stream larger than 2 GiB on 64-bit systems.
Diffstat (limited to 'Modules/cStringIO.c')
-rw-r--r-- | Modules/cStringIO.c | 85 |
1 files changed, 53 insertions, 32 deletions
diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c index a19a31e9d3..9922d03f3a 100644 --- a/Modules/cStringIO.c +++ b/Modules/cStringIO.c @@ -170,10 +170,15 @@ IO_cread(PyObject *self, char **output, Py_ssize_t n) { n = l; if (n < 0) n=0; } + if (n > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "length too large"); + return -1; + } *output=((IOobject*)self)->buf + ((IOobject*)self)->pos; ((IOobject*)self)->pos += n; - return n; + return (int)n; } static PyObject * @@ -192,26 +197,33 @@ PyDoc_STRVAR(IO_readline__doc__, "readline() -- Read one line"); static int IO_creadline(PyObject *self, char **output) { - char *n, *s; - Py_ssize_t l; + char *n, *start, *end; + Py_ssize_t len; if (!IO__opencheck(IOOOBJECT(self))) return -1; - for (n = ((IOobject*)self)->buf + ((IOobject*)self)->pos, - s = ((IOobject*)self)->buf + ((IOobject*)self)->string_size; - n < s && *n != '\n'; n++); + n = start = ((IOobject*)self)->buf + ((IOobject*)self)->pos; + end = ((IOobject*)self)->buf + ((IOobject*)self)->string_size; + while (n < end && *n != '\n') + n++; - if (n < s) n++; + if (n < end) n++; - *output=((IOobject*)self)->buf + ((IOobject*)self)->pos; - l = n - ((IOobject*)self)->buf - ((IOobject*)self)->pos; + len = n - start; + if (len > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "length too large"); + return -1; + } + + *output=start; - assert(IOOOBJECT(self)->pos <= PY_SSIZE_T_MAX - l); + assert(IOOOBJECT(self)->pos <= PY_SSIZE_T_MAX - len); assert(IOOOBJECT(self)->pos >= 0); assert(IOOOBJECT(self)->string_size >= 0); - ((IOobject*)self)->pos += l; - return (int)l; + ((IOobject*)self)->pos += len; + return (int)len; } static PyObject * @@ -239,9 +251,9 @@ IO_readlines(IOobject *self, PyObject *args) { int n; char *output; PyObject *result, *line; - int hint = 0, length = 0; + Py_ssize_t hint = 0, length = 0; - if (!PyArg_ParseTuple(args, "|i:readlines", &hint)) return NULL; + if (!PyArg_ParseTuple(args, "|n:readlines", &hint)) return NULL; result = PyList_New(0); if (!result) @@ -377,31 +389,41 @@ PyDoc_STRVAR(O_write__doc__, static int -O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { - Py_ssize_t newl; +O_cwrite(PyObject *self, const char *c, Py_ssize_t len) { + Py_ssize_t newpos; Oobject *oself; char *newbuf; if (!IO__opencheck(IOOOBJECT(self))) return -1; oself = (Oobject *)self; - newl = oself->pos+l; - if (newl >= oself->buf_size) { - oself->buf_size *= 2; - if (oself->buf_size <= newl) { - assert(newl + 1 < INT_MAX); - oself->buf_size = (int)(newl+1); + if (len > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "length too large"); + return -1; + } + assert(len >= 0); + if (oself->pos >= PY_SSIZE_T_MAX - len) { + PyErr_SetString(PyExc_OverflowError, + "new position too large"); + return -1; + } + newpos = oself->pos + len; + if (newpos >= oself->buf_size) { + size_t newsize = oself->buf_size; + newsize *= 2; + if (newsize <= (size_t)newpos || newsize > PY_SSIZE_T_MAX) { + assert(newpos < PY_SSIZE_T_MAX - 1); + newsize = newpos + 1; } - newbuf = (char*)realloc(oself->buf, oself->buf_size); + newbuf = (char*)realloc(oself->buf, newsize); if (!newbuf) { PyErr_SetString(PyExc_MemoryError,"out of memory"); - free(oself->buf); - oself->buf = 0; - oself->buf_size = oself->pos = 0; return -1; - } + } + oself->buf_size = (Py_ssize_t)newsize; oself->buf = newbuf; - } + } if (oself->string_size < oself->pos) { /* In case of overseek, pad with null bytes the buffer region between @@ -416,16 +438,15 @@ O_cwrite(PyObject *self, const char *c, Py_ssize_t l) { (oself->pos - oself->string_size) * sizeof(char)); } - memcpy(oself->buf+oself->pos,c,l); + memcpy(oself->buf + oself->pos, c, len); - assert(oself->pos + l < INT_MAX); - oself->pos += (int)l; + oself->pos = newpos; if (oself->string_size < oself->pos) { oself->string_size = oself->pos; } - return (int)l; + return (int)len; } static PyObject * |