Skip to content

Commit

Permalink
SF #1022953: binascii.a2b_hqx("") raises SystemError
Browse files Browse the repository at this point in the history
Several functions adopted the strategy of altering a full lengthed
string copy and resizing afterwards.  That would fail if the initial
string was short enough (0 or 1) to be interned.  Interning precluded
the subsequent resizing operation.

The solution was to make sure the initial string was at least two
characters long.

Added tests to verify that all binascii functions do not crater when
given an empty string argument.
  • Loading branch information
rhettinger committed Sep 6, 2004
1 parent 8158e84 commit 658717e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
10 changes: 10 additions & 0 deletions Lib/test/test_binascii.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ def test_qp(self):
"0"*75+"=\r\n=FF\r\n=FF\r\n=FF"
)

def test_empty_string(self):
# A test for SF bug #1022953. Make sure SystemError is not raised.
for n in ['b2a_qp', 'a2b_hex', 'b2a_base64', 'a2b_uu', 'a2b_qp',
'b2a_hex', 'unhexlify', 'hexlify', 'crc32', 'b2a_hqx',
'a2b_hqx', 'a2b_base64', 'rlecode_hqx', 'b2a_uu',
'rledecode_hqx']:
f = getattr(binascii, n)
f('')
binascii.crc_hqx('', 0)

def test_main():
test_support.run_unittest(BinASCIITest)

Expand Down
21 changes: 16 additions & 5 deletions Modules/binascii.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
}

/* We're lazy and allocate to much (fixed up later) */
if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2)) == NULL )
if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2+2)) == NULL )
return NULL;
ascii_data = (unsigned char *)PyString_AsString(rv);

Expand Down Expand Up @@ -491,8 +491,10 @@ binascii_a2b_hqx(PyObject *self, PyObject *args)
if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) )
return NULL;

/* Allocate a string that is too big (fixed later) */
if ( (rv=PyString_FromStringAndSize(NULL, len)) == NULL )
/* Allocate a string that is too big (fixed later)
Add two to the initial length to prevent interning which
would preclude subsequent resizing. */
if ( (rv=PyString_FromStringAndSize(NULL, len+2)) == NULL )
return NULL;
bin_data = (unsigned char *)PyString_AsString(rv);

Expand Down Expand Up @@ -528,6 +530,15 @@ binascii_a2b_hqx(PyObject *self, PyObject *args)
Py_DECREF(rv);
return NULL;
}


assert(PyString_Check(rv));
assert((bin_data - (unsigned char *)PyString_AsString(rv)) >= 0);
assert(!PyString_CHECK_INTERNED(rv));

assert(rv->ob_refcnt == 1);


_PyString_Resize(
&rv, (bin_data - (unsigned char *)PyString_AsString(rv)));
if (rv) {
Expand All @@ -553,7 +564,7 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
return NULL;

/* Worst case: output is twice as big as input (fixed later) */
if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL )
if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL )
return NULL;
out_data = (unsigned char *)PyString_AsString(rv);

Expand Down Expand Up @@ -602,7 +613,7 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
return NULL;

/* Allocate a buffer that is at least large enough */
if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL )
if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL )
return NULL;
ascii_data = (unsigned char *)PyString_AsString(rv);

Expand Down

0 comments on commit 658717e

Please sign in to comment.