diff options
Diffstat (limited to 'Modules/binascii.c')
-rw-r--r-- | Modules/binascii.c | 287 |
1 files changed, 137 insertions, 150 deletions
diff --git a/Modules/binascii.c b/Modules/binascii.c index 1a40b4148a..9b9cd7f011 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -74,7 +74,7 @@ static PyObject *Incomplete; #define SKIP 0x7E #define FAIL 0x7D -static unsigned char table_a2b_hqx[256] = { +static const unsigned char table_a2b_hqx[256] = { /* ^@ ^A ^B ^C ^D ^E ^F ^G */ /* 0*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, /* \b \t \n ^K ^L \r ^N ^O */ @@ -125,10 +125,10 @@ static unsigned char table_a2b_hqx[256] = { FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, }; -static unsigned char table_b2a_hqx[] = +static const unsigned char table_b2a_hqx[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; -static char table_a2b_base64[] = { +static const char table_a2b_base64[] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, @@ -144,12 +144,12 @@ static char table_a2b_base64[] = { /* Max binary chunk size; limited only by available memory */ #define BASE64_MAXBIN ((PY_SSIZE_T_MAX - 3) / 2) -static unsigned char table_b2a_base64[] = +static const unsigned char table_b2a_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static unsigned short crctab_hqx[256] = { +static const unsigned short crctab_hqx[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, @@ -256,7 +256,8 @@ static PyObject * binascii_a2b_uu_impl(PyObject *module, Py_buffer *data) /*[clinic end generated code: output=e027f8e0b0598742 input=7cafeaf73df63d1c]*/ { - unsigned char *ascii_data, *bin_data; + const unsigned char *ascii_data; + unsigned char *bin_data; int leftbits = 0; unsigned char this_ch; unsigned int leftchar = 0; @@ -342,13 +343,15 @@ static PyObject * binascii_b2a_uu_impl(PyObject *module, Py_buffer *data) /*[clinic end generated code: output=0070670e52e4aa6b input=00fdf458ce8b465b]*/ { - unsigned char *ascii_data, *bin_data; + unsigned char *ascii_data; + const unsigned char *bin_data; int leftbits = 0; unsigned char this_ch; unsigned int leftchar = 0; - PyObject *rv; - Py_ssize_t bin_len; + Py_ssize_t bin_len, out_len; + _PyBytesWriter writer; + _PyBytesWriter_Init(&writer); bin_data = data->buf; bin_len = data->len; if ( bin_len > 45 ) { @@ -358,9 +361,10 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data) } /* We're lazy and allocate to much (fixed up later) */ - if ( (rv=PyBytes_FromStringAndSize(NULL, 2 + (bin_len+2)/3*4)) == NULL ) + out_len = 2 + (bin_len + 2) / 3 * 4; + ascii_data = _PyBytesWriter_Alloc(&writer, out_len); + if (ascii_data == NULL) return NULL; - ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); /* Store the length */ *ascii_data++ = ' ' + (bin_len & 077); @@ -382,17 +386,12 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data) } *ascii_data++ = '\n'; /* Append a courtesy newline */ - if (_PyBytes_Resize(&rv, - (ascii_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { - Py_CLEAR(rv); - } - return rv; + return _PyBytesWriter_Finish(&writer, ascii_data); } static int -binascii_find_valid(unsigned char *s, Py_ssize_t slen, int num) +binascii_find_valid(const unsigned char *s, Py_ssize_t slen, int num) { /* Finds & returns the (num+1)th ** valid character for base64, or -1 if none. @@ -429,13 +428,14 @@ static PyObject * binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) /*[clinic end generated code: output=0628223f19fd3f9b input=5872acf6e1cac243]*/ { - unsigned char *ascii_data, *bin_data; + const unsigned char *ascii_data; + unsigned char *bin_data; int leftbits = 0; unsigned char this_ch; unsigned int leftchar = 0; - PyObject *rv; Py_ssize_t ascii_len, bin_len; int quad_pos = 0; + _PyBytesWriter writer; ascii_data = data->buf; ascii_len = data->len; @@ -447,11 +447,12 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */ + _PyBytesWriter_Init(&writer); + /* Allocate the buffer */ - if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL ) + bin_data = _PyBytesWriter_Alloc(&writer, bin_len); + if (bin_data == NULL) return NULL; - bin_data = (unsigned char *)PyBytes_AS_STRING(rv); - bin_len = 0; for( ; ascii_len > 0; ascii_len--, ascii_data++) { this_ch = *ascii_data; @@ -496,31 +497,17 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) if ( leftbits >= 8 ) { leftbits -= 8; *bin_data++ = (leftchar >> leftbits) & 0xff; - bin_len++; leftchar &= ((1 << leftbits) - 1); } } if (leftbits != 0) { PyErr_SetString(Error, "Incorrect padding"); - Py_DECREF(rv); + _PyBytesWriter_Dealloc(&writer); return NULL; } - /* And set string size correctly. If the result string is empty - ** (because the input was all invalid) return the shared empty - ** string instead; _PyBytes_Resize() won't do this for us. - */ - if (bin_len > 0) { - if (_PyBytes_Resize(&rv, bin_len) < 0) { - Py_CLEAR(rv); - } - } - else { - Py_DECREF(rv); - rv = PyBytes_FromStringAndSize("", 0); - } - return rv; + return _PyBytesWriter_Finish(&writer, bin_data); } @@ -528,24 +515,27 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data) binascii.b2a_base64 data: Py_buffer - / + * + newline: int(c_default="1") = True Base64-code line of data. [clinic start generated code]*/ static PyObject * -binascii_b2a_base64_impl(PyObject *module, Py_buffer *data) -/*[clinic end generated code: output=4d96663170778dc3 input=14ec4e47371174a9]*/ +binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int newline) +/*[clinic end generated code: output=4ad62c8e8485d3b3 input=7b2ea6fa38d8924c]*/ { - unsigned char *ascii_data, *bin_data; + unsigned char *ascii_data; + const unsigned char *bin_data; int leftbits = 0; unsigned char this_ch; unsigned int leftchar = 0; - PyObject *rv; - Py_ssize_t bin_len; + Py_ssize_t bin_len, out_len; + _PyBytesWriter writer; bin_data = data->buf; bin_len = data->len; + _PyBytesWriter_Init(&writer); assert(bin_len >= 0); @@ -555,11 +545,14 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data) } /* 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=PyBytes_FromStringAndSize(NULL, bin_len*2 + 3)) == NULL ) + "+2" leaves room for up to two pad characters. + Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */ + out_len = bin_len*2 + 2; + if (newline) + out_len++; + ascii_data = _PyBytesWriter_Alloc(&writer, out_len); + if (ascii_data == NULL) return NULL; - ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); for( ; bin_len > 0 ; bin_len--, bin_data++ ) { /* Shift the data into our buffer */ @@ -581,14 +574,10 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data) *ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2]; *ascii_data++ = BASE64_PAD; } - *ascii_data++ = '\n'; /* Append a courtesy newline */ + if (newline) + *ascii_data++ = '\n'; /* Append a courtesy newline */ - if (_PyBytes_Resize(&rv, - (ascii_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { - Py_CLEAR(rv); - } - return rv; + return _PyBytesWriter_Finish(&writer, ascii_data); } /*[clinic input] @@ -604,16 +593,19 @@ static PyObject * binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data) /*[clinic end generated code: output=4d6d8c54d54ea1c1 input=0d914c680e0eed55]*/ { - unsigned char *ascii_data, *bin_data; + const unsigned char *ascii_data; + unsigned char *bin_data; int leftbits = 0; unsigned char this_ch; unsigned int leftchar = 0; - PyObject *rv; + PyObject *res; Py_ssize_t len; int done = 0; + _PyBytesWriter writer; ascii_data = data->buf; len = data->len; + _PyBytesWriter_Init(&writer); assert(len >= 0); @@ -623,9 +615,9 @@ binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data) /* 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=PyBytes_FromStringAndSize(NULL, len+2)) == NULL ) + bin_data = _PyBytesWriter_Alloc(&writer, len + 2); + if (bin_data == NULL) return NULL; - bin_data = (unsigned char *)PyBytes_AS_STRING(rv); for( ; len > 0 ; len--, ascii_data++ ) { /* Get the byte and look it up */ @@ -634,7 +626,7 @@ binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data) continue; if ( this_ch == FAIL ) { PyErr_SetString(Error, "Illegal char"); - Py_DECREF(rv); + _PyBytesWriter_Dealloc(&writer); return NULL; } if ( this_ch == DONE ) { @@ -656,21 +648,14 @@ binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data) if ( leftbits && !done ) { PyErr_SetString(Incomplete, "String has incomplete number of bytes"); - Py_DECREF(rv); + _PyBytesWriter_Dealloc(&writer); return NULL; } - if (_PyBytes_Resize(&rv, - (bin_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { - Py_CLEAR(rv); - } - if (rv) { - PyObject *rrv = Py_BuildValue("Oi", rv, done); - Py_DECREF(rv); - return rrv; - } - return NULL; + res = _PyBytesWriter_Finish(&writer, bin_data); + if (res == NULL) + return NULL; + return Py_BuildValue("Ni", res, done); } @@ -687,11 +672,13 @@ static PyObject * binascii_rlecode_hqx_impl(PyObject *module, Py_buffer *data) /*[clinic end generated code: output=393d79338f5f5629 input=e1f1712447a82b09]*/ { - unsigned char *in_data, *out_data; - PyObject *rv; + const unsigned char *in_data; + unsigned char *out_data; unsigned char ch; Py_ssize_t in, inend, len; + _PyBytesWriter writer; + _PyBytesWriter_Init(&writer); in_data = data->buf; len = data->len; @@ -701,9 +688,9 @@ binascii_rlecode_hqx_impl(PyObject *module, Py_buffer *data) return PyErr_NoMemory(); /* Worst case: output is twice as big as input (fixed later) */ - if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) + out_data = _PyBytesWriter_Alloc(&writer, len * 2 + 2); + if (out_data == NULL) return NULL; - out_data = (unsigned char *)PyBytes_AS_STRING(rv); for( in=0; in<len; in++) { ch = in_data[in]; @@ -729,12 +716,8 @@ binascii_rlecode_hqx_impl(PyObject *module, Py_buffer *data) } } } - if (_PyBytes_Resize(&rv, - (out_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { - Py_CLEAR(rv); - } - return rv; + + return _PyBytesWriter_Finish(&writer, out_data); } @@ -751,15 +734,17 @@ static PyObject * binascii_b2a_hqx_impl(PyObject *module, Py_buffer *data) /*[clinic end generated code: output=d0aa5a704bc9f7de input=9596ebe019fe12ba]*/ { - unsigned char *ascii_data, *bin_data; + unsigned char *ascii_data; + const unsigned char *bin_data; int leftbits = 0; unsigned char this_ch; unsigned int leftchar = 0; - PyObject *rv; Py_ssize_t len; + _PyBytesWriter writer; bin_data = data->buf; len = data->len; + _PyBytesWriter_Init(&writer); assert(len >= 0); @@ -767,9 +752,9 @@ binascii_b2a_hqx_impl(PyObject *module, Py_buffer *data) return PyErr_NoMemory(); /* Allocate a buffer that is at least large enough */ - if ( (rv=PyBytes_FromStringAndSize(NULL, len*2+2)) == NULL ) + ascii_data = _PyBytesWriter_Alloc(&writer, len * 2 + 2); + if (ascii_data == NULL) return NULL; - ascii_data = (unsigned char *)PyBytes_AS_STRING(rv); for( ; len > 0 ; len--, bin_data++ ) { /* Shift into our buffer, and output any 6bits ready */ @@ -786,12 +771,8 @@ binascii_b2a_hqx_impl(PyObject *module, Py_buffer *data) leftchar <<= (6-leftbits); *ascii_data++ = table_b2a_hqx[leftchar & 0x3f]; } - if (_PyBytes_Resize(&rv, - (ascii_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { - Py_CLEAR(rv); - } - return rv; + + return _PyBytesWriter_Finish(&writer, ascii_data); } @@ -808,13 +789,15 @@ static PyObject * binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data) /*[clinic end generated code: output=9826619565de1c6c input=54cdd49fc014402c]*/ { - unsigned char *in_data, *out_data; + const unsigned char *in_data; + unsigned char *out_data; unsigned char in_byte, in_repeat; - PyObject *rv; - Py_ssize_t in_len, out_len, out_len_left; + Py_ssize_t in_len; + _PyBytesWriter writer; in_data = data->buf; in_len = data->len; + _PyBytesWriter_Init(&writer); assert(in_len >= 0); @@ -825,59 +808,48 @@ binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data) return PyErr_NoMemory(); /* Allocate a buffer of reasonable size. Resized when needed */ - out_len = in_len*2; - if ( (rv=PyBytes_FromStringAndSize(NULL, out_len)) == NULL ) + out_data = _PyBytesWriter_Alloc(&writer, in_len); + if (out_data == NULL) return NULL; - out_len_left = out_len; - out_data = (unsigned char *)PyBytes_AS_STRING(rv); + + /* Use overallocation */ + writer.overallocate = 1; /* ** We need two macros here to get/put bytes and handle ** end-of-buffer for input and output strings. */ -#define INBYTE(b) \ - do { \ - if ( --in_len < 0 ) { \ - PyErr_SetString(Incomplete, ""); \ - Py_DECREF(rv); \ - return NULL; \ - } \ - b = *in_data++; \ +#define INBYTE(b) \ + do { \ + if ( --in_len < 0 ) { \ + PyErr_SetString(Incomplete, ""); \ + goto error; \ + } \ + b = *in_data++; \ } while(0) -#define OUTBYTE(b) \ - do { \ - if ( --out_len_left < 0 ) { \ - if ( out_len > PY_SSIZE_T_MAX / 2) return PyErr_NoMemory(); \ - if (_PyBytes_Resize(&rv, 2*out_len) < 0) \ - { Py_XDECREF(rv); return NULL; } \ - out_data = (unsigned char *)PyBytes_AS_STRING(rv) \ - + out_len; \ - out_len_left = out_len-1; \ - out_len = out_len * 2; \ - } \ - *out_data++ = b; \ - } while(0) - - /* - ** Handle first byte separately (since we have to get angry - ** in case of an orphaned RLE code). - */ - INBYTE(in_byte); + /* + ** Handle first byte separately (since we have to get angry + ** in case of an orphaned RLE code). + */ + INBYTE(in_byte); if (in_byte == RUNCHAR) { INBYTE(in_repeat); + /* only 1 byte will be written, but 2 bytes were preallocated: + subtract 1 byte to prevent overallocation */ + writer.min_size--; + if (in_repeat != 0) { /* Note Error, not Incomplete (which is at the end ** of the string only). This is a programmer error. */ PyErr_SetString(Error, "Orphaned RLE code at start"); - Py_DECREF(rv); - return NULL; + goto error; } - OUTBYTE(RUNCHAR); + *out_data++ = RUNCHAR; } else { - OUTBYTE(in_byte); + *out_data++ = in_byte; } while( in_len > 0 ) { @@ -885,26 +857,39 @@ binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data) if (in_byte == RUNCHAR) { INBYTE(in_repeat); + /* only 1 byte will be written, but 2 bytes were preallocated: + subtract 1 byte to prevent overallocation */ + writer.min_size--; + if ( in_repeat == 0 ) { /* Just an escaped RUNCHAR value */ - OUTBYTE(RUNCHAR); + *out_data++ = RUNCHAR; } else { /* Pick up value and output a sequence of it */ in_byte = out_data[-1]; + + /* enlarge the buffer if needed */ + if (in_repeat > 1) { + /* -1 because we already preallocated 1 byte */ + out_data = _PyBytesWriter_Prepare(&writer, out_data, + in_repeat - 1); + if (out_data == NULL) + goto error; + } + while ( --in_repeat > 0 ) - OUTBYTE(in_byte); + *out_data++ = in_byte; } } else { /* Normal byte */ - OUTBYTE(in_byte); + *out_data++ = in_byte; } } - if (_PyBytes_Resize(&rv, - (out_data - - (unsigned char *)PyBytes_AS_STRING(rv))) < 0) { - Py_CLEAR(rv); - } - return rv; + return _PyBytesWriter_Finish(&writer, out_data); + +error: + _PyBytesWriter_Dealloc(&writer); + return NULL; } @@ -922,7 +907,7 @@ static unsigned int binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc) /*[clinic end generated code: output=8ec2a78590d19170 input=add8c53712ccceda]*/ { - unsigned char *bin_data; + const unsigned char *bin_data; Py_ssize_t len; crc &= 0xffff; @@ -1000,7 +985,7 @@ binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc) using byte-swap instructions. ********************************************************************/ -static unsigned int crc_32_tab[256] = { +static const unsigned int crc_32_tab[256] = { 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, @@ -1073,7 +1058,7 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc) #ifdef USE_ZLIB_CRC32 /* This was taken from zlibmodule.c PyZlib_crc32 (but is PY_SSIZE_T_CLEAN) */ { - Byte *buf; + const Byte *buf; Py_ssize_t len; int signed_val; @@ -1084,7 +1069,7 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc) } #else /* USE_ZLIB_CRC32 */ { /* By Jim Ahlstrom; All rights transferred to CNRI */ - unsigned char *bin_data; + const unsigned char *bin_data; Py_ssize_t len; unsigned int result; @@ -1167,7 +1152,7 @@ static PyObject * binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr) /*[clinic end generated code: output=0cc1a139af0eeecb input=9e1e7f2f94db24fd]*/ { - char* argbuf; + const char* argbuf; Py_ssize_t arglen; PyObject *retval; char* retbuf; @@ -1224,7 +1209,7 @@ binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr) return binascii_a2b_hex_impl(module, hexstr); } -static int table_hex[128] = { +static const int table_hex[128] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, @@ -1255,7 +1240,8 @@ binascii_a2b_qp_impl(PyObject *module, Py_buffer *data, int header) { Py_ssize_t in, out; char ch; - unsigned char *ascii_data, *odata; + const unsigned char *ascii_data; + unsigned char *odata; Py_ssize_t datalen = 0; PyObject *rv; @@ -1362,13 +1348,14 @@ binascii_b2a_qp_impl(PyObject *module, Py_buffer *data, int quotetabs, /*[clinic end generated code: output=e9884472ebb1a94c input=7f2a9aaa008e92b2]*/ { Py_ssize_t in, out; - unsigned char *databuf, *odata; + const unsigned char *databuf; + unsigned char *odata; Py_ssize_t datalen = 0, odatalen = 0; PyObject *rv; unsigned int linelen = 0; unsigned char ch; int crlf = 0; - unsigned char *p; + const unsigned char *p; databuf = data->buf; datalen = data->len; @@ -1377,7 +1364,7 @@ binascii_b2a_qp_impl(PyObject *module, Py_buffer *data, int quotetabs, /* XXX: this function has the side effect of converting all of * the end of lines to be the same depending on this detection * here */ - p = (unsigned char *) memchr(databuf, '\n', datalen); + p = (const unsigned char *) memchr(databuf, '\n', datalen); if ((p != NULL) && (p > databuf) && (*(p-1) == '\r')) crlf = 1; |