diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 34529bce496d88..b5b1321a6bae85 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -331,12 +331,19 @@ _ctypes_alloc_format_string(const char *prefix, const char *suffix) return NULL; } len = strlen(suffix); - if (prefix) - len += strlen(prefix); + if (prefix) { + size_t prefix_len = strlen(prefix); + if (len > PY_SIZE_MAX - prefix_len) { + goto oom; + } + len += prefix_len; + } + if (len == PY_SIZE_MAX) { + goto oom; + } result = PyMem_Malloc(len + 1); if (result == NULL) { - PyErr_NoMemory(); - return NULL; + goto oom; } if (prefix) strcpy(result, prefix); @@ -344,6 +351,10 @@ _ctypes_alloc_format_string(const char *prefix, const char *suffix) result[0] = '\0'; strcat(result, suffix); return result; + +oom: + PyErr_NoMemory(); + return NULL; } /* @@ -363,12 +374,16 @@ _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape, int k; prefix_len = 32 * ndim + 3; - if (prefix) - prefix_len += strlen(prefix); + if (prefix) { + size_t l = strlen(prefix); + if ((size_t)prefix > (size_t)PY_SSIZE_T_MAX - l) { + goto oom; + } + prefix_len += l; + } new_prefix = PyMem_Malloc(prefix_len); if (new_prefix == NULL) { - PyErr_NoMemory(); - return NULL; + goto oom; } new_prefix[0] = '\0'; if (prefix) @@ -388,6 +403,10 @@ _ctypes_alloc_format_string_with_shape(int ndim, const Py_ssize_t *shape, result = _ctypes_alloc_format_string(new_prefix, suffix); PyMem_Free(new_prefix); return result; + +oom: + PyErr_NoMemory(); + return NULL; } /* StructParamObject and StructParam_Type are used in _ctypes_callproc() @@ -1666,7 +1685,7 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) if (stginfo->format == NULL) goto error; stginfo->ndim = iteminfo->ndim + 1; - stginfo->shape = PyMem_Malloc(sizeof(Py_ssize_t) * stginfo->ndim); + stginfo->shape = PyMem_New(Py_ssize_t, stginfo->ndim); if (stginfo->shape == NULL) { PyErr_NoMemory(); goto error; @@ -3094,7 +3113,7 @@ PyCData_MallocBuffer(CDataObject *obj, StgInfo *info) /* In python 2.4, and ctypes 0.9.6, the malloc call took about 33% of the creation time for c_int(). */ - obj->b_ptr = (char *)PyMem_Malloc(info->size); + obj->b_ptr = PyMem_New(char, info->size); if (obj->b_ptr == NULL) { PyErr_NoMemory(); return -1; @@ -4775,7 +4794,7 @@ Array_subscript(PyObject *myself, PyObject *item) return PyBytes_FromStringAndSize(ptr + start, slicelen); } - dest = (char *)PyMem_Malloc(slicelen); + dest = PyMem_New(char, slicelen); if (dest == NULL) return PyErr_NoMemory(); @@ -5461,7 +5480,7 @@ Pointer_subscript(PyObject *myself, PyObject *item) return PyBytes_FromStringAndSize(ptr + start, len); } - dest = (char *)PyMem_Malloc(len); + dest = PyMem_New(char, len); if (dest == NULL) return PyErr_NoMemory(); for (cur = start, i = 0; i < len; cur += step, i++) { diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 5dbbe0b3285d58..9aa2ab38f38577 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -23,8 +23,6 @@ int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info) { - Py_ssize_t size; - ctype_clear_stginfo(dst_info); PyMem_Free(dst_info->ffi_type_pointer.elements); PyMem_Free(dst_info->format); @@ -43,18 +41,20 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info) Py_XINCREF(dst_info->module); if (src_info->format) { - dst_info->format = PyMem_Malloc(strlen(src_info->format) + 1); + size_t s = strlen(src_info->format); + if (s >= (size_t)PY_SSIZE_T_MAX) { + goto oom; + } + dst_info->format = PyMem_Malloc(s + 1); if (dst_info->format == NULL) { - PyErr_NoMemory(); - return -1; + goto oom; } strcpy(dst_info->format, src_info->format); } if (src_info->shape) { - dst_info->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src_info->ndim); + dst_info->shape = PyMem_New(Py_ssize_t, src_info->ndim); if (dst_info->shape == NULL) { - PyErr_NoMemory(); - return -1; + goto oom; } memcpy(dst_info->shape, src_info->shape, sizeof(Py_ssize_t) * src_info->ndim); @@ -62,16 +62,28 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info) if (src_info->ffi_type_pointer.elements == NULL) return 0; - size = sizeof(ffi_type *) * (src_info->length + 1); + if ((size_t)src_info->length > (size_t)PY_SSIZE_T_MAX / sizeof(ffi_type *) - 1) { + goto oom; + } + Py_ssize_t size = sizeof(ffi_type *) * (src_info->length + 1); dst_info->ffi_type_pointer.elements = PyMem_Malloc(size); if (dst_info->ffi_type_pointer.elements == NULL) { - PyErr_NoMemory(); - return -1; + goto oom; } memcpy(dst_info->ffi_type_pointer.elements, src_info->ffi_type_pointer.elements, size); return 0; + +oom: + if (src_info->format) { + PyMem_Free(dst_info->format); + } + if (src_info->shape) { + PyMem_Free(dst_info->shape); + } + PyErr_NoMemory(); + return -1; } /* descr is the descriptor for a field marked as anonymous. Get all the @@ -331,6 +343,10 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct PyMem_Free(stginfo->format); stginfo->format = NULL; } + if (format_spec_size >= PY_SSIZE_T_MAX) { + PyErr_NoMemory(); + goto error; + } stginfo->format = PyMem_Malloc(format_spec_size + 1); if (!stginfo->format) { PyErr_NoMemory(); @@ -564,8 +580,9 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct * dummy fields standing in for array elements, and the * ffi_types representing the dummy structures. */ - alloc_size = (ffi_ofs + 1 + len + num_ffi_type_pointers) * sizeof(ffi_type *) + - num_ffi_types * sizeof(ffi_type); + // TODO: check if this can overflow + alloc_size = (ffi_ofs + 1 + len + num_ffi_type_pointers) * sizeof(ffi_type *) + + num_ffi_types * sizeof(ffi_type); type_block = PyMem_Malloc(alloc_size); if (type_block == NULL) { diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 040ffa81153ebe..d0cf83d1d3bb23 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -5186,6 +5186,7 @@ cursesmodule_exec(PyObject *module) continue; } if (strncmp(key_name, "KEY_F(", 6) == 0) { + // We may assume that the name has a small enough length. char *fn_key_name = PyMem_Malloc(strlen(key_name) + 1); if (!fn_key_name) { PyErr_NoMemory(); diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index c564813036e504..ffa3d85e957120 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2116,10 +2116,10 @@ numeric_as_ascii(PyObject *u, int strip_ws, int ignore_underscores) data = PyUnicode_DATA(u); len = PyUnicode_GET_LENGTH(u); + // Note: this should not overflow since the number of digits is << 2^32. cp = res = PyMem_Malloc(len+1); if (res == NULL) { - PyErr_NoMemory(); - return NULL; + goto oom; } j = 0; @@ -2155,6 +2155,10 @@ numeric_as_ascii(PyObject *u, int strip_ws, int ignore_underscores) } *cp = '\0'; return res; + +oom: + PyErr_NoMemory(); + return NULL; } /* Return a new PyDecObject or a subtype from a C string. Use the context @@ -2689,6 +2693,7 @@ dectuple_as_str(PyObject *dectuple) tsize = PyTuple_Size(digits); /* [sign][coeffdigits+1][E][-][expdigits+1]['\0'] */ + // TODO: this should not overflow since we would be below the digits limit mem = 1 + tsize + 3 + MPD_EXPDIGITS + 2; cp = decstring = PyMem_Malloc(mem); if (decstring == NULL) { @@ -3377,6 +3382,7 @@ dec_repr(PyObject *dec) static char * dec_strdup(const char *src, Py_ssize_t size) { + // Note: this should not overflow since the number of digits is << 2^32. char *dest = PyMem_Malloc(size+1); if (dest == NULL) { PyErr_NoMemory(); diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 791ee070401fe5..1e6afb863f9fb0 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -465,6 +465,10 @@ _PyIncrementalNewlineDecoder_decode(PyObject *myself, when there is something to translate. On the other hand, we already know there is a \r byte, so chances are high that something needs to be done. */ + if (len > PY_SSIZE_T_MAX / kind) { + PyErr_NoMemory(); + goto error; + } translated = PyMem_Malloc(kind * len); if (translated == NULL) { PyErr_NoMemory(); diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 3fa0301e337991..b15ce46c302898 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -610,7 +610,7 @@ static wchar_t * read_console_w(HANDLE handle, DWORD maxlen, DWORD *readlen) { int err = 0, sig = 0; - wchar_t *buf = (wchar_t*)PyMem_Malloc(maxlen * sizeof(wchar_t)); + wchar_t *buf = PyMem_New(wchar_t, maxlen); if (!buf) { PyErr_NoMemory(); goto error; @@ -875,8 +875,10 @@ _io__WindowsConsoleIO_readall_impl(winconsoleio *self) return NULL; bufsize = BUFSIZ; - - buf = (wchar_t*)PyMem_Malloc((bufsize + 1) * sizeof(wchar_t)); + // Note: BUFSIZ is small enough not to overflow, so no need + // to check that 'bufsize + 1' overflows. However, we + // still need to check (bufsize + 1) * sizeof(wchar_t). + buf = PyMem_New(wchar_t, bufsize); if (buf == NULL) { PyErr_NoMemory(); return NULL; diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index 876627bcf5fad8..84e72706a3e67f 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -642,7 +642,11 @@ static PyObject * decode_strings(const char *result, size_t max_count) { /* Convert a sequence of NUL-separated C strings to a Python string - * containing semicolon separated items. */ + * containing semicolon separated items. + * + * For efficiency purposes, we assume that messages to be translated + * are not absurdly large so that 'i' never overflows. + */ size_t i = 0; size_t count = 0; for (; count < max_count && result[i]; count++) { diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 9eef7c25636899..15be84e11a51fd 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -502,6 +502,7 @@ _multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value, } if (!unlink) { + // We may assume that the name has a small enough length. name_copy = PyMem_Malloc(strlen(name) + 1); if (name_copy == NULL) { return PyErr_NoMemory(); @@ -555,6 +556,7 @@ _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle, char *name_copy = NULL; if (name != NULL) { + // We may assume that the name has a small enough length. name_copy = PyMem_Malloc(strlen(name) + 1); if (name_copy == NULL) return PyErr_NoMemory(); diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index ad6d7ceda84e37..53dc3874472e23 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -1125,13 +1125,16 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, if (extra_group_size < 0) goto cleanup; - if (extra_group_size > MAX_GROUPS) { + if (extra_group_size > MAX_GROUPS + || (size_t)extra_group_size > (size_t)PY_SSIZE_T_MAX / sizeof(gid_t)) + { PyErr_SetString(PyExc_ValueError, "too many extra_groups"); goto cleanup; } /* Deliberately keep extra_groups == NULL for extra_group_size == 0 */ if (extra_group_size > 0) { + /* extra_group_size < MAX_GROUPS */ extra_groups = PyMem_RawMalloc(extra_group_size * sizeof(gid_t)); if (extra_groups == NULL) { PyErr_SetString(PyExc_MemoryError, @@ -1192,7 +1195,7 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, #endif /* HAVE_SETREUID */ } - c_fds_to_keep = PyMem_Malloc(fds_to_keep_len * sizeof(int)); + c_fds_to_keep = PyMem_New(int, fds_to_keep_len); if (c_fds_to_keep == NULL) { PyErr_SetString(PyExc_MemoryError, "failed to malloc c_fds_to_keep"); goto cleanup; diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index ad66df47349db0..72ac316e78b8a9 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -524,10 +524,10 @@ _random_Random_getrandbits_impl(RandomObject *self, int k) return PyLong_FromUnsignedLong(genrand_uint32(self) >> (32 - k)); words = (k - 1) / 32 + 1; + // words * 4 always fits on int if k fits on ints (and thus fits on size_t) wordarray = (uint32_t *)PyMem_Malloc(words * 4); if (wordarray == NULL) { - PyErr_NoMemory(); - return NULL; + goto oom; } /* Fill-out bits of long integer, by 32-bit words, from least significant @@ -548,6 +548,10 @@ _random_Random_getrandbits_impl(RandomObject *self, int k) PY_LITTLE_ENDIAN, 0 /* unsigned */); PyMem_Free(wordarray); return result; + +oom: + PyErr_NoMemory(); + return NULL; } static int diff --git a/Modules/_scproxy.c b/Modules/_scproxy.c index e9170f2ce1ae87..403a1216efc032 100644 --- a/Modules/_scproxy.c +++ b/Modules/_scproxy.c @@ -36,6 +36,7 @@ cfstring_to_pystring(CFStringRef ref) PyObject* result; char* buf; + // TODO: can this overflow? buf = PyMem_Malloc(len*4); if (buf == NULL) { PyErr_NoMemory(); diff --git a/Modules/_struct.c b/Modules/_struct.c index 21582b945be23d..e1581bfadc392c 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1725,7 +1725,7 @@ prepare_s(PyStructObject *self) } /* check for overflow */ - if ((ncodes + 1) > ((size_t)PY_SSIZE_T_MAX / sizeof(formatcode))) { + if (ncodes > ((size_t)PY_SSIZE_T_MAX / sizeof(formatcode)) - 1) { PyErr_NoMemory(); return -1; } diff --git a/Modules/_winapi.c b/Modules/_winapi.c index 4ce689fe30e6df..a52fcf54e8ef30 100644 --- a/Modules/_winapi.c +++ b/Modules/_winapi.c @@ -1653,6 +1653,7 @@ _winapi_GetShortPathName_impl(PyObject *module, LPCWSTR path) cchBuffer = GetShortPathNameW(path, NULL, 0); Py_END_ALLOW_THREADS if (cchBuffer) { + // Note: the path length is way smaller than the max alloc. size. WCHAR *buffer = (WCHAR *)PyMem_Malloc(cchBuffer * sizeof(WCHAR)); if (buffer) { Py_BEGIN_ALLOW_THREADS diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index c5292575c22f23..eb6e9f4ff2207d 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -1021,12 +1021,14 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) self->num_transitions = (size_t)num_transitions; self->num_ttinfos = (size_t)num_ttinfos; + // TODO: can this overflow? // Load the transition indices and list self->trans_list_utc = PyMem_Malloc(self->num_transitions * sizeof(int64_t)); if (self->trans_list_utc == NULL) { goto error; } + // TODO: can this overflow? trans_idx = PyMem_Malloc(self->num_transitions * sizeof(Py_ssize_t)); if (trans_idx == NULL) { goto error; @@ -1064,6 +1066,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) } // Load UTC offsets and isdst (size num_ttinfos) + // TODO: can this overflow? utcoff = PyMem_Malloc(self->num_ttinfos * sizeof(long)); isdst = PyMem_Malloc(self->num_ttinfos * sizeof(unsigned char)); @@ -1111,6 +1114,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj) } // Build _ttinfo objects from utcoff, dstoff and abbr + // TODO: can this overflow? self->_ttinfos = PyMem_Malloc(self->num_ttinfos * sizeof(_ttinfo)); if (self->_ttinfos == NULL) { goto error; @@ -2115,6 +2119,7 @@ ts_to_local(size_t *trans_idx, int64_t *trans_utc, long *utcoff, // Copy the UTC transitions into each array to be modified in place later for (size_t i = 0; i < 2; ++i) { + // TODO: can this overflow? trans_local[i] = PyMem_Malloc(num_transitions * sizeof(int64_t)); if (trans_local[i] == NULL) { return -1; diff --git a/Modules/getpath.c b/Modules/getpath.c index 18ddfaf8dbce1a..f423f59e111307 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -261,6 +261,7 @@ getpath_joinpath(PyObject *Py_UNUSED(self), PyObject *args) return Py_GetConstant(Py_CONSTANT_EMPTY_STR); } /* Convert all parts to wchar and accumulate max final length */ + // TODO: can this overflow? wchar_t **parts = (wchar_t **)PyMem_Malloc(n * sizeof(wchar_t *)); if (parts == NULL) { PyErr_NoMemory(); @@ -292,6 +293,7 @@ getpath_joinpath(PyObject *Py_UNUSED(self), PyObject *args) cchFinal += cch + 1; } + // TODO: can this overflow? wchar_t *final = cchFinal > 0 ? (wchar_t *)PyMem_Malloc(cchFinal * sizeof(wchar_t)) : NULL; if (!final) { for (Py_ssize_t i = 0; i < n; ++i) { diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 29638114dd94a9..36f16390107999 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2661,6 +2661,7 @@ math_hypot_impl(PyObject *module, PyObject * const *args, double *coordinates = coord_on_stack; if (args_length > NUM_STACK_ELEMS) { + // Number of coordinates should be way smaller than the max alloc. size. coordinates = (double *) PyMem_Malloc(args_length * sizeof(double)); if (coordinates == NULL) { return PyErr_NoMemory(); diff --git a/Objects/abstract.c b/Objects/abstract.c index f6647874d732f6..b801afcdf3f22a 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -705,8 +705,7 @@ int PyObject_CopyData(PyObject *dest, PyObject *src) /* Otherwise a more elaborate copy scheme is needed */ - /* XXX(nnorwitz): need to check for overflow! */ - indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*view_src.ndim); + indices = PyMem_New(Py_ssize_t, view_src.ndim); if (indices == NULL) { PyErr_NoMemory(); PyBuffer_Release(&view_dest); diff --git a/Objects/call.c b/Objects/call.c index b1610dababd466..749e13066f0749 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -484,10 +484,13 @@ _PyObject_Call_Prepend(PyThreadState *tstate, PyObject *callable, PyObject **stack; Py_ssize_t argcount = PyTuple_GET_SIZE(args); - if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { + if (argcount <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack) - 1) { stack = small_stack; } else { + // Note: argcount + 1 is likely small enough not to overflow + // and we don't want to hurt performances by adding an + // additional check. stack = PyMem_Malloc((argcount + 1) * sizeof(PyObject *)); if (stack == NULL) { PyErr_NoMemory(); @@ -794,6 +797,9 @@ object_vacall(PyThreadState *tstate, PyObject *base, stack = small_stack; } else { + // Note: nargs is likely small enough not to overflow and + // we don't want to hurt performances by adding an + // additional check. stack = PyMem_Malloc(nargs * sizeof(stack[0])); if (stack == NULL) { PyErr_NoMemory(); diff --git a/Objects/capsule.c b/Objects/capsule.c index 28965e0f21b7a0..18783d05c9033f 100644 --- a/Objects/capsule.c +++ b/Objects/capsule.c @@ -230,6 +230,7 @@ PyCapsule_Import(const char *name, int no_block) PyObject *object = NULL; void *return_value = NULL; char *trace; + // Note: strlen(name) is likely smaller than the max alloc. size. size_t name_length = (strlen(name) + 1) * sizeof(char); char *name_dup = (char *)PyMem_Malloc(name_length); diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 1c9f86438dadc3..8bf576badc3344 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -776,6 +776,7 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode) dk = _Py_FREELIST_POP_MEM(dictkeys); } if (dk == NULL) { + // TODO: should we check for an overflow? dk = PyMem_Malloc(sizeof(PyDictKeysObject) + ((size_t)1 << log2_bytes) + entry_size * usable); @@ -826,6 +827,7 @@ values_size_from_count(size_t count) size_t suffix_size = _Py_SIZE_ROUND_UP(count, sizeof(PyObject *)); assert(suffix_size < 128); assert(suffix_size % sizeof(PyObject *) == 0); + // TODO: should we check for an overflow? return (count + 1) * sizeof(PyObject *) + suffix_size; } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index bcc77287454768..80ac53d51af8d8 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -968,6 +968,8 @@ double_round(double x, int ndigits) { buflen = buf_end - buf; if (buflen + 8 > mybuflen) { mybuflen = buflen+8; + // Note: the number of digits to round is likely + // way smaller than the max alloc. size. mybuf = (char *)PyMem_Malloc(mybuflen); if (mybuf == NULL) { PyErr_NoMemory(); diff --git a/Objects/listobject.c b/Objects/listobject.c index 3832295600a0ab..1f0bfcc17eebde 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3637,8 +3637,7 @@ list_ass_subscript_lock_held(PyObject *_self, PyObject *item, PyObject *value) step = -step; } - garbage = (PyObject**) - PyMem_Malloc(slicelength*sizeof(PyObject*)); + garbage = PyMem_New(PyObject *, slicelength); if (!garbage) { PyErr_NoMemory(); return -1; diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index 25634f997ac66b..8cb3b8043e1a4f 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -413,6 +413,7 @@ copy_single(PyMemoryViewObject *self, const Py_buffer *dest, const Py_buffer *sr return -1; if (!last_dim_is_contiguous(dest, src)) { + // TODO: should we check for an overflow? mem = PyMem_Malloc(dest->shape[0] * dest->itemsize); if (mem == NULL) { PyErr_NoMemory(); @@ -445,6 +446,7 @@ copy_buffer(const Py_buffer *dest, const Py_buffer *src) return -1; if (!last_dim_is_contiguous(dest, src)) { + // TODO: should we check for an overflow? mem = PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize); if (mem == NULL) { PyErr_NoMemory(); @@ -503,6 +505,7 @@ buffer_to_contiguous(char *mem, const Py_buffer *src, char order) assert(src->shape != NULL); assert(src->strides != NULL); + // TODO: should we check for an overflow? strides = PyMem_Malloc(src->ndim * (sizeof *src->strides)); if (strides == NULL) { PyErr_NoMemory(); @@ -861,6 +864,7 @@ static int mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt) { if (fmt != NULL) { + // TODO: should we check for an overflow? char *cp = PyMem_Malloc(strlen(fmt)+1); if (cp == NULL) { PyErr_NoMemory(); @@ -1065,6 +1069,7 @@ PyBuffer_ToContiguous(void *buf, const Py_buffer *src, Py_ssize_t len, char orde } /* buffer_to_contiguous() assumes PyBUF_FULL */ + // TODO: should we check for an overflow? fb = PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array)); if (fb == NULL) { PyErr_NoMemory(); diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 2cc0377f68f990..6af1ebd705c9f9 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1060,6 +1060,7 @@ char * _PyMem_Strdup(const char *str) { assert(str != NULL); + // TODO: should we check for an overflow? size_t size = strlen(str) + 1; char *copy = PyMem_Malloc(size); if (copy == NULL) { diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2068d6aa9be52b..78b621ffa2d303 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4041,7 +4041,9 @@ type_new_set_doc(PyTypeObject *type) return -1; } - // Silently truncate the docstring if it contains a null byte + // Silently truncate the docstring if it contains a null byte. + // Note: the docstring length is likely smaller than the max + // alloc. size. Py_ssize_t size = strlen(doc_str) + 1; char *tp_doc = (char *)PyMem_Malloc(size); if (tp_doc == NULL) { @@ -4825,6 +4827,8 @@ PyType_FromMetaclass( * of any such flag. * So, we use a separate buffer, _ht_tpname, that's always * deallocated with the type (if it's non-NULL). + * + * Note: the type name length is way smaller than the max alloc. size. */ Py_ssize_t name_buf_len = strlen(spec->name) + 1; _ht_tpname = PyMem_Malloc(name_buf_len);