summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/_ctypes.c62
-rw-r--r--Modules/_ctypes/ctypes.h3
-rw-r--r--Modules/_ctypes/stgdict.c7
-rw-r--r--Modules/_io/textio.c9
-rw-r--r--Modules/_operator.c2
-rw-r--r--Modules/_sre.c15
-rw-r--r--Modules/faulthandler.c4
-rw-r--r--Modules/gcmodule.c34
-rw-r--r--Modules/sre.h1
-rw-r--r--Modules/sre_lib.h20
10 files changed, 111 insertions, 46 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 97ae798..01adbb5 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -289,6 +289,48 @@ _ctypes_alloc_format_string(const char *prefix, const char *suffix)
}
/*
+ Allocate a memory block for a pep3118 format string, adding
+ the given prefix (if non-null), an additional shape prefix, and a suffix.
+ Returns NULL on failure, with the error indicator set. If called with
+ a suffix of NULL the error indicator must already be set.
+ */
+char *
+_ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape,
+ const char *prefix, const char *suffix)
+{
+ char *new_prefix;
+ char *result;
+ char buf[32];
+ int prefix_len;
+ int k;
+
+ prefix_len = 32 * ndim + 3;
+ if (prefix)
+ prefix_len += strlen(prefix);
+ new_prefix = PyMem_Malloc(prefix_len);
+ if (new_prefix == NULL)
+ return NULL;
+ new_prefix[0] = '\0';
+ if (prefix)
+ strcpy(new_prefix, prefix);
+ if (ndim > 0) {
+ /* Add the prefix "(shape[0],shape[1],...,shape[ndim-1])" */
+ strcat(new_prefix, "(");
+ for (k = 0; k < ndim; ++k) {
+ if (k < ndim-1) {
+ sprintf(buf, "%"PY_FORMAT_SIZE_T"d,", shape[k]);
+ } else {
+ sprintf(buf, "%"PY_FORMAT_SIZE_T"d)", shape[k]);
+ }
+ strcat(new_prefix, buf);
+ }
+ }
+ result = _ctypes_alloc_format_string(new_prefix, suffix);
+ PyMem_Free(new_prefix);
+ return result;
+}
+
+/*
PyCStructType_Type - a meta type/class. Creating a new class using this one as
__metaclass__ will call the contructor StructUnionType_new. It replaces the
tp_dict member with a new instance of StgDict, and initializes the C
@@ -860,14 +902,21 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (proto) {
StgDictObject *itemdict = PyType_stgdict(proto);
+ const char *current_format;
assert(itemdict);
/* If itemdict->format is NULL, then this is a pointer to an
incomplete type. We create a generic format string
'pointer to bytes' in this case. XXX Better would be to
fix the format string later...
*/
- stgdict->format = _ctypes_alloc_format_string("&",
- itemdict->format ? itemdict->format : "B");
+ current_format = itemdict->format ? itemdict->format : "B";
+ if (itemdict->shape != NULL) {
+ /* pointer to an array: the shape needs to be prefixed */
+ stgdict->format = _ctypes_alloc_format_string_with_shape(
+ itemdict->ndim, itemdict->shape, "&", current_format);
+ } else {
+ stgdict->format = _ctypes_alloc_format_string("&", current_format);
+ }
if (stgdict->format == NULL) {
Py_DECREF((PyObject *)stgdict);
return NULL;
@@ -1245,7 +1294,6 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
long length;
int overflow;
Py_ssize_t itemsize, itemalign;
- char buf[32];
/* create the new instance (which is a class,
since we are a metatype!) */
@@ -1295,13 +1343,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
assert(itemdict->format);
- if (itemdict->format[0] == '(') {
- sprintf(buf, "(%ld,", length);
- stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format+1);
- } else {
- sprintf(buf, "(%ld)", length);
- stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format);
- }
+ stgdict->format = _ctypes_alloc_format_string(NULL, itemdict->format);
if (stgdict->format == NULL)
goto error;
stgdict->ndim = itemdict->ndim + 1;
diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h
index 5237ac2..ac8341e 100644
--- a/Modules/_ctypes/ctypes.h
+++ b/Modules/_ctypes/ctypes.h
@@ -357,6 +357,9 @@ extern void _ctypes_add_traceback(char *, char *, int);
extern PyObject *PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr);
extern char *_ctypes_alloc_format_string(const char *prefix, const char *suffix);
+extern char *_ctypes_alloc_format_string_with_shape(int ndim,
+ const Py_ssize_t *shape,
+ const char *prefix, const char *suffix);
extern int _ctypes_simple_instance(PyObject *obj);
diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c
index b95b0a4..728f751 100644
--- a/Modules/_ctypes/stgdict.c
+++ b/Modules/_ctypes/stgdict.c
@@ -505,7 +505,12 @@ PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct
sprintf(buf, "%s:%s:", fieldfmt, fieldname);
ptr = stgdict->format;
- stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
+ if (dict->shape != NULL) {
+ stgdict->format = _ctypes_alloc_format_string_with_shape(
+ dict->ndim, dict->shape, stgdict->format, buf);
+ } else {
+ stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
+ }
PyMem_Free(ptr);
PyMem_Free(buf);
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index 5739bc4..ba5789d 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -1297,7 +1297,7 @@ textiowrapper_write(textio *self, PyObject *args)
PyObject *b;
Py_ssize_t textlen;
int haslf = 0;
- int needflush = 0;
+ int needflush = 0, text_needflush = 0;
CHECK_INITIALIZED(self);
@@ -1331,8 +1331,8 @@ textiowrapper_write(textio *self, PyObject *args)
}
if (self->write_through)
- needflush = 1;
- else if (self->line_buffering &&
+ text_needflush = 1;
+ if (self->line_buffering &&
(haslf ||
PyUnicode_FindChar(text, '\r', 0, PyUnicode_GET_LENGTH(text), 1) != -1))
needflush = 1;
@@ -1363,7 +1363,8 @@ textiowrapper_write(textio *self, PyObject *args)
}
self->pending_bytes_count += PyBytes_GET_SIZE(b);
Py_DECREF(b);
- if (self->pending_bytes_count > self->chunk_size || needflush) {
+ if (self->pending_bytes_count > self->chunk_size || needflush ||
+ text_needflush) {
if (_textiowrapper_writeflush(self) < 0)
return NULL;
}
diff --git a/Modules/_operator.c b/Modules/_operator.c
index e8bef04..adeb99e 100644
--- a/Modules/_operator.c
+++ b/Modules/_operator.c
@@ -277,7 +277,7 @@ compare_digest(PyObject *self, PyObject *args)
Py_buffer view_a;
Py_buffer view_b;
- if ((PyObject_CheckBuffer(a) == 0) & (PyObject_CheckBuffer(b) == 0)) {
+ if (PyObject_CheckBuffer(a) == 0 && PyObject_CheckBuffer(b) == 0) {
PyErr_Format(PyExc_TypeError,
"unsupported operand types(s) or combination of types: "
"'%.100s' and '%.100s'",
diff --git a/Modules/_sre.c b/Modules/_sre.c
index eb1106a..300d883 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -505,14 +505,14 @@ pattern_dealloc(PatternObject* self)
}
LOCAL(Py_ssize_t)
-sre_match(SRE_STATE* state, SRE_CODE* pattern)
+sre_match(SRE_STATE* state, SRE_CODE* pattern, int match_all)
{
if (state->charsize == 1)
- return sre_ucs1_match(state, pattern);
+ return sre_ucs1_match(state, pattern, match_all);
if (state->charsize == 2)
- return sre_ucs2_match(state, pattern);
+ return sre_ucs2_match(state, pattern, match_all);
assert(state->charsize == 4);
- return sre_ucs4_match(state, pattern);
+ return sre_ucs4_match(state, pattern, match_all);
}
LOCAL(Py_ssize_t)
@@ -576,7 +576,7 @@ pattern_match(PatternObject *self, PyObject *args, PyObject *kwargs)
TRACE(("|%p|%p|MATCH\n", PatternObject_GetCode(self), state.ptr));
- status = sre_match(&state, PatternObject_GetCode(self));
+ status = sre_match(&state, PatternObject_GetCode(self), 0);
TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr));
if (PyErr_Occurred())
@@ -609,12 +609,11 @@ pattern_fullmatch(PatternObject* self, PyObject* args, PyObject* kw)
if (!string)
return NULL;
- state.match_all = 1;
state.ptr = state.start;
TRACE(("|%p|%p|FULLMATCH\n", PatternObject_GetCode(self), state.ptr));
- status = sre_match(&state, PatternObject_GetCode(self));
+ status = sre_match(&state, PatternObject_GetCode(self), 1);
TRACE(("|%p|%p|END\n", PatternObject_GetCode(self), state.ptr));
if (PyErr_Occurred())
@@ -2572,7 +2571,7 @@ scanner_match(ScannerObject* self, PyObject *unused)
state->ptr = state->start;
- status = sre_match(state, PatternObject_GetCode(self->pattern));
+ status = sre_match(state, PatternObject_GetCode(self->pattern), 0);
if (PyErr_Occurred())
return NULL;
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index fff960f..6a145dc 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -144,6 +144,10 @@ faulthandler_get_fileno(PyObject *file, int *p_fd)
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr");
return NULL;
}
+ if (file == Py_None) {
+ PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None");
+ return NULL;
+ }
}
result = _PyObject_CallMethodId(file, &PyId_fileno, "");
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 6281a7c..9bb3666 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -776,28 +776,40 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
return 0;
}
+/* Run first-time finalizers (if any) on all the objects in collectable.
+ * Note that this may remove some (or even all) of the objects from the
+ * list, due to refcounts falling to 0.
+ */
static void
-finalize_garbage(PyGC_Head *collectable, PyGC_Head *old)
+finalize_garbage(PyGC_Head *collectable)
{
destructor finalize;
- PyGC_Head *gc = collectable->gc.gc_next;
+ PyGC_Head seen;
+
+ /* While we're going through the loop, `finalize(op)` may cause op, or
+ * other objects, to be reclaimed via refcounts falling to zero. So
+ * there's little we can rely on about the structure of the input
+ * `collectable` list across iterations. For safety, we always take the
+ * first object in that list and move it to a temporary `seen` list.
+ * If objects vanish from the `collectable` and `seen` lists we don't
+ * care.
+ */
+ gc_list_init(&seen);
- for (; gc != collectable; gc = gc->gc.gc_next) {
+ while (!gc_list_is_empty(collectable)) {
+ PyGC_Head *gc = collectable->gc.gc_next;
PyObject *op = FROM_GC(gc);
-
+ gc_list_move(gc, &seen);
if (!_PyGCHead_FINALIZED(gc) &&
- PyType_HasFeature(Py_TYPE(op), Py_TPFLAGS_HAVE_FINALIZE) &&
- (finalize = Py_TYPE(op)->tp_finalize) != NULL) {
+ PyType_HasFeature(Py_TYPE(op), Py_TPFLAGS_HAVE_FINALIZE) &&
+ (finalize = Py_TYPE(op)->tp_finalize) != NULL) {
_PyGCHead_SET_FINALIZED(gc, 1);
Py_INCREF(op);
finalize(op);
- if (Py_REFCNT(op) == 1) {
- /* op will be destroyed */
- gc = gc->gc.gc_prev;
- }
Py_DECREF(op);
}
}
+ gc_list_merge(&seen, collectable);
}
/* Walk the collectable list and check that they are really unreachable
@@ -1006,7 +1018,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
m += handle_weakrefs(&unreachable, old);
/* Call tp_finalize on objects which have one. */
- finalize_garbage(&unreachable, old);
+ finalize_garbage(&unreachable);
if (check_garbage(&unreachable)) {
revive_garbage(&unreachable);
diff --git a/Modules/sre.h b/Modules/sre.h
index 621e2d8..42fe28d 100644
--- a/Modules/sre.h
+++ b/Modules/sre.h
@@ -86,7 +86,6 @@ typedef struct {
SRE_REPEAT *repeat;
/* hooks */
SRE_TOLOWER_HOOK lower;
- int match_all;
} SRE_STATE;
typedef struct {
diff --git a/Modules/sre_lib.h b/Modules/sre_lib.h
index df86697..5c6c5a5 100644
--- a/Modules/sre_lib.h
+++ b/Modules/sre_lib.h
@@ -173,7 +173,7 @@ SRE(charset)(SRE_CODE* set, SRE_CODE ch)
}
}
-LOCAL(Py_ssize_t) SRE(match)(SRE_STATE* state, SRE_CODE* pattern);
+LOCAL(Py_ssize_t) SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all);
LOCAL(Py_ssize_t)
SRE(count)(SRE_STATE* state, SRE_CODE* pattern, Py_ssize_t maxcount)
@@ -259,7 +259,7 @@ SRE(count)(SRE_STATE* state, SRE_CODE* pattern, Py_ssize_t maxcount)
/* repeated single character pattern */
TRACE(("|%p|%p|COUNT SUBPATTERN\n", pattern, ptr));
while ((SRE_CHAR*) state->ptr < end) {
- i = SRE(match)(state, pattern);
+ i = SRE(match)(state, pattern, 0);
if (i < 0)
return i;
if (!i)
@@ -490,7 +490,7 @@ typedef struct {
/* check if string matches the given pattern. returns <0 for
error, 0 for failure, and 1 for success */
LOCAL(Py_ssize_t)
-SRE(match)(SRE_STATE* state, SRE_CODE* pattern)
+SRE(match)(SRE_STATE* state, SRE_CODE* pattern, int match_all)
{
SRE_CHAR* end = (SRE_CHAR *)state->end;
Py_ssize_t alloc_pos, ctx_pos = -1;
@@ -507,7 +507,7 @@ SRE(match)(SRE_STATE* state, SRE_CODE* pattern)
ctx->last_ctx_pos = -1;
ctx->jump = JUMP_NONE;
ctx->pattern = pattern;
- ctx->match_all = state->match_all;
+ ctx->match_all = match_all;
ctx_pos = alloc_pos;
entrance:
@@ -739,7 +739,7 @@ entrance:
RETURN_FAILURE;
if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS &&
- (!ctx->match_all || ctx->ptr == state->end)) {
+ ctx->ptr == state->end) {
/* tail is empty. we're finished */
state->ptr = ctx->ptr;
RETURN_SUCCESS;
@@ -824,7 +824,7 @@ entrance:
}
if (ctx->pattern[ctx->pattern[0]] == SRE_OP_SUCCESS &&
- (!ctx->match_all || ctx->ptr == state->end)) {
+ (!match_all || ctx->ptr == state->end)) {
/* tail is empty. we're finished */
state->ptr = ctx->ptr;
RETURN_SUCCESS;
@@ -1269,7 +1269,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
state->ptr = ptr - (prefix_len - prefix_skip - 1);
if (flags & SRE_INFO_LITERAL)
return 1; /* we got all of it */
- status = SRE(match)(state, pattern + 2*prefix_skip);
+ status = SRE(match)(state, pattern + 2*prefix_skip, 0);
if (status != 0)
return status;
/* close but no cigar -- try again */
@@ -1302,7 +1302,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
state->ptr = ++ptr;
if (flags & SRE_INFO_LITERAL)
return 1; /* we got all of it */
- status = SRE(match)(state, pattern + 2);
+ status = SRE(match)(state, pattern + 2, 0);
if (status != 0)
break;
}
@@ -1317,7 +1317,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
TRACE(("|%p|%p|SEARCH CHARSET\n", pattern, ptr));
state->start = ptr;
state->ptr = ptr;
- status = SRE(match)(state, pattern);
+ status = SRE(match)(state, pattern, 0);
if (status != 0)
break;
ptr++;
@@ -1327,7 +1327,7 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
while (ptr <= end) {
TRACE(("|%p|%p|SEARCH\n", pattern, ptr));
state->start = state->ptr = ptr++;
- status = SRE(match)(state, pattern);
+ status = SRE(match)(state, pattern, 0);
if (status != 0)
break;
}