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.
This commit is contained in:
Tim Peters 2002-04-27 18:44:32 +00:00
parent 602f740bc2
commit 5de9842b34
14 changed files with 54 additions and 90 deletions

View file

@ -586,7 +586,16 @@ parameter and are called with a non-string parameter.
\begin{cfuncdesc}{int}{_PyString_Resize}{PyObject **string, int newsize}
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
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}
\begin{cfuncdesc}{PyObject*}{PyString_Format}{PyObject *format,

View file

@ -331,8 +331,8 @@ static PyObject *PySSL_SSLread(PySSLObject *self, PyObject *args)
Py_DECREF(buf);
return PySSL_SetError(self, count);
}
if (count != len && _PyString_Resize(&buf, count) < 0)
return NULL;
if (count != len)
_PyString_Resize(&buf, count);
return buf;
}

View file

@ -1252,14 +1252,8 @@ modified_EncodeRawUnicodeEscape(const Py_UNICODE *s, int size)
*p++ = (char) ch;
}
*p = '\0';
if (_PyString_Resize(&repr, p - q))
goto onError;
_PyString_Resize(&repr, p - q);
return repr;
onError:
Py_DECREF(repr);
return NULL;
}

View file

@ -251,8 +251,7 @@ CD_readda(cdplayerobject *self, PyObject *args)
return NULL;
}
if (n < numframes)
if (_PyString_Resize(&result, n * sizeof(CDFRAME)))
return NULL;
_PyString_Resize(&result, n * sizeof(CDFRAME));
return result;
}

View file

@ -135,8 +135,7 @@ cl_CompressImage(PyObject *self, PyObject *args)
}
if (compressedBufferSize < frameBufferSize)
if (_PyString_Resize(&compressedBuffer, compressedBufferSize))
return NULL;
_PyString_Resize(&compressedBuffer, compressedBufferSize);
return compressedBuffer;
}

View file

@ -158,8 +158,7 @@ lad_read(lad_t *self, PyObject *args)
return NULL;
}
self->x_icount += count;
if (_PyString_Resize(&rv, count) == -1)
return NULL;
_PyString_Resize(&rv, count);
return rv;
}

View file

@ -516,11 +516,8 @@ symcomp(PyObject *pattern, PyObject *gdict)
return NULL;
}
/* _PyString_Resize() decrements npattern on failure */
if (_PyString_Resize(&npattern, n - v) == 0)
return npattern;
else {
return NULL;
}
_PyString_Resize(&npattern, n - v);
return npattern;
}

View file

@ -1402,8 +1402,8 @@ PySocketSock_recv(PySocketSockObject *s, PyObject *args)
Py_DECREF(buf);
return s->errorhandler();
}
if (n != len && _PyString_Resize(&buf, n) < 0)
return NULL;
if (n != len)
_PyString_Resize(&buf, n);
return buf;
}

View file

@ -215,10 +215,8 @@ strop_joinfields(PyObject *self, PyObject *args)
}
slen = PyString_GET_SIZE(item);
while (reslen + slen + seplen >= sz) {
if (_PyString_Resize(&res, sz * 2)) {
Py_DECREF(res);
if (_PyString_Resize(&res, sz * 2) < 0)
return NULL;
}
sz *= 2;
p = PyString_AsString(res) + reslen;
}
@ -231,10 +229,7 @@ strop_joinfields(PyObject *self, PyObject *args)
p += slen;
reslen += slen;
}
if (_PyString_Resize(&res, reslen)) {
Py_DECREF(res);
res = NULL;
}
_PyString_Resize(&res, reslen);
return res;
}
@ -257,8 +252,7 @@ strop_joinfields(PyObject *self, PyObject *args)
}
slen = PyString_GET_SIZE(item);
while (reslen + slen + seplen >= sz) {
if (_PyString_Resize(&res, sz * 2)) {
Py_DECREF(res);
if (_PyString_Resize(&res, sz * 2) < 0) {
Py_DECREF(item);
return NULL;
}
@ -275,10 +269,7 @@ strop_joinfields(PyObject *self, PyObject *args)
reslen += slen;
Py_DECREF(item);
}
if (_PyString_Resize(&res, reslen)) {
Py_DECREF(res);
res = NULL;
}
_PyString_Resize(&res, reslen);
return res;
}
@ -989,8 +980,8 @@ strop_translate(PyObject *self, PyObject *args)
return input_obj;
}
/* Fix the size of the resulting string */
if (inlen > 0 &&_PyString_Resize(&result, output-output_start))
return NULL;
if (inlen > 0)
_PyString_Resize(&result, output - output_start);
return result;
}

View file

@ -255,9 +255,8 @@ PyZlib_decompress(PyObject *self, PyObject *args)
/* fall through */
case(Z_OK):
/* need more memory */
if (_PyString_Resize(&result_str, r_strlen << 1) == -1) {
if (_PyString_Resize(&result_str, r_strlen << 1) < 0) {
inflateEnd(&zst);
result_str = NULL;
goto error;
}
zst.next_out = (unsigned char *)PyString_AS_STRING(result_str) \
@ -414,10 +413,8 @@ PyZlib_objcompress(compobject *self, PyObject *args)
/* while Z_OK and the output buffer is full, there might be more output,
so extend the output buffer and try again */
while (err == Z_OK && self->zst.avail_out == 0) {
if (_PyString_Resize(&RetVal, length << 1) == -1) {
RetVal = NULL;
if (_PyString_Resize(&RetVal, length << 1) < 0)
goto error;
}
self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \
+ length;
self->zst.avail_out = length;
@ -438,9 +435,7 @@ PyZlib_objcompress(compobject *self, PyObject *args)
RetVal = NULL;
goto error;
}
if (_PyString_Resize(&RetVal,
self->zst.total_out - start_total_out) < 0)
RetVal = NULL;
_PyString_Resize(&RetVal, self->zst.total_out - start_total_out);
error:
LEAVE_ZLIB
@ -510,10 +505,8 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
if (max_length && length > max_length)
length = max_length;
if (_PyString_Resize(&RetVal, length) == -1) {
RetVal = NULL;
if (_PyString_Resize(&RetVal, length) < 0)
goto error;
}
self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \
+ old_length;
self->zst.avail_out = length - old_length;
@ -561,8 +554,7 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
goto error;
}
if (_PyString_Resize(&RetVal, self->zst.total_out - start_total_out) < 0)
RetVal = NULL;
_PyString_Resize(&RetVal, self->zst.total_out - start_total_out);
error:
LEAVE_ZLIB
@ -612,10 +604,8 @@ PyZlib_flush(compobject *self, PyObject *args)
/* while Z_OK and the output buffer is full, there might be more output,
so extend the output buffer and try again */
while (err == Z_OK && self->zst.avail_out == 0) {
if (_PyString_Resize(&RetVal, length << 1) == -1) {
RetVal = NULL;
if (_PyString_Resize(&RetVal, length << 1) < 0)
goto error;
}
self->zst.next_out = (unsigned char *)PyString_AS_STRING(RetVal) \
+ length;
self->zst.avail_out = length;
@ -651,8 +641,7 @@ PyZlib_flush(compobject *self, PyObject *args)
goto error;
}
if (_PyString_Resize(&RetVal, self->zst.total_out - start_total_out) < 0)
RetVal = NULL;
_PyString_Resize(&RetVal, self->zst.total_out - start_total_out);
error:
LEAVE_ZLIB

View file

@ -1317,9 +1317,7 @@ file_readlines(PyFileObject *f, PyObject *args)
goto error;
}
cleanup:
if (big_buffer) {
Py_DECREF(big_buffer);
}
Py_XDECREF(big_buffer);
return list;
}

View file

@ -1869,8 +1869,8 @@ string_translate(PyStringObject *self, PyObject *args)
return input_obj;
}
/* Fix the size of the resulting string */
if (inlen > 0 &&_PyString_Resize(&result, output-output_start))
return NULL;
if (inlen > 0)
_PyString_Resize(&result, output - output_start);
return result;
}
@ -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
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
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
_PyString_Resize(PyObject **pv, int newsize)

View file

@ -927,10 +927,7 @@ PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s,
*out++ = '-';
}
if (_PyString_Resize(&v, out - start)) {
Py_DECREF(v);
return NULL;
}
_PyString_Resize(&v, out - start);
return v;
}
@ -1764,7 +1761,7 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
/* Resize the string if necessary */
if (offset + 12 > PyString_GET_SIZE(repr)) {
if (_PyString_Resize(&repr, PyString_GET_SIZE(repr) + 100))
goto onError;
return NULL;
p = PyString_AS_STRING(repr) + offset;
}
@ -1847,14 +1844,8 @@ PyObject *unicodeescape_string(const Py_UNICODE *s,
*p++ = PyString_AS_STRING(repr)[1];
*p = '\0';
if (_PyString_Resize(&repr, p - PyString_AS_STRING(repr)))
goto onError;
_PyString_Resize(&repr, p - PyString_AS_STRING(repr));
return repr;
onError:
Py_DECREF(repr);
return NULL;
}
PyObject *PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s,
@ -1985,14 +1976,8 @@ PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s,
*p++ = (char) ch;
}
*p = '\0';
if (_PyString_Resize(&repr, p - q))
goto onError;
_PyString_Resize(&repr, p - q);
return repr;
onError:
Py_DECREF(repr);
return NULL;
}
PyObject *PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)
@ -2092,8 +2077,7 @@ PyObject *PyUnicode_EncodeLatin1(const Py_UNICODE *p,
}
/* Resize if error handling skipped some characters */
if (s - start < PyString_GET_SIZE(repr))
if (_PyString_Resize(&repr, s - start))
goto onError;
_PyString_Resize(&repr, s - start);
return repr;
onError:
@ -2240,8 +2224,7 @@ PyObject *PyUnicode_EncodeASCII(const Py_UNICODE *p,
}
/* Resize if error handling skipped some characters */
if (s - start < PyString_GET_SIZE(repr))
if (_PyString_Resize(&repr, s - start))
goto onError;
_PyString_Resize(&repr, s - start);
return repr;
onError:
@ -2588,12 +2571,11 @@ PyObject *PyUnicode_EncodeCharmap(const Py_UNICODE *p,
Py_DECREF(x);
}
if (s - PyString_AS_STRING(v) < PyString_GET_SIZE(v))
if (_PyString_Resize(&v, (int)(s - PyString_AS_STRING(v))))
goto onError;
_PyString_Resize(&v, (int)(s - PyString_AS_STRING(v)));
return v;
onError:
Py_DECREF(v);
Py_XDECREF(v);
return NULL;
}

View file

@ -1993,8 +1993,8 @@ filterstring(PyObject *func, PyObject *strobj)
Py_DECREF(item);
}
if (j < len && _PyString_Resize(&result, j) < 0)
return NULL;
if (j < len)
_PyString_Resize(&result, j);
return result;