Skip to content

Commit ca99af3

Browse files
authored
gh-129813, PEP 782: Use PyBytesWriter in binascii (#138825)
Replace the private _PyBytesWriter API with the new public PyBytesWriter API.
1 parent 805e336 commit ca99af3

File tree

1 file changed

+50
-47
lines changed

1 file changed

+50
-47
lines changed

Modules/binascii.c

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,9 @@ binascii_a2b_uu_impl(PyObject *module, Py_buffer *data)
205205
/*[clinic end generated code: output=e027f8e0b0598742 input=7cafeaf73df63d1c]*/
206206
{
207207
const unsigned char *ascii_data;
208-
unsigned char *bin_data;
209208
int leftbits = 0;
210209
unsigned char this_ch;
211210
unsigned int leftchar = 0;
212-
PyObject *rv;
213211
Py_ssize_t ascii_len, bin_len;
214212
binascii_state *state;
215213

@@ -223,9 +221,11 @@ binascii_a2b_uu_impl(PyObject *module, Py_buffer *data)
223221
ascii_len--;
224222

225223
/* Allocate the buffer */
226-
if ( (rv=PyBytes_FromStringAndSize(NULL, bin_len)) == NULL )
224+
PyBytesWriter *writer = PyBytesWriter_Create(bin_len);
225+
if (writer == NULL) {
227226
return NULL;
228-
bin_data = (unsigned char *)PyBytes_AS_STRING(rv);
227+
}
228+
unsigned char *bin_data = PyBytesWriter_GetData(writer);
229229

230230
for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) {
231231
/* XXX is it really best to add NULs if there's no more data */
@@ -245,11 +245,10 @@ binascii_a2b_uu_impl(PyObject *module, Py_buffer *data)
245245
if ( this_ch < ' ' || this_ch > (' ' + 64)) {
246246
state = get_binascii_state(module);
247247
if (state == NULL) {
248-
return NULL;
248+
goto error;
249249
}
250250
PyErr_SetString(state->Error, "Illegal char");
251-
Py_DECREF(rv);
252-
return NULL;
251+
goto error;
253252
}
254253
this_ch = (this_ch - ' ') & 077;
255254
}
@@ -277,14 +276,17 @@ binascii_a2b_uu_impl(PyObject *module, Py_buffer *data)
277276
this_ch != '\n' && this_ch != '\r' ) {
278277
state = get_binascii_state(module);
279278
if (state == NULL) {
280-
return NULL;
279+
goto error;
281280
}
282281
PyErr_SetString(state->Error, "Trailing garbage");
283-
Py_DECREF(rv);
284-
return NULL;
282+
goto error;
285283
}
286284
}
287-
return rv;
285+
return PyBytesWriter_Finish(writer);
286+
287+
error:
288+
PyBytesWriter_Discard(writer);
289+
return NULL;
288290
}
289291

290292
/*[clinic input]
@@ -302,16 +304,13 @@ static PyObject *
302304
binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick)
303305
/*[clinic end generated code: output=b1b99de62d9bbeb8 input=beb27822241095cd]*/
304306
{
305-
unsigned char *ascii_data;
306307
const unsigned char *bin_data;
307308
int leftbits = 0;
308309
unsigned char this_ch;
309310
unsigned int leftchar = 0;
310311
binascii_state *state;
311-
Py_ssize_t bin_len, out_len;
312-
_PyBytesWriter writer;
312+
Py_ssize_t bin_len;
313313

314-
_PyBytesWriter_Init(&writer);
315314
bin_data = data->buf;
316315
bin_len = data->len;
317316
if ( bin_len > 45 ) {
@@ -325,10 +324,12 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick)
325324
}
326325

327326
/* We're lazy and allocate to much (fixed up later) */
328-
out_len = 2 + (bin_len + 2) / 3 * 4;
329-
ascii_data = _PyBytesWriter_Alloc(&writer, out_len);
330-
if (ascii_data == NULL)
327+
Py_ssize_t out_len = 2 + (bin_len + 2) / 3 * 4;
328+
PyBytesWriter *writer = PyBytesWriter_Create(out_len);
329+
if (writer == NULL) {
331330
return NULL;
331+
}
332+
unsigned char *ascii_data = PyBytesWriter_GetData(writer);
332333

333334
/* Store the length */
334335
if (backtick && !bin_len)
@@ -356,7 +357,7 @@ binascii_b2a_uu_impl(PyObject *module, Py_buffer *data, int backtick)
356357
}
357358
*ascii_data++ = '\n'; /* Append a courtesy newline */
358359

359-
return _PyBytesWriter_Finish(&writer, ascii_data);
360+
return PyBytesWriter_FinishWithPointer(writer, ascii_data);
360361
}
361362

362363
/*[clinic input]
@@ -388,12 +389,11 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
388389

389390
/* Allocate the buffer */
390391
Py_ssize_t bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
391-
_PyBytesWriter writer;
392-
_PyBytesWriter_Init(&writer);
393-
unsigned char *bin_data = _PyBytesWriter_Alloc(&writer, bin_len);
394-
if (bin_data == NULL)
392+
PyBytesWriter *writer = PyBytesWriter_Create(bin_len);
393+
if (writer == NULL) {
395394
return NULL;
396-
unsigned char *bin_data_start = bin_data;
395+
}
396+
unsigned char *bin_data = PyBytesWriter_GetData(writer);
397397

398398
if (strict_mode && ascii_len > 0 && ascii_data[0] == '=') {
399399
state = get_binascii_state(module);
@@ -489,12 +489,14 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
489489
state = get_binascii_state(module);
490490
if (state == NULL) {
491491
/* error already set, from get_binascii_state */
492+
assert(PyErr_Occurred());
492493
} else if (quad_pos == 1) {
493494
/*
494495
** There is exactly one extra valid, non-padding, base64 character.
495496
** This is an invalid length, as there is no possible input that
496497
** could encoded into such a base64 string.
497498
*/
499+
unsigned char *bin_data_start = PyBytesWriter_GetData(writer);
498500
PyErr_Format(state->Error,
499501
"Invalid base64-encoded string: "
500502
"number of data characters (%zd) cannot be 1 more "
@@ -503,13 +505,15 @@ binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
503505
} else {
504506
PyErr_SetString(state->Error, "Incorrect padding");
505507
}
506-
error_end:
507-
_PyBytesWriter_Dealloc(&writer);
508-
return NULL;
508+
goto error_end;
509509
}
510510

511511
done:
512-
return _PyBytesWriter_Finish(&writer, bin_data);
512+
return PyBytesWriter_FinishWithPointer(writer, bin_data);
513+
514+
error_end:
515+
PyBytesWriter_Discard(writer);
516+
return NULL;
513517
}
514518

515519

@@ -528,18 +532,15 @@ static PyObject *
528532
binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int newline)
529533
/*[clinic end generated code: output=4ad62c8e8485d3b3 input=0e20ff59c5f2e3e1]*/
530534
{
531-
unsigned char *ascii_data;
532535
const unsigned char *bin_data;
533536
int leftbits = 0;
534537
unsigned char this_ch;
535538
unsigned int leftchar = 0;
536-
Py_ssize_t bin_len, out_len;
537-
_PyBytesWriter writer;
539+
Py_ssize_t bin_len;
538540
binascii_state *state;
539541

540542
bin_data = data->buf;
541543
bin_len = data->len;
542-
_PyBytesWriter_Init(&writer);
543544

544545
assert(bin_len >= 0);
545546

@@ -555,12 +556,15 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int newline)
555556
/* We're lazy and allocate too much (fixed up later).
556557
"+2" leaves room for up to two pad characters.
557558
Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */
558-
out_len = bin_len*2 + 2;
559-
if (newline)
559+
Py_ssize_t out_len = bin_len*2 + 2;
560+
if (newline) {
560561
out_len++;
561-
ascii_data = _PyBytesWriter_Alloc(&writer, out_len);
562-
if (ascii_data == NULL)
562+
}
563+
PyBytesWriter *writer = PyBytesWriter_Create(out_len);
564+
if (writer == NULL) {
563565
return NULL;
566+
}
567+
unsigned char *ascii_data = PyBytesWriter_GetData(writer);
564568

565569
for( ; bin_len > 0 ; bin_len--, bin_data++ ) {
566570
/* Shift the data into our buffer */
@@ -585,7 +589,7 @@ binascii_b2a_base64_impl(PyObject *module, Py_buffer *data, int newline)
585589
if (newline)
586590
*ascii_data++ = '\n'; /* Append a courtesy newline */
587591

588-
return _PyBytesWriter_Finish(&writer, ascii_data);
592+
return PyBytesWriter_FinishWithPointer(writer, ascii_data);
589593
}
590594

591595

@@ -887,8 +891,6 @@ binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr)
887891
{
888892
const char* argbuf;
889893
Py_ssize_t arglen;
890-
PyObject *retval;
891-
char* retbuf;
892894
Py_ssize_t i, j;
893895
binascii_state *state;
894896

@@ -910,29 +912,30 @@ binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr)
910912
return NULL;
911913
}
912914

913-
retval = PyBytes_FromStringAndSize(NULL, (arglen/2));
914-
if (!retval)
915+
PyBytesWriter *writer = PyBytesWriter_Create(arglen/2);
916+
if (writer == NULL) {
915917
return NULL;
916-
retbuf = PyBytes_AS_STRING(retval);
918+
}
919+
char *retbuf = PyBytesWriter_GetData(writer);
917920

918921
for (i=j=0; i < arglen; i += 2) {
919922
unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])];
920923
unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])];
921924
if (top >= 16 || bot >= 16) {
922925
state = get_binascii_state(module);
923926
if (state == NULL) {
924-
return NULL;
927+
goto error;
925928
}
926929
PyErr_SetString(state->Error,
927930
"Non-hexadecimal digit found");
928-
goto finally;
931+
goto error;
929932
}
930933
retbuf[j++] = (top << 4) + bot;
931934
}
932-
return retval;
935+
return PyBytesWriter_Finish(writer);
933936

934-
finally:
935-
Py_DECREF(retval);
937+
error:
938+
PyBytesWriter_Discard(writer);
936939
return NULL;
937940
}
938941

0 commit comments

Comments
 (0)