diff options
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 62 | ||||
-rw-r--r-- | Modules/_ctypes/ctypes.h | 3 | ||||
-rw-r--r-- | Modules/_ctypes/stgdict.c | 7 | ||||
-rw-r--r-- | Modules/_io/textio.c | 9 | ||||
-rw-r--r-- | Modules/_operator.c | 2 | ||||
-rw-r--r-- | Modules/_sre.c | 15 | ||||
-rw-r--r-- | Modules/faulthandler.c | 4 | ||||
-rw-r--r-- | Modules/gcmodule.c | 34 | ||||
-rw-r--r-- | Modules/sre.h | 1 | ||||
-rw-r--r-- | Modules/sre_lib.h | 20 |
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; } |