Commit 6d833302 authored by Tim Peters's avatar Tim Peters

Repair widespread misuse of _PyString_Resize. Since it's clear people

don't understand how this function works, also beefed up the docs.  The
most common usage error is of this form (often spread out across gotos):

	if (_PyString_Resize(&s, n) < 0) {
		Py_DECREF(s);
		s = NULL;
		goto outtahere;
	}

The error is that if _PyString_Resize runs out of memory, it automatically
decrefs the input string object s (which also deallocates it, since its
refcount must be 1 upon entry), and sets s to NULL.  So if the "if"
branch ever triggers, it's an error to call Py_DECREF(s):  s is already
NULL!  A correct way to write the above is the simpler (and intended)

	if (_PyString_Resize(&s, n) < 0)
		goto outtahere;

Bugfix candidate.
parent 679e04b0
...@@ -586,7 +586,16 @@ parameter and are called with a non-string parameter. ...@@ -586,7 +586,16 @@ parameter and are called with a non-string parameter.
\begin{cfuncdesc}{int}{_PyString_Resize}{PyObject **string, int newsize} \begin{cfuncdesc}{int}{_PyString_Resize}{PyObject **string, int newsize}
A way to resize a string object even though it is ``immutable''. A way to resize a string object even though it is ``immutable''.
Only use this to build up a brand new string object; don't use this Only use this to build up a brand new string object; don't use this
if the string may already be known in other parts of the code. if the string may already be known in other parts of the code. It
is an error to call this function if the refcount on the input string
object is not one.
Pass the address of an existing string object as an lvalue (it may
be written into), and the new size desired. On success, \var{*string}
holds the resized string object and 0 is returned; the address in
\var{*string} may differ from its input value. If the
reallocation fails, the original string object at \var{*string} is
deallocated, \var{*string} is set to \NULL{}, a memory exception is set,
and -1 is returned.
\end{cfuncdesc} \end{cfuncdesc}
\begin{cfuncdesc}{PyObject*}{PyString_Format}{PyObject *format, \begin{cfuncdesc}{PyObject*}{PyString_Format}{PyObject *format,
......
...@@ -331,8 +331,8 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args) ...@@ -331,8 +331,8 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
Py_DECREF(buf); Py_DECREF(buf);
return PySSL_SetError(self, count); return PySSL_SetError(self, count);
} }
if (count != len && _PyString_Resize(&buf, count) < 0) if (count != len)
return NULL; _PyString_Resize(&buf, count);
return buf; return buf;
} }
......
...@@ -1252,14 +1252,8 @@ modified_EncodeRawUnicodeEscape(const Py_UNICODE *s, int size) ...@@ -1252,14 +1252,8 @@ modified_EncodeRawUnicodeEscape(const Py_UNICODE *s, int size)
*p++ = (char) ch; *p++ = (char) ch;
} }
*p = '\0'; *p = '\0';
if (_PyString_Resize(&repr, p - q)) _PyString_Resize(&repr, p - q);
goto onError;
return repr; return repr;
onError:
Py_DECREF(repr);
return NULL;
} }
......
...@@ -251,8 +251,7 @@ CD_readda(cdplayerobject *self, PyObject *args) ...@@ -251,8 +251,7 @@ CD_readda(cdplayerobject *self, PyObject *args)
return NULL; return NULL;
} }
if (n < numframes) if (n < numframes)
if (_PyString_Resize(&result, n * sizeof(CDFRAME))) _PyString_Resize(&result, n * sizeof(CDFRAME));
return NULL;
return result; return result;
} }
......
...@@ -135,8 +135,7 @@ cl_CompressImage(PyObject *self, PyObject *args) ...@@ -135,8 +135,7 @@ cl_CompressImage(PyObject *self, PyObject *args)
} }
if (compressedBufferSize < frameBufferSize) if (compressedBufferSize < frameBufferSize)
if (_PyString_Resize(&compressedBuffer, compressedBufferSize)) _PyString_Resize(&compressedBuffer, compressedBufferSize);
return NULL;
return compressedBuffer; return compressedBuffer;
} }
......
...@@ -158,8 +158,7 @@ lad_read(lad_t *self, PyObject *args) ...@@ -158,8 +158,7 @@ lad_read(lad_t *self, PyObject *args)
return NULL; return NULL;
} }
self->x_icount += count; self->x_icount += count;
if (_PyString_Resize(&rv, count) == -1) _PyString_Resize(&rv, count);
return NULL;
return rv; return rv;
} }
......
...@@ -516,11 +516,8 @@ symcomp(PyObject *pattern, PyObject *gdict) ...@@ -516,11 +516,8 @@ symcomp(PyObject *pattern, PyObject *gdict)
return NULL; return NULL;
} }
/* _PyString_Resize() decrements npattern on failure */ /* _PyString_Resize() decrements npattern on failure */
if (_PyString_Resize(&npattern, n - v) == 0) _PyString_Resize(&npattern, n - v);
return npattern; return npattern;
else {
return NULL;
}
} }
......
...@@ -1402,8 +1402,8 @@ PySocketSock_recv(PySocketSockObject *s, PyObject *args) ...@@ -1402,8 +1402,8 @@ PySocketSock_recv(PySocketSockObject *s, PyObject *args)
Py_DECREF(buf); Py_DECREF(buf);
return s->errorhandler(); return s->errorhandler();
} }
if (n != len && _PyString_Resize(&buf, n) < 0) if (n != len)
return NULL; _PyString_Resize(&buf, n);
return buf; return buf;
} }
......
...@@ -215,10 +215,8 @@ strop_joinfields(PyObject *self, PyObject *args) ...@@ -215,10 +215,8 @@ strop_joinfields(PyObject *self, PyObject *args)
} }
slen = PyString_GET_SIZE(item); slen = PyString_GET_SIZE(item);
while (reslen + slen + seplen >= sz) { while (reslen + slen + seplen >= sz) {
if (_PyString_Resize(&res, sz * 2)) { if (_PyString_Resize(&res, sz * 2) < 0)
Py_DECREF(res);
return NULL; return NULL;
}
sz *= 2; sz *= 2;
p = PyString_AsString(res) + reslen; p = PyString_AsString(res) + reslen;
} }
...@@ -231,10 +229,7 @@ strop_joinfields(PyObject *self, PyObject *args) ...@@ -231,10 +229,7 @@ strop_joinfields(PyObject *self, PyObject *args)
p += slen; p += slen;
reslen += slen; reslen += slen;
} }
if (_PyString_Resize(&res, reslen)) { _PyString_Resize(&res, reslen);
Py_DECREF(res);
res = NULL;
}
return res; return res;
} }
...@@ -257,8 +252,7 @@ strop_joinfields(PyObject *self, PyObject *args) ...@@ -257,8 +252,7 @@ strop_joinfields(PyObject *self, PyObject *args)
} }
slen = PyString_GET_SIZE(item); slen = PyString_GET_SIZE(item);
while (reslen + slen + seplen >= sz) { while (reslen + slen + seplen >= sz) {
if (_PyString_Resize(&res, sz * 2)) { if (_PyString_Resize(&res, sz * 2) < 0) {
Py_DECREF(res);
Py_DECREF(item); Py_DECREF(item);
return NULL; return NULL;
} }
...@@ -275,10 +269,7 @@ strop_joinfields(PyObject *self, PyObject *args) ...@@ -275,10 +269,7 @@ strop_joinfields(PyObject *self, PyObject *args)
reslen += slen; reslen += slen;
Py_DECREF(item); Py_DECREF(item);
} }
if (_PyString_Resize(&res, reslen)) { _PyString_Resize(&res, reslen);
Py_DECREF(res);
res = NULL;
}
return res; return res;
} }
...@@ -989,8 +980,8 @@ strop_translate(PyObject *self, PyObject *args) ...@@ -989,8 +980,8 @@ strop_translate(PyObject *self, PyObject *args)
return input_obj; return input_obj;
} }
/* Fix the size of the resulting string */ /* Fix the size of the resulting string */
if (inlen > 0 &&_PyString_Resize(&result, output-output_start)) if (inlen > 0)
return NULL; _PyString_Resize(&result, output - output_start);
return result; return result;
} }
......
...@@ -255,9 +255,8 @@ PyZlib_decompress(PyObject *self, PyObject *args) ...@@ -255,9 +255,8 @@ PyZlib_decompress(PyObject *self, PyObject *args)
/* fall through */ /* fall through */
case(Z_OK): case(Z_OK):
/* need more memory */ /* need more memory */
if (_PyString_Resize(&result_str, r_strlen << 1) == -1) { if (_PyString_Resize(&result_str, r_strlen << 1) < 0) {
inflateEnd(&zst); inflateEnd(&zst);
result_str = NULL;
goto error; goto error;
} }
zst.next_out = (unsigned char *)PyString_AS_STRING(result_str) \ zst.next_out = (unsigned char *)PyString_AS_STRING(result_str) \
...@@ -414,10 +413,8 @@ PyZlib_objcompress(compobject *self, PyObject *args) ...@@ -414,10 +413,8 @@ PyZlib_objcompress(compobject *self, PyObject *args)
/* while Z_OK and the output buffer is full, there might be more output, /* while Z_OK and the output buffer is full, there might be more output,
so extend the output buffer and try again */ so extend the output buffer and try again */
while (err == Z_OK && self->zst.avail_out == 0) { while (err == Z_OK && self->zst.avail_out == 0) {
if (_PyString_Resize(&RetVal, length << 1) == -1) { if (_PyString_Resize(&RetVal, length << 1) < 0)
RetVal = NULL;
goto error; goto error;
}
self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \ self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \
+ length; + length;
self->zst.avail_out = length; self->zst.avail_out = length;
...@@ -438,9 +435,7 @@ PyZlib_objcompress(compobject *self, PyObject *args) ...@@ -438,9 +435,7 @@ PyZlib_objcompress(compobject *self, PyObject *args)
RetVal = NULL; RetVal = NULL;
goto error; goto error;
} }
if (_PyString_Resize(&RetVal, _PyString_Resize(&RetVal, self->zst.total_out - start_total_out);
self->zst.total_out - start_total_out) < 0)
RetVal = NULL;
error: error:
LEAVE_ZLIB LEAVE_ZLIB
...@@ -510,10 +505,8 @@ PyZlib_objdecompress(compobject *self, PyObject *args) ...@@ -510,10 +505,8 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
if (max_length && length > max_length) if (max_length && length > max_length)
length = max_length; length = max_length;
if (_PyString_Resize(&RetVal, length) == -1) { if (_PyString_Resize(&RetVal, length) < 0)
RetVal = NULL;
goto error; goto error;
}
self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \ self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \
+ old_length; + old_length;
self->zst.avail_out = length - old_length; self->zst.avail_out = length - old_length;
...@@ -561,8 +554,7 @@ PyZlib_objdecompress(compobject *self, PyObject *args) ...@@ -561,8 +554,7 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
goto error; goto error;
} }
if (_PyString_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) _PyString_Resize(&RetVal, self->zst.total_out - start_total_out);
RetVal = NULL;
error: error:
LEAVE_ZLIB LEAVE_ZLIB
...@@ -612,10 +604,8 @@ PyZlib_flush(compobject *self, PyObject *args) ...@@ -612,10 +604,8 @@ PyZlib_flush(compobject *self, PyObject *args)
/* while Z_OK and the output buffer is full, there might be more output, /* while Z_OK and the output buffer is full, there might be more output,
so extend the output buffer and try again */ so extend the output buffer and try again */
while (err == Z_OK && self->zst.avail_out == 0) { while (err == Z_OK && self->zst.avail_out == 0) {
if (_PyString_Resize(&RetVal, length << 1) == -1) { if (_PyString_Resize(&RetVal, length << 1) < 0)
RetVal = NULL;
goto error; goto error;
}
self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \ self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \
+ length; + length;
self->zst.avail_out = length; self->zst.avail_out = length;
...@@ -651,8 +641,7 @@ PyZlib_flush(compobject *self, PyObject *args) ...@@ -651,8 +641,7 @@ PyZlib_flush(compobject *self, PyObject *args)
goto error; goto error;
} }
if (_PyString_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) _PyString_Resize(&RetVal, self->zst.total_out - start_total_out);
RetVal = NULL;
error: error:
LEAVE_ZLIB LEAVE_ZLIB
......
...@@ -1317,9 +1317,7 @@ file_readlines(PyFileObject *f, PyObject *args) ...@@ -1317,9 +1317,7 @@ file_readlines(PyFileObject *f, PyObject *args)
goto error; goto error;
} }
cleanup: cleanup:
if (big_buffer) { Py_XDECREF(big_buffer);
Py_DECREF(big_buffer);
}
return list; return list;
} }
......
...@@ -1869,8 +1869,8 @@ string_translate(PyStringObject *self, PyObject *args) ...@@ -1869,8 +1869,8 @@ string_translate(PyStringObject *self, PyObject *args)
return input_obj; return input_obj;
} }
/* Fix the size of the resulting string */ /* Fix the size of the resulting string */
if (inlen > 0 &&_PyString_Resize(&result, output-output_start)) if (inlen > 0)
return NULL; _PyString_Resize(&result, output - output_start);
return result; return result;
} }
...@@ -2927,7 +2927,14 @@ PyString_ConcatAndDel(register PyObject **pv, register PyObject *w) ...@@ -2927,7 +2927,14 @@ PyString_ConcatAndDel(register PyObject **pv, register PyObject *w)
is only one module referencing the object. You can also think of it is only one module referencing the object. You can also think of it
as creating a new string object and destroying the old one, only as creating a new string object and destroying the old one, only
more efficiently. In any case, don't use this if the string may more efficiently. In any case, don't use this if the string may
already be known to some other part of the code... */ already be known to some other part of the code...
Note that if there's not enough memory to resize the string, the original
string object at *pv is deallocated, *pv is set to NULL, an "out of
memory" exception is set, and -1 is returned. Else (on success) 0 is
returned, and the value in *pv may or may not be the same as on input.
As always, an extra byte is allocated for a trailing \0 byte (newsize
does *not* include that), and a trailing \0 byte is stored.
*/
int int
_PyString_Resize(PyObject **pv, int newsize) _PyString_Resize(PyObject **pv, int newsize)
......
...@@ -927,10 +927,7 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s, ...@@ -927,10 +927,7 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s,
*out++ = '-'; *out++ = '-';
} }
if (_PyString_Resize(&v, out - start)) { _PyString_Resize(&v, out - start);
Py_DECREF(v);
return NULL;
}
return v; return v;
} }
...@@ -1764,7 +1761,7 @@ PyObject *unicodeescape_string(const Py_UNICODE *s, ...@@ -1764,7 +1761,7 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
/* Resize the string if necessary */ /* Resize the string if necessary */
if (offset + 12 > PyString_GET_SIZE(repr)) { if (offset + 12 > PyString_GET_SIZE(repr)) {
if (_PyString_Resize(&repr, PyString_GET_SIZE(repr) + 100)) if (_PyString_Resize(&repr, PyString_GET_SIZE(repr) + 100))
goto onError; return NULL;
p = PyString_AS_STRING(repr) + offset; p = PyString_AS_STRING(repr) + offset;
} }
...@@ -1847,14 +1844,8 @@ PyObject *unicodeescape_string(const Py_UNICODE *s, ...@@ -1847,14 +1844,8 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
*p++ = PyString_AS_STRING(repr)[1]; *p++ = PyString_AS_STRING(repr)[1];
*p = '\0'; *p = '\0';
if (_PyString_Resize(&repr, p - PyString_AS_STRING(repr))) _PyString_Resize(&repr, p - PyString_AS_STRING(repr));
goto onError;
return repr; return repr;
onError:
Py_DECREF(repr);
return NULL;
} }
PyObject *PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s, PyObject *PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s,
...@@ -1985,14 +1976,8 @@ PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s, ...@@ -1985,14 +1976,8 @@ PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s,
*p++ = (char) ch; *p++ = (char) ch;
} }
*p = '\0'; *p = '\0';
if (_PyString_Resize(&repr, p - q)) _PyString_Resize(&repr, p - q);
goto onError;
return repr; return repr;
onError:
Py_DECREF(repr);
return NULL;
} }
PyObject *PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode) PyObject *PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)
...@@ -2092,8 +2077,7 @@ PyObject *PyUnicode_EncodeLatin1(const Py_UNICODE *p, ...@@ -2092,8 +2077,7 @@ PyObject *PyUnicode_EncodeLatin1(const Py_UNICODE *p,
} }
/* Resize if error handling skipped some characters */ /* Resize if error handling skipped some characters */
if (s - start < PyString_GET_SIZE(repr)) if (s - start < PyString_GET_SIZE(repr))
if (_PyString_Resize(&repr, s - start)) _PyString_Resize(&repr, s - start);
goto onError;
return repr; return repr;
onError: onError:
...@@ -2240,8 +2224,7 @@ PyObject *PyUnicode_EncodeASCII(const Py_UNICODE *p, ...@@ -2240,8 +2224,7 @@ PyObject *PyUnicode_EncodeASCII(const Py_UNICODE *p,
} }
/* Resize if error handling skipped some characters */ /* Resize if error handling skipped some characters */
if (s - start < PyString_GET_SIZE(repr)) if (s - start < PyString_GET_SIZE(repr))
if (_PyString_Resize(&repr, s - start)) _PyString_Resize(&repr, s - start);
goto onError;
return repr; return repr;
onError: onError:
...@@ -2588,12 +2571,11 @@ PyObject *PyUnicode_EncodeCharmap(const Py_UNICODE *p, ...@@ -2588,12 +2571,11 @@ PyObject *PyUnicode_EncodeCharmap(const Py_UNICODE *p,
Py_DECREF(x); Py_DECREF(x);
} }
if (s - PyString_AS_STRING(v) < PyString_GET_SIZE(v)) if (s - PyString_AS_STRING(v) < PyString_GET_SIZE(v))
if (_PyString_Resize(&v, (int)(s - PyString_AS_STRING(v)))) _PyString_Resize(&v, (int)(s - PyString_AS_STRING(v)));
goto onError;
return v; return v;
onError: onError:
Py_DECREF(v); Py_XDECREF(v);
return NULL; return NULL;
} }
......
...@@ -1993,8 +1993,8 @@ filterstring(PyObject *func, PyObject *strobj) ...@@ -1993,8 +1993,8 @@ filterstring(PyObject *func, PyObject *strobj)
Py_DECREF(item); Py_DECREF(item);
} }
if (j < len && _PyString_Resize(&result, j) < 0) if (j < len)
return NULL; _PyString_Resize(&result, j);
return result; return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment