From 49fc8ece8172162510890f42127d2aa4e13f878b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 7 Jul 2013 23:30:24 +0200 Subject: [PATCH] Issue #18203: Add _PyMem_RawStrdup() and _PyMem_Strdup() Replace strdup() with _PyMem_RawStrdup() or _PyMem_Strdup(), depending if the GIL is held or not. --- Include/pymem.h | 3 +++ Modules/_cursesmodule.c | 8 ++++---- Modules/_pickle.c | 12 ++++++------ Modules/faulthandler.c | 11 ++++++----- Modules/main.c | 4 ++-- Modules/python.c | 6 +++--- Objects/obmalloc.c | 28 ++++++++++++++++++++++++++++ Python/pythonrun.c | 21 ++++++++++++--------- 8 files changed, 64 insertions(+), 29 deletions(-) diff --git a/Include/pymem.h b/Include/pymem.h index 58c52425b46..83f1537f3f5 100644 --- a/Include/pymem.h +++ b/Include/pymem.h @@ -58,6 +58,9 @@ PyAPI_FUNC(void *) PyMem_Malloc(size_t size); PyAPI_FUNC(void *) PyMem_Realloc(void *ptr, size_t new_size); PyAPI_FUNC(void) PyMem_Free(void *ptr); +PyAPI_FUNC(char *) _PyMem_RawStrdup(const char *str); +PyAPI_FUNC(char *) _PyMem_Strdup(const char *str); + /* Macros. */ /* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index fbe18f6e06b..5d1489852d9 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -529,7 +529,7 @@ PyCursesWindow_New(WINDOW *win, const char *encoding) wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type); if (wo == NULL) return NULL; wo->win = win; - wo->encoding = strdup(encoding); + wo->encoding = _PyMem_Strdup(encoding); if (wo->encoding == NULL) { Py_DECREF(wo); PyErr_NoMemory(); @@ -543,7 +543,7 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo) { if (wo->win != stdscr) delwin(wo->win); if (wo->encoding != NULL) - free(wo->encoding); + PyMem_Free(wo->encoding); PyObject_DEL(wo); } @@ -1938,13 +1938,13 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value) ascii = PyUnicode_AsASCIIString(value); if (ascii == NULL) return -1; - encoding = strdup(PyBytes_AS_STRING(ascii)); + encoding = _PyMem_Strdup(PyBytes_AS_STRING(ascii)); Py_DECREF(ascii); if (encoding == NULL) { PyErr_NoMemory(); return -1; } - free(self->encoding); + PyMem_Free(self->encoding); self->encoding = encoding; return 0; } diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 5b309313108..72bd7fce655 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1213,8 +1213,8 @@ _Unpickler_SetInputEncoding(UnpicklerObject *self, if (errors == NULL) errors = "strict"; - self->encoding = strdup(encoding); - self->errors = strdup(errors); + self->encoding = _PyMem_Strdup(encoding); + self->errors = _PyMem_Strdup(errors); if (self->encoding == NULL || self->errors == NULL) { PyErr_NoMemory(); return -1; @@ -5590,8 +5590,8 @@ Unpickler_dealloc(UnpicklerObject *self) _Unpickler_MemoCleanup(self); PyMem_Free(self->marks); PyMem_Free(self->input_line); - free(self->encoding); - free(self->errors); + PyMem_Free(self->encoding); + PyMem_Free(self->errors); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -5627,9 +5627,9 @@ Unpickler_clear(UnpicklerObject *self) self->marks = NULL; PyMem_Free(self->input_line); self->input_line = NULL; - free(self->encoding); + PyMem_Free(self->encoding); self->encoding = NULL; - free(self->errors); + PyMem_Free(self->errors); self->errors = NULL; return 0; diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 686a45a145c..172945d1a40 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -475,7 +475,7 @@ cancel_dump_traceback_later(void) Py_CLEAR(thread.file); if (thread.header) { - free(thread.header); + PyMem_Free(thread.header); thread.header = NULL; } } @@ -504,7 +504,7 @@ format_timeout(double timeout) "Timeout (%lu:%02lu:%02lu)!\n", hour, min, sec); - return strdup(buffer); + return _PyMem_Strdup(buffer); } static PyObject* @@ -570,7 +570,7 @@ faulthandler_dump_traceback_later(PyObject *self, if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) { PyThread_release_lock(thread.running); Py_CLEAR(thread.file); - free(header); + PyMem_Free(header); thread.header = NULL; PyErr_SetString(PyExc_RuntimeError, "unable to start watchdog thread"); @@ -729,9 +729,10 @@ faulthandler_register_py(PyObject *self, return NULL; if (user_signals == NULL) { - user_signals = calloc(NSIG, sizeof(user_signal_t)); + user_signals = PyMem_Malloc(NSIG * sizeof(user_signal_t)); if (user_signals == NULL) return PyErr_NoMemory(); + memset(user_signals, 0, NSIG * sizeof(user_signal_t)); } user = &user_signals[signum]; @@ -1136,7 +1137,7 @@ void _PyFaulthandler_Fini(void) if (user_signals != NULL) { for (signum=0; signum < NSIG; signum++) faulthandler_unregister(&user_signals[signum], signum); - free(user_signals); + PyMem_Free(user_signals); user_signals = NULL; } #endif diff --git a/Modules/main.c b/Modules/main.c index 2bafbfda586..af0d7f40641 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -544,7 +544,7 @@ Py_Main(int argc, wchar_t **argv) Py_FatalError( "not enough memory to copy PYTHONWARNINGS"); strcpy(buf, p); - oldloc = strdup(setlocale(LC_ALL, NULL)); + oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, ""); for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) { #ifdef __APPLE__ @@ -562,7 +562,7 @@ Py_Main(int argc, wchar_t **argv) Py_DECREF(unicode); } setlocale(LC_ALL, oldloc); - free(oldloc); + PyMem_RawFree(oldloc); PyMem_RawFree(buf); } #endif diff --git a/Modules/python.c b/Modules/python.c index aaa7fcff22b..0ad1130f199 100644 --- a/Modules/python.c +++ b/Modules/python.c @@ -43,12 +43,12 @@ main(int argc, char **argv) fpsetmask(m & ~FP_X_OFL); #endif - oldloc = strdup(setlocale(LC_ALL, NULL)); + oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); setlocale(LC_ALL, ""); for (i = 0; i < argc; i++) { argv_copy[i] = _Py_char2wchar(argv[i], NULL); if (!argv_copy[i]) { - free(oldloc); + PyMem_RawFree(oldloc); fprintf(stderr, "Fatal Python error: " "unable to decode the command line argument #%i\n", i + 1); @@ -59,7 +59,7 @@ main(int argc, char **argv) argv_copy2[argc] = argv_copy[argc] = NULL; setlocale(LC_ALL, oldloc); - free(oldloc); + PyMem_RawFree(oldloc); res = Py_Main(argc, argv_copy); for (i = 0; i < argc; i++) { PyMem_RawFree(argv_copy2[i]); diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 97a137db373..8e25229e09f 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -294,6 +294,34 @@ PyMem_Free(void *ptr) _PyMem.free(_PyMem.ctx, ptr); } +char * +_PyMem_RawStrdup(const char *str) +{ + size_t size; + char *copy; + + size = strlen(str) + 1; + copy = PyMem_RawMalloc(size); + if (copy == NULL) + return NULL; + memcpy(copy, str, size); + return copy; +} + +char * +_PyMem_Strdup(const char *str) +{ + size_t size; + char *copy; + + size = strlen(str) + 1; + copy = PyMem_Malloc(size); + if (copy == NULL) + return NULL; + memcpy(copy, str, size); + return copy; +} + void * PyObject_Malloc(size_t size) { diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 94175be87e9..d95a09d4a7e 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -174,7 +174,7 @@ get_codec_name(const char *encoding) name_utf8 = _PyUnicode_AsString(name); if (name_utf8 == NULL) goto error; - name_str = strdup(name_utf8); + name_str = _PyMem_RawStrdup(name_utf8); Py_DECREF(name); if (name_str == NULL) { PyErr_NoMemory(); @@ -626,7 +626,7 @@ Py_Finalize(void) /* reset file system default encoding */ if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) { - free((char*)Py_FileSystemDefaultEncoding); + PyMem_RawFree((char*)Py_FileSystemDefaultEncoding); Py_FileSystemDefaultEncoding = NULL; } @@ -1081,7 +1081,11 @@ initstdio(void) encoding = Py_GETENV("PYTHONIOENCODING"); errors = NULL; if (encoding) { - encoding = strdup(encoding); + encoding = _PyMem_Strdup(encoding); + if (encoding == NULL) { + PyErr_NoMemory(); + goto error; + } errors = strchr(encoding, ':'); if (errors) { *errors = '\0'; @@ -1140,10 +1144,10 @@ initstdio(void) when import.c tries to write to stderr in verbose mode. */ encoding_attr = PyObject_GetAttrString(std, "encoding"); if (encoding_attr != NULL) { - const char * encoding; - encoding = _PyUnicode_AsString(encoding_attr); - if (encoding != NULL) { - PyObject *codec_info = _PyCodec_Lookup(encoding); + const char * std_encoding; + std_encoding = _PyUnicode_AsString(encoding_attr); + if (std_encoding != NULL) { + PyObject *codec_info = _PyCodec_Lookup(std_encoding); Py_XDECREF(codec_info); } Py_DECREF(encoding_attr); @@ -1160,8 +1164,7 @@ initstdio(void) status = -1; } - if (encoding) - free(encoding); + PyMem_Free(encoding); Py_XDECREF(bimod); Py_XDECREF(iomod); return status;