Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e48944b

Browse files
committed
keep the buffer object around while we're using it (closes #14212)
1 parent 30b8e54 commit e48944b

4 files changed

Lines changed: 65 additions & 34 deletions

File tree

Lib/test/test_re.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from test.support import verbose, run_unittest
1+
from test.support import verbose, run_unittest, gc_collect
2+
import io
23
import re
34
from re import Scanner
45
import sys
@@ -16,6 +17,17 @@
1617

1718
class ReTests(unittest.TestCase):
1819

20+
def test_keep_buffer(self):
21+
# See bug 14212
22+
b = bytearray(b'x')
23+
it = re.finditer(b'a', b)
24+
with self.assertRaises(BufferError):
25+
b.extend(b'x'*400)
26+
list(it)
27+
del it
28+
gc_collect()
29+
b.extend(b'x'*400)
30+
1931
def test_weakref(self):
2032
s = 'QabbbcR'
2133
x = re.compile('ab+c')

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,9 @@ Tests
549549
Extension Modules
550550
-----------------
551551

552+
- Issue #14212: The re module didn't retain a reference to buffers it was
553+
scanning, resulting in segfaults.
554+
552555
- Issue #13840: The error message produced by ctypes.create_string_buffer
553556
when given a Unicode string has been fixed.
554557

Modules/_sre.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,7 +1664,7 @@ state_reset(SRE_STATE* state)
16641664
}
16651665

16661666
static void*
1667-
getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize)
1667+
getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize, Py_buffer *view)
16681668
{
16691669
/* given a python object, return a data pointer, a length (in
16701670
characters), and a character size. return NULL if the object
@@ -1674,7 +1674,6 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize)
16741674
Py_ssize_t size, bytes;
16751675
int charsize;
16761676
void* ptr;
1677-
Py_buffer view;
16781677

16791678
/* Unicode objects do not support the buffer API. So, get the data
16801679
directly instead. */
@@ -1686,26 +1685,21 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize)
16861685
}
16871686

16881687
/* get pointer to string buffer */
1689-
view.len = -1;
1688+
view->len = -1;
16901689
buffer = Py_TYPE(string)->tp_as_buffer;
16911690
if (!buffer || !buffer->bf_getbuffer ||
1692-
(*buffer->bf_getbuffer)(string, &view, PyBUF_SIMPLE) < 0) {
1691+
(*buffer->bf_getbuffer)(string, view, PyBUF_SIMPLE) < 0) {
16931692
PyErr_SetString(PyExc_TypeError, "expected string or buffer");
16941693
return NULL;
16951694
}
16961695

16971696
/* determine buffer size */
1698-
bytes = view.len;
1699-
ptr = view.buf;
1700-
1701-
/* Release the buffer immediately --- possibly dangerous
1702-
but doing something else would require some re-factoring
1703-
*/
1704-
PyBuffer_Release(&view);
1697+
bytes = view->len;
1698+
ptr = view->buf;
17051699

17061700
if (bytes < 0) {
17071701
PyErr_SetString(PyExc_TypeError, "buffer has negative size");
1708-
return NULL;
1702+
goto err;
17091703
}
17101704

17111705
/* determine character size */
@@ -1719,7 +1713,7 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize)
17191713
#endif
17201714
else {
17211715
PyErr_SetString(PyExc_TypeError, "buffer size mismatch");
1722-
return NULL;
1716+
goto err;
17231717
}
17241718

17251719
*p_length = size;
@@ -1728,8 +1722,13 @@ getstring(PyObject* string, Py_ssize_t* p_length, int* p_charsize)
17281722
if (ptr == NULL) {
17291723
PyErr_SetString(PyExc_ValueError,
17301724
"Buffer is NULL");
1725+
goto err;
17311726
}
17321727
return ptr;
1728+
err:
1729+
PyBuffer_Release(view);
1730+
view->buf = NULL;
1731+
return NULL;
17331732
}
17341733

17351734
LOCAL(PyObject*)
@@ -1747,20 +1746,21 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
17471746
state->lastmark = -1;
17481747
state->lastindex = -1;
17491748

1750-
ptr = getstring(string, &length, &charsize);
1749+
state->buffer.buf = NULL;
1750+
ptr = getstring(string, &length, &charsize, &state->buffer);
17511751
if (!ptr)
1752-
return NULL;
1752+
goto err;
17531753

1754-
if (charsize == 1 && pattern->charsize > 1) {
1755-
PyErr_SetString(PyExc_TypeError,
1754+
if (charsize == 1 && pattern->charsize > 1) {
1755+
PyErr_SetString(PyExc_TypeError,
17561756
"can't use a string pattern on a bytes-like object");
1757-
return NULL;
1758-
}
1759-
if (charsize > 1 && pattern->charsize == 1) {
1760-
PyErr_SetString(PyExc_TypeError,
1757+
goto err;
1758+
}
1759+
if (charsize > 1 && pattern->charsize == 1) {
1760+
PyErr_SetString(PyExc_TypeError,
17611761
"can't use a bytes pattern on a string-like object");
1762-
return NULL;
1763-
}
1762+
goto err;
1763+
}
17641764

17651765
/* adjust boundaries */
17661766
if (start < 0)
@@ -1797,11 +1797,17 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
17971797
state->lower = sre_lower;
17981798

17991799
return string;
1800+
err:
1801+
if (state->buffer.buf)
1802+
PyBuffer_Release(&state->buffer);
1803+
return NULL;
18001804
}
18011805

18021806
LOCAL(void)
18031807
state_fini(SRE_STATE* state)
18041808
{
1809+
if (state->buffer.buf)
1810+
PyBuffer_Release(&state->buffer);
18051811
Py_XDECREF(state->string);
18061812
data_stack_dealloc(state);
18071813
}
@@ -1863,6 +1869,8 @@ pattern_dealloc(PatternObject* self)
18631869
{
18641870
if (self->weakreflist != NULL)
18651871
PyObject_ClearWeakRefs((PyObject *) self);
1872+
if (self->view.buf)
1873+
PyBuffer_Release(&self->view);
18661874
Py_XDECREF(self->pattern);
18671875
Py_XDECREF(self->groupindex);
18681876
Py_XDECREF(self->indexgroup);
@@ -2297,6 +2305,7 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
22972305
Py_ssize_t i, b, e;
22982306
int bint;
22992307
int filter_is_callable;
2308+
Py_buffer view;
23002309

23012310
if (PyCallable_Check(ptemplate)) {
23022311
/* sub/subn takes either a function or a template */
@@ -2306,7 +2315,8 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
23062315
} else {
23072316
/* if not callable, check if it's a literal string */
23082317
int literal;
2309-
ptr = getstring(ptemplate, &n, &bint);
2318+
view.buf = NULL;
2319+
ptr = getstring(ptemplate, &n, &bint, &view);
23102320
b = bint;
23112321
if (ptr) {
23122322
if (b == 1) {
@@ -2320,6 +2330,8 @@ pattern_subx(PatternObject* self, PyObject* ptemplate, PyObject* string,
23202330
PyErr_Clear();
23212331
literal = 0;
23222332
}
2333+
if (view.buf)
2334+
PyBuffer_Release(&view);
23232335
if (literal) {
23242336
filter = ptemplate;
23252337
Py_INCREF(filter);
@@ -2661,6 +2673,7 @@ _compile(PyObject* self_, PyObject* args)
26612673
Py_ssize_t groups = 0;
26622674
PyObject* groupindex = NULL;
26632675
PyObject* indexgroup = NULL;
2676+
26642677
if (!PyArg_ParseTuple(args, "OiO!|nOO", &pattern, &flags,
26652678
&PyList_Type, &code, &groups,
26662679
&groupindex, &indexgroup))
@@ -2675,6 +2688,7 @@ _compile(PyObject* self_, PyObject* args)
26752688
self->pattern = NULL;
26762689
self->groupindex = NULL;
26772690
self->indexgroup = NULL;
2691+
self->view.buf = NULL;
26782692

26792693
self->codesize = n;
26802694

@@ -2694,15 +2708,15 @@ _compile(PyObject* self_, PyObject* args)
26942708
return NULL;
26952709
}
26962710

2697-
if (pattern == Py_None)
2698-
self->charsize = -1;
2699-
else {
2700-
Py_ssize_t p_length;
2701-
if (!getstring(pattern, &p_length, &self->charsize)) {
2702-
Py_DECREF(self);
2703-
return NULL;
2704-
}
2705-
}
2711+
if (pattern == Py_None)
2712+
self->charsize = -1;
2713+
else {
2714+
Py_ssize_t p_length;
2715+
if (!getstring(pattern, &p_length, &self->charsize, &self->view)) {
2716+
Py_DECREF(self);
2717+
return NULL;
2718+
}
2719+
}
27062720

27072721
Py_INCREF(pattern);
27082722
self->pattern = pattern;

Modules/sre.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ typedef struct {
3131
int flags; /* flags used when compiling pattern source */
3232
PyObject *weakreflist; /* List of weak references */
3333
int charsize; /* pattern charsize (or -1) */
34+
Py_buffer view;
3435
/* pattern code */
3536
Py_ssize_t codesize;
3637
SRE_CODE code[1];
@@ -80,6 +81,7 @@ typedef struct {
8081
char* data_stack;
8182
size_t data_stack_size;
8283
size_t data_stack_base;
84+
Py_buffer buffer;
8385
/* current repeat context */
8486
SRE_REPEAT *repeat;
8587
/* hooks */

0 commit comments

Comments
 (0)