From b3e6f44212a1534d0ec05de57fefaa33fe77d9b7 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Tue, 16 May 2023 23:36:19 +0300 Subject: [PATCH 1/7] Fix missing/incomplete NULL checks in multiple source files * `Modules/_cursesmodule.c:_curses_initscr_impl`: pass `screen_encoding` to `PyCursesWindowObject` constructor instead of assigning it to field with possible NULL dereference * `Modules/_zoneinfo.c:update_strong_cache`: check `new_node` value for NULL * `Modules/errnomodule.c:errno_exec`: prevent leak of `error_dict` reference in case if `module_dict` is NULL * `Modules/posixmodule.c:os_setgroups`: check if `grouplist` is allocated, raise `MemoryError` otherwise * `Modules/sha1module.c:newSHA1object`: check `sha` value for NULL * `Modules/zlibmodule.c:ZlibDecompressor__new__`: check `self` value for NULL --- Modules/_cursesmodule.c | 5 +---- Modules/_zoneinfo.c | 3 +++ Modules/errnomodule.c | 1 + Modules/posixmodule.c | 4 ++++ Modules/sha1module.c | 3 +++ Modules/zlibmodule.c | 3 +++ 6 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5691a419a32f8e..a9f06e625a500a 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3252,7 +3252,6 @@ _curses_initscr_impl(PyObject *module) /*[clinic end generated code: output=619fb68443810b7b input=514f4bce1821f6b5]*/ { WINDOW *win; - PyCursesWindowObject *winobj; if (initialised) { wrefresh(stdscr); @@ -3348,9 +3347,7 @@ _curses_initscr_impl(PyObject *module) SetDictInt("LINES", LINES); SetDictInt("COLS", COLS); - winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); - screen_encoding = winobj->encoding; - return (PyObject *)winobj; + return (PyObject *)PyCursesWindow_New(win, screen_encoding); } /*[clinic input] diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index c8c791b6d7c0d8..a179cd76ae89fb 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -2572,6 +2572,9 @@ update_strong_cache(zoneinfo_state *state, const PyTypeObject *const type, } StrongCacheNode *new_node = strong_cache_node_new(key, zone); + if (new_node == NULL) { + return; + } StrongCacheNode **root = &(state->ZONEINFO_STRONG_CACHE); move_strong_cache_node_to_front(state, root, new_node); diff --git a/Modules/errnomodule.c b/Modules/errnomodule.c index fddde960a5fe9a..3d0c2d7ae945bc 100644 --- a/Modules/errnomodule.c +++ b/Modules/errnomodule.c @@ -84,6 +84,7 @@ errno_exec(PyObject *module) PyObject *module_dict = PyModule_GetDict(module); PyObject *error_dict = PyDict_New(); if (!module_dict || !error_dict) { + Py_XDECREF(error_dict); return -1; } if (PyDict_SetItemString(module_dict, "errorcode", error_dict) < 0) { diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 5022fdeb03703a..5280e25c052e9b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9023,6 +9023,10 @@ os_setgroups(PyObject *module, PyObject *groups) } gid_t *grouplist = PyMem_New(gid_t, len); + if (grouplist == NULL) { + PyErr_NoMemory(); + return NULL; + } for (Py_ssize_t i = 0; i < len; i++) { PyObject *elem; elem = PySequence_GetItem(groups, i); diff --git a/Modules/sha1module.c b/Modules/sha1module.c index bdb76c56f1a6e8..909587d24a521b 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -71,6 +71,9 @@ static SHA1object * newSHA1object(SHA1State *st) { SHA1object *sha = (SHA1object *)PyObject_GC_New(SHA1object, st->sha1_type); + if (sha == NULL) { + return NULL; + } PyObject_GC_Track(sha); return sha; } diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index b67844a67c315c..534d065765f0f9 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -1722,6 +1722,9 @@ ZlibDecompressor__new__(PyTypeObject *cls, return NULL; } ZlibDecompressor *self = PyObject_New(ZlibDecompressor, cls); + if (self == NULL) { + return NULL; + } self->eof = 0; self->needs_input = 1; self->avail_in_real = 0; From b621e3791165dea380e5caf233f8d9eb1670378f Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Wed, 17 May 2023 12:40:12 +0300 Subject: [PATCH 2/7] updated _cursesmodule.c --- Modules/_cursesmodule.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index a9f06e625a500a..f9984fa722187c 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3252,6 +3252,7 @@ _curses_initscr_impl(PyObject *module) /*[clinic end generated code: output=619fb68443810b7b input=514f4bce1821f6b5]*/ { WINDOW *win; + PyCursesWindowObject *winobj; if (initialised) { wrefresh(stdscr); @@ -3347,7 +3348,12 @@ _curses_initscr_impl(PyObject *module) SetDictInt("LINES", LINES); SetDictInt("COLS", COLS); - return (PyObject *)PyCursesWindow_New(win, screen_encoding); + winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); + if (winobj == NULL) { + return NULL; + } + screen_encoding = winobj->encoding; + return (PyObject *)winobj; } /*[clinic input] From bf131ede1dd5187c2453be70dc409fd2db8c04e2 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Wed, 17 May 2023 17:30:39 +0300 Subject: [PATCH 3/7] set MemoryError in strong_cache_node_new --- Modules/_zoneinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index a179cd76ae89fb..dc70c6e01a2797 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -2387,6 +2387,7 @@ strong_cache_node_new(PyObject *key, PyObject *zone) { StrongCacheNode *node = PyMem_Malloc(sizeof(StrongCacheNode)); if (node == NULL) { + PyErr_NoMemory(); return NULL; } From 1d5ab2d6380389f254b02d8c148c26521aab479d Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Wed, 17 May 2023 17:34:04 +0300 Subject: [PATCH 4/7] revert strong_cache_node_new change --- Modules/_zoneinfo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index dc70c6e01a2797..a179cd76ae89fb 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -2387,7 +2387,6 @@ strong_cache_node_new(PyObject *key, PyObject *zone) { StrongCacheNode *node = PyMem_Malloc(sizeof(StrongCacheNode)); if (node == NULL) { - PyErr_NoMemory(); return NULL; } From 7ae74e6e2357e7993ea5335469eec31f07f83ec5 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Mon, 22 May 2023 13:53:47 +0300 Subject: [PATCH 5/7] reverted _curses change --- Modules/_cursesmodule.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index f9984fa722187c..5691a419a32f8e 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -3349,9 +3349,6 @@ _curses_initscr_impl(PyObject *module) SetDictInt("COLS", COLS); winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); - if (winobj == NULL) { - return NULL; - } screen_encoding = winobj->encoding; return (PyObject *)winobj; } From e414f1d83f678910fb87b1595601422b58785d35 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov Date: Mon, 22 May 2023 23:24:57 +0300 Subject: [PATCH 6/7] clarified in strong_cache_node_new comment why it doesn't set exception if allocation fails --- Modules/_zoneinfo.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c index a179cd76ae89fb..0dcdb4da47d5db 100644 --- a/Modules/_zoneinfo.c +++ b/Modules/_zoneinfo.c @@ -2381,7 +2381,12 @@ get_local_timestamp(PyObject *dt, int64_t *local_ts) ///// // Functions for cache handling -/* Constructor for StrongCacheNode */ +/* Constructor for StrongCacheNode + * + * This function doesn't set MemoryError if PyMem_Malloc fails, + * as the cache intentionally doesn't propagate exceptions + * and fails silently if error occurs. + */ static StrongCacheNode * strong_cache_node_new(PyObject *key, PyObject *zone) { From 242d22e70e276055de93355e01853d586bd9e50c Mon Sep 17 00:00:00 2001 From: chgnrdv <52372310+chgnrdv@users.noreply.github.com> Date: Tue, 23 May 2023 03:39:14 +0300 Subject: [PATCH 7/7] removed accidental newline in sha1module.c --- Modules/sha1module.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/sha1module.c b/Modules/sha1module.c index d367f2b4149033..ef8e067dd337b3 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -73,7 +73,6 @@ static SHA1object * newSHA1object(SHA1State *st) { SHA1object *sha = (SHA1object *)PyObject_GC_New(SHA1object, st->sha1_type); - if (sha == NULL) { return NULL; }