Index: Modules/binascii.c =================================================================== --- Modules/binascii.c (revision 77489) +++ Modules/binascii.c (working copy) @@ -188,6 +188,7 @@ static PyObject * binascii_a2b_uu(PyObject *self, PyObject *args) { + Py_buffer pascii; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -195,8 +196,10 @@ PyObject *rv; Py_ssize_t ascii_len, bin_len; - if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) ) + if ( !PyArg_ParseTuple(args, "s*:a2b_uu", &pascii) ) return NULL; + ascii_data = pascii.buf; + ascii_len = pascii.len; assert(ascii_len >= 0); @@ -205,9 +208,11 @@ ascii_len--; /* Allocate the buffer */ - if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL ) + if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL ) { + PyBuffer_Release(&pascii); return NULL; - bin_data = (unsigned char *)PyString_AsString(rv); + } + bin_data = (unsigned char *)PyString_AS_STRING(rv); for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) { /* XXX is it really best to add NULs if there's no more data */ @@ -226,6 +231,7 @@ */ if ( this_ch < ' ' || this_ch > (' ' + 64)) { PyErr_SetString(Error, "Illegal char"); + PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } @@ -254,10 +260,12 @@ if ( this_ch != ' ' && this_ch != ' '+64 && this_ch != '\n' && this_ch != '\r' ) { PyErr_SetString(Error, "Trailing garbage"); + PyBuffer_Release(&pascii); Py_DECREF(rv); return NULL; } } + PyBuffer_Release(&pascii); return rv; } @@ -266,6 +274,7 @@ static PyObject * binascii_b2a_uu(PyObject *self, PyObject *args) { + Py_buffer pbin; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -273,18 +282,23 @@ PyObject *rv; Py_ssize_t bin_len; - if ( !PyArg_ParseTuple(args, "s#:b2a_uu", &bin_data, &bin_len) ) + if ( !PyArg_ParseTuple(args, "s*:b2a_uu", &pbin) ) return NULL; + bin_data = pbin.buf; + bin_len = pbin.len; if ( bin_len > 45 ) { /* The 45 is a limit that appears in all uuencode's */ PyErr_SetString(Error, "At most 45 bytes at once"); + PyBuffer_Release(&pbin); return NULL; } /* We're lazy and allocate to much (fixed up later) */ - if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2+2)) == NULL ) + if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2+2)) == NULL ) { + PyBuffer_Release(&pbin); return NULL; - ascii_data = (unsigned char *)PyString_AsString(rv); + } + ascii_data = (unsigned char *)PyString_AS_STRING(rv); /* Store the length */ *ascii_data++ = ' ' + (bin_len & 077); @@ -306,8 +320,13 @@ } *ascii_data++ = '\n'; /* Append a courtesy newline */ - _PyString_Resize(&rv, (ascii_data - - (unsigned char *)PyString_AsString(rv))); + if (_PyString_Resize(&rv, + (ascii_data - + (unsigned char *)PyString_AS_STRING(rv))) < 0) { + Py_DECREF(rv); + rv = NULL; + } + PyBuffer_Release(&pbin); return rv; } @@ -342,6 +361,7 @@ static PyObject * binascii_a2b_base64(PyObject *self, PyObject *args) { + Py_buffer pascii; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -350,20 +370,26 @@ Py_ssize_t ascii_len, bin_len; int quad_pos = 0; - if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) ) + if ( !PyArg_ParseTuple(args, "s*:a2b_base64", &pascii) ) return NULL; + ascii_data = pascii.buf; + ascii_len = pascii.len; assert(ascii_len >= 0); - if (ascii_len > PY_SSIZE_T_MAX - 3) + if (ascii_len > PY_SSIZE_T_MAX - 3) { + PyBuffer_Release(&pascii); return PyErr_NoMemory(); + } bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */ /* Allocate the buffer */ - if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL ) + if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL ) { + PyBuffer_Release(&pascii); return NULL; - bin_data = (unsigned char *)PyString_AsString(rv); + } + bin_data = (unsigned char *)PyString_AS_STRING(rv); bin_len = 0; for( ; ascii_len > 0; ascii_len--, ascii_data++) { @@ -415,6 +441,7 @@ } if (leftbits != 0) { + PyBuffer_Release(&pascii); PyErr_SetString(Error, "Incorrect padding"); Py_DECREF(rv); return NULL; @@ -424,12 +451,17 @@ ** (because the input was all invalid) return the shared empty ** string instead; _PyString_Resize() won't do this for us. */ - if (bin_len > 0) - _PyString_Resize(&rv, bin_len); + if (bin_len > 0) { + if (_PyString_Resize(&rv, bin_len) < 0) { + Py_DECREF(rv); + rv = NULL; + } + } else { Py_DECREF(rv); - rv = PyString_FromString(""); + rv = PyString_FromStringAndSize("", 0); } + PyBuffer_Release(&pascii); return rv; } @@ -438,6 +470,7 @@ static PyObject * binascii_b2a_base64(PyObject *self, PyObject *args) { + Py_buffer pbuf; unsigned char *ascii_data, *bin_data; int leftbits = 0; unsigned char this_ch; @@ -445,22 +478,27 @@ PyObject *rv; Py_ssize_t bin_len; - if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) ) + if ( !PyArg_ParseTuple(args, "s*:b2a_base64", &pbuf) ) return NULL; + bin_data = pbuf.buf; + bin_len = pbuf.len; assert(bin_len >= 0); if ( bin_len > BASE64_MAXBIN ) { PyErr_SetString(Error, "Too much data for base64 line"); + PyBuffer_Release(&pbuf); return NULL; } /* We're lazy and allocate too much (fixed up later). "+3" leaves room for up to two pad characters and a trailing newline. Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */ - if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) + if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) { + PyBuffer_Release(&pbuf); return NULL; - ascii_data = (unsigned char *)PyString_AsString(rv); + } + ascii_data = (unsigned char *)PyString_AS_STRING(rv); for( ; bin_len > 0 ; bin_len--, bin_data++ ) { /* Shift the data into our buffer */ @@ -484,8 +522,13 @@ } *ascii_data++ = '\n'; /* Append a courtesy newline */ - _PyString_Resize(&rv, (ascii_data - - (unsigned char *)PyString_AsString(rv))); + if (_PyString_Resize(&rv, + (ascii_data - + (unsigned char *)PyString_AS_STRING(rv))) < 0) { + Py_DECREF(rv); + rv = NULL; + } + PyBuffer_Release(&pbuf); return rv; } @@ -515,7 +558,7 @@ would preclude subsequent resizing. */ if ( (rv=PyString_FromStringAndSize(NULL, len+2)) == NULL ) return NULL; - bin_data = (unsigned char *)PyString_AsString(rv); + bin_data = (unsigned char *)PyString_AS_STRING(rv); for( ; len > 0 ; len--, ascii_data++ ) { /* Get the byte and look it up */ @@ -549,8 +592,12 @@ Py_DECREF(rv); return NULL; } - _PyString_Resize( - &rv, (bin_data - (unsigned char *)PyString_AsString(rv))); + if (_PyString_Resize(&rv, + (bin_data - + (unsigned char *)PyString_AS_STRING(rv))) < 0) { + Py_DECREF(rv); + rv = NULL; + } if (rv) { PyObject *rrv = Py_BuildValue("Oi", rv, done); Py_DECREF(rv); @@ -565,23 +612,30 @@ static PyObject * binascii_rlecode_hqx(PyObject *self, PyObject *args) { + Py_buffer pbuf; unsigned char *in_data, *out_data; PyObject *rv; unsigned char ch; Py_ssize_t in, inend, len; - if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) ) + if ( !PyArg_ParseTuple(args, "s*:rlecode_hqx", &pbuf) ) return NULL; + in_data = pbuf.buf; + len = pbuf.len; assert(len >= 0); - if (len > PY_SSIZE_T_MAX / 2 - 2) + if (len > PY_SSIZE_T_MAX / 2 - 2) { + PyBuffer_Release(&pbuf); return PyErr_NoMemory(); + } /* Worst case: output is twice as big as input (fixed later) */ - if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL ) + if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL ) { + PyBuffer_Release(&pbuf); return NULL; - out_data = (unsigned char *)PyString_AsString(rv); + } + out_data = (unsigned char *)PyString_AS_STRING(rv); for( in=0; in= 0); - if (len > PY_SSIZE_T_MAX / 2 - 2) + if (len > PY_SSIZE_T_MAX / 2 - 2) { + PyBuffer_Release(&pbin); return PyErr_NoMemory(); + } /* Allocate a buffer that is at least large enough */ - if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL ) + if ( (rv=PyString_FromStringAndSize(NULL, len*2+2)) == NULL ) { + PyBuffer_Release(&pbin); return NULL; - ascii_data = (unsigned char *)PyString_AsString(rv); + } + ascii_data = (unsigned char *)PyString_AS_STRING(rv); for( ; len > 0 ; len--, bin_data++ ) { /* Shift into our buffer, and output any 6bits ready */ @@ -652,8 +718,13 @@ leftchar <<= (6-leftbits); *ascii_data++ = table_b2a_hqx[leftchar & 0x3f]; } - _PyString_Resize(&rv, (ascii_data - - (unsigned char *)PyString_AsString(rv))); + if (_PyString_Resize(&rv, + (ascii_data - + (unsigned char *)PyString_AS_STRING(rv))) < 0) { + Py_DECREF(rv); + rv = NULL; + } + PyBuffer_Release(&pbin); return rv; } @@ -662,28 +733,37 @@ static PyObject * binascii_rledecode_hqx(PyObject *self, PyObject *args) { + Py_buffer pin; unsigned char *in_data, *out_data; unsigned char in_byte, in_repeat; PyObject *rv; Py_ssize_t in_len, out_len, out_len_left; - if ( !PyArg_ParseTuple(args, "s#:rledecode_hqx", &in_data, &in_len) ) + if ( !PyArg_ParseTuple(args, "s*:rledecode_hqx", &pin) ) return NULL; + in_data = pin.buf; + in_len = pin.len; assert(in_len >= 0); /* Empty string is a special case */ - if ( in_len == 0 ) - return PyString_FromString(""); - else if (in_len > PY_SSIZE_T_MAX / 2) - return PyErr_NoMemory(); + if ( in_len == 0 ) { + PyBuffer_Release(&pin); + return PyString_FromStringAndSize("", 0); + } + else if (in_len > PY_SSIZE_T_MAX / 2) { + PyBuffer_Release(&pin); + return PyErr_NoMemory(); + } /* Allocate a buffer of reasonable size. Resized when needed */ out_len = in_len*2; - if ( (rv=PyString_FromStringAndSize(NULL, out_len)) == NULL ) + if ( (rv=PyString_FromStringAndSize(NULL, out_len)) == NULL ) { + PyBuffer_Release(&pin); return NULL; + } out_len_left = out_len; - out_data = (unsigned char *)PyString_AsString(rv); + out_data = (unsigned char *)PyString_AS_STRING(rv); /* ** We need two macros here to get/put bytes and handle @@ -694,6 +774,7 @@ if ( --in_len < 0 ) { \ PyErr_SetString(Incomplete, ""); \ Py_DECREF(rv); \ + PyBuffer_Release(&pin); \ return NULL; \ } \ b = *in_data++; \ @@ -703,9 +784,9 @@ do { \ if ( --out_len_left < 0 ) { \ if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \ - _PyString_Resize(&rv, 2*out_len); \ - if ( rv == NULL ) return NULL; \ - out_data = (unsigned char *)PyString_AsString(rv) \ + if (_PyString_Resize(&rv, 2*out_len) < 0) \ + { Py_DECREF(rv); PyBuffer_Release(&pin); return NULL; } \ + out_data = (unsigned char *)PyString_AS_STRING(rv) \ + out_len; \ out_len_left = out_len-1; \ out_len = out_len * 2; \ @@ -726,6 +807,7 @@ ** of the string only). This is a programmer error. */ PyErr_SetString(Error, "Orphaned RLE code at start"); + PyBuffer_Release(&pin); Py_DECREF(rv); return NULL; } @@ -753,8 +835,13 @@ OUTBYTE(in_byte); } } - _PyString_Resize(&rv, (out_data - - (unsigned char *)PyString_AsString(rv))); + if (_PyString_Resize(&rv, + (out_data - + (unsigned char *)PyString_AS_STRING(rv))) < 0) { + Py_DECREF(rv); + rv = NULL; + } + PyBuffer_Release(&pin); return rv; } @@ -764,17 +851,21 @@ static PyObject * binascii_crc_hqx(PyObject *self, PyObject *args) { + Py_buffer pin; unsigned char *bin_data; unsigned int crc; Py_ssize_t len; - if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) ) + if ( !PyArg_ParseTuple(args, "s*i:crc_hqx", &pin, &crc) ) return NULL; + bin_data = pin.buf; + len = pin.len; while(len-- > 0) { crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++]; } + PyBuffer_Release(&pin); return Py_BuildValue("i", crc); } @@ -787,17 +878,21 @@ binascii_crc32(PyObject *self, PyObject *args) { unsigned int crc32val = 0; /* crc32(0L, Z_NULL, 0) */ + Py_buffer pbuf; Byte *buf; Py_ssize_t len; int signed_val; - if (!PyArg_ParseTuple(args, "s#|I:crc32", &buf, &len, &crc32val)) - return NULL; + if (!PyArg_ParseTuple(args, "s*|I:crc32", &pbuf, &crc32val)) + return NULL; /* In Python 2.x we return a signed integer regardless of native platform * long size (the 32bit unsigned long is treated as 32-bit signed and sign * extended into a 64-bit long inside the integer object). 3.0 does the * right thing and returns unsigned. http://bugs.python.org/issue1202 */ + buf = (Byte*)pbuf.buf; + len = pbuf.len; signed_val = crc32(crc32val, buf, len); + PyBuffer_Release(&pbuf); return PyInt_FromLong(signed_val); } #else /* USE_ZLIB_CRC32 */ @@ -922,13 +1017,16 @@ static PyObject * binascii_crc32(PyObject *self, PyObject *args) { /* By Jim Ahlstrom; All rights transferred to CNRI */ + Py_buffer pbin; unsigned char *bin_data; unsigned int crc = 0U; /* initial value of CRC */ Py_ssize_t len; int result; - if ( !PyArg_ParseTuple(args, "s#|I:crc32", &bin_data, &len, &crc) ) + if ( !PyArg_ParseTuple(args, "s*|I:crc32", &pbin, &crc) ) return NULL; + bin_data = pbin.buf; + len = pbin.len; crc = ~ crc; while (len-- > 0) @@ -936,6 +1034,7 @@ /* Note: (crc >> 8) MUST zero fill on left */ result = (int)(crc ^ 0xFFFFFFFFU); + PyBuffer_Release(&pbin); return PyInt_FromLong(result); } #endif /* USE_ZLIB_CRC32 */ @@ -944,25 +1043,30 @@ static PyObject * binascii_hexlify(PyObject *self, PyObject *args) { + Py_buffer parg; char* argbuf; Py_ssize_t arglen; PyObject *retval; char* retbuf; Py_ssize_t i, j; - if (!PyArg_ParseTuple(args, "s#:b2a_hex", &argbuf, &arglen)) + if (!PyArg_ParseTuple(args, "s*:b2a_hex", &parg)) return NULL; + argbuf = parg.buf; + arglen = parg.len; assert(arglen >= 0); - if (arglen > PY_SSIZE_T_MAX / 2) + if (arglen > PY_SSIZE_T_MAX / 2) { + PyBuffer_Release(&parg); return PyErr_NoMemory(); + } retval = PyString_FromStringAndSize(NULL, arglen*2); - if (!retval) + if (!retval) { + PyBuffer_Release(&parg); return NULL; - retbuf = PyString_AsString(retval); - if (!retbuf) - goto finally; + } + retbuf = PyString_AS_STRING(retval); /* make hex version of string, taken from shamodule.c */ for (i=j=0; i < arglen; i++) { @@ -974,11 +1078,8 @@ c = (c>9) ? c+'a'-10 : c + '0'; retbuf[j++] = c; } + PyBuffer_Release(&parg); return retval; - - finally: - Py_DECREF(retval); - return NULL; } PyDoc_STRVAR(doc_hexlify, @@ -1005,14 +1106,17 @@ static PyObject * binascii_unhexlify(PyObject *self, PyObject *args) { + Py_buffer parg; char* argbuf; Py_ssize_t arglen; PyObject *retval; char* retbuf; Py_ssize_t i, j; - if (!PyArg_ParseTuple(args, "s#:a2b_hex", &argbuf, &arglen)) + if (!PyArg_ParseTuple(args, "s*:a2b_hex", &parg)) return NULL; + argbuf = parg.buf; + arglen = parg.len; assert(arglen >= 0); @@ -1021,16 +1125,17 @@ * raise an exception. */ if (arglen % 2) { + PyBuffer_Release(&parg); PyErr_SetString(PyExc_TypeError, "Odd-length string"); return NULL; } retval = PyString_FromStringAndSize(NULL, (arglen/2)); - if (!retval) + if (!retval) { + PyBuffer_Release(&parg); return NULL; - retbuf = PyString_AsString(retval); - if (!retbuf) - goto finally; + } + retbuf = PyString_AS_STRING(retval); for (i=j=0; i < arglen; i += 2) { int top = to_int(Py_CHARMASK(argbuf[i])); @@ -1042,9 +1147,11 @@ } retbuf[j++] = (top << 4) + bot; } + PyBuffer_Release(&parg); return retval; finally: + PyBuffer_Release(&parg); Py_DECREF(retval); return NULL; } @@ -1077,15 +1184,18 @@ { Py_ssize_t in, out; char ch; + Py_buffer pdata; unsigned char *data, *odata; Py_ssize_t datalen = 0; PyObject *rv; static char *kwlist[] = {"data", "header", NULL}; int header = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data, - &datalen, &header)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|i", kwlist, &pdata, + &header)) return NULL; + data = pdata.buf; + datalen = pdata.len; /* We allocate the output same size as input, this is overkill. * The previous implementation used calloc() so we'll zero out the @@ -1093,6 +1203,7 @@ */ odata = (unsigned char *) PyMem_Malloc(datalen); if (odata == NULL) { + PyBuffer_Release(&pdata); PyErr_NoMemory(); return NULL; } @@ -1143,9 +1254,11 @@ } } if ((rv = PyString_FromStringAndSize((char *)odata, out)) == NULL) { + PyBuffer_Release(&pdata); PyMem_Free(odata); return NULL; } + PyBuffer_Release(&pdata); PyMem_Free(odata); return rv; } @@ -1176,6 +1289,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs) { Py_ssize_t in, out; + Py_buffer pdata; unsigned char *data, *odata; Py_ssize_t datalen = 0, odatalen = 0; PyObject *rv; @@ -1189,9 +1303,11 @@ int crlf = 0; unsigned char *p; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data, - &datalen, "etabs, &istext, &header)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s*|iii", kwlist, &pdata, + "etabs, &istext, &header)) return NULL; + data = pdata.buf; + datalen = pdata.len; /* See if this string is using CRLF line ends */ /* XXX: this function has the side effect of converting all of @@ -1269,6 +1385,7 @@ */ odata = (unsigned char *) PyMem_Malloc(odatalen); if (odata == NULL) { + PyBuffer_Release(&pdata); PyErr_NoMemory(); return NULL; } @@ -1343,9 +1460,11 @@ } } if ((rv = PyString_FromStringAndSize((char *)odata, out)) == NULL) { + PyBuffer_Release(&pdata); PyMem_Free(odata); return NULL; } + PyBuffer_Release(&pdata); PyMem_Free(odata); return rv; }