Issue #18203: Add _PyMem_RawStrdup() and _PyMem_Strdup()

Replace strdup() with _PyMem_RawStrdup() or _PyMem_Strdup(), depending if the
GIL is held or not.
This commit is contained in:
Victor Stinner 2013-07-07 23:30:24 +02:00
parent 6f8eeee7b9
commit 49fc8ece81
8 changed files with 64 additions and 29 deletions

View File

@ -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_Realloc(void *ptr, size_t new_size);
PyAPI_FUNC(void) PyMem_Free(void *ptr); PyAPI_FUNC(void) PyMem_Free(void *ptr);
PyAPI_FUNC(char *) _PyMem_RawStrdup(const char *str);
PyAPI_FUNC(char *) _PyMem_Strdup(const char *str);
/* Macros. */ /* Macros. */
/* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL /* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL

View File

@ -529,7 +529,7 @@ PyCursesWindow_New(WINDOW *win, const char *encoding)
wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type); wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type);
if (wo == NULL) return NULL; if (wo == NULL) return NULL;
wo->win = win; wo->win = win;
wo->encoding = strdup(encoding); wo->encoding = _PyMem_Strdup(encoding);
if (wo->encoding == NULL) { if (wo->encoding == NULL) {
Py_DECREF(wo); Py_DECREF(wo);
PyErr_NoMemory(); PyErr_NoMemory();
@ -543,7 +543,7 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo)
{ {
if (wo->win != stdscr) delwin(wo->win); if (wo->win != stdscr) delwin(wo->win);
if (wo->encoding != NULL) if (wo->encoding != NULL)
free(wo->encoding); PyMem_Free(wo->encoding);
PyObject_DEL(wo); PyObject_DEL(wo);
} }
@ -1938,13 +1938,13 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value)
ascii = PyUnicode_AsASCIIString(value); ascii = PyUnicode_AsASCIIString(value);
if (ascii == NULL) if (ascii == NULL)
return -1; return -1;
encoding = strdup(PyBytes_AS_STRING(ascii)); encoding = _PyMem_Strdup(PyBytes_AS_STRING(ascii));
Py_DECREF(ascii); Py_DECREF(ascii);
if (encoding == NULL) { if (encoding == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
free(self->encoding); PyMem_Free(self->encoding);
self->encoding = encoding; self->encoding = encoding;
return 0; return 0;
} }

View File

@ -1213,8 +1213,8 @@ _Unpickler_SetInputEncoding(UnpicklerObject *self,
if (errors == NULL) if (errors == NULL)
errors = "strict"; errors = "strict";
self->encoding = strdup(encoding); self->encoding = _PyMem_Strdup(encoding);
self->errors = strdup(errors); self->errors = _PyMem_Strdup(errors);
if (self->encoding == NULL || self->errors == NULL) { if (self->encoding == NULL || self->errors == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
@ -5590,8 +5590,8 @@ Unpickler_dealloc(UnpicklerObject *self)
_Unpickler_MemoCleanup(self); _Unpickler_MemoCleanup(self);
PyMem_Free(self->marks); PyMem_Free(self->marks);
PyMem_Free(self->input_line); PyMem_Free(self->input_line);
free(self->encoding); PyMem_Free(self->encoding);
free(self->errors); PyMem_Free(self->errors);
Py_TYPE(self)->tp_free((PyObject *)self); Py_TYPE(self)->tp_free((PyObject *)self);
} }
@ -5627,9 +5627,9 @@ Unpickler_clear(UnpicklerObject *self)
self->marks = NULL; self->marks = NULL;
PyMem_Free(self->input_line); PyMem_Free(self->input_line);
self->input_line = NULL; self->input_line = NULL;
free(self->encoding); PyMem_Free(self->encoding);
self->encoding = NULL; self->encoding = NULL;
free(self->errors); PyMem_Free(self->errors);
self->errors = NULL; self->errors = NULL;
return 0; return 0;

View File

@ -475,7 +475,7 @@ cancel_dump_traceback_later(void)
Py_CLEAR(thread.file); Py_CLEAR(thread.file);
if (thread.header) { if (thread.header) {
free(thread.header); PyMem_Free(thread.header);
thread.header = NULL; thread.header = NULL;
} }
} }
@ -504,7 +504,7 @@ format_timeout(double timeout)
"Timeout (%lu:%02lu:%02lu)!\n", "Timeout (%lu:%02lu:%02lu)!\n",
hour, min, sec); hour, min, sec);
return strdup(buffer); return _PyMem_Strdup(buffer);
} }
static PyObject* static PyObject*
@ -570,7 +570,7 @@ faulthandler_dump_traceback_later(PyObject *self,
if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) { if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) {
PyThread_release_lock(thread.running); PyThread_release_lock(thread.running);
Py_CLEAR(thread.file); Py_CLEAR(thread.file);
free(header); PyMem_Free(header);
thread.header = NULL; thread.header = NULL;
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"unable to start watchdog thread"); "unable to start watchdog thread");
@ -729,9 +729,10 @@ faulthandler_register_py(PyObject *self,
return NULL; return NULL;
if (user_signals == 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) if (user_signals == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
memset(user_signals, 0, NSIG * sizeof(user_signal_t));
} }
user = &user_signals[signum]; user = &user_signals[signum];
@ -1136,7 +1137,7 @@ void _PyFaulthandler_Fini(void)
if (user_signals != NULL) { if (user_signals != NULL) {
for (signum=0; signum < NSIG; signum++) for (signum=0; signum < NSIG; signum++)
faulthandler_unregister(&user_signals[signum], signum); faulthandler_unregister(&user_signals[signum], signum);
free(user_signals); PyMem_Free(user_signals);
user_signals = NULL; user_signals = NULL;
} }
#endif #endif

View File

@ -544,7 +544,7 @@ Py_Main(int argc, wchar_t **argv)
Py_FatalError( Py_FatalError(
"not enough memory to copy PYTHONWARNINGS"); "not enough memory to copy PYTHONWARNINGS");
strcpy(buf, p); strcpy(buf, p);
oldloc = strdup(setlocale(LC_ALL, NULL)); oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) { for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) {
#ifdef __APPLE__ #ifdef __APPLE__
@ -562,7 +562,7 @@ Py_Main(int argc, wchar_t **argv)
Py_DECREF(unicode); Py_DECREF(unicode);
} }
setlocale(LC_ALL, oldloc); setlocale(LC_ALL, oldloc);
free(oldloc); PyMem_RawFree(oldloc);
PyMem_RawFree(buf); PyMem_RawFree(buf);
} }
#endif #endif

View File

@ -43,12 +43,12 @@ main(int argc, char **argv)
fpsetmask(m & ~FP_X_OFL); fpsetmask(m & ~FP_X_OFL);
#endif #endif
oldloc = strdup(setlocale(LC_ALL, NULL)); oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
argv_copy[i] = _Py_char2wchar(argv[i], NULL); argv_copy[i] = _Py_char2wchar(argv[i], NULL);
if (!argv_copy[i]) { if (!argv_copy[i]) {
free(oldloc); PyMem_RawFree(oldloc);
fprintf(stderr, "Fatal Python error: " fprintf(stderr, "Fatal Python error: "
"unable to decode the command line argument #%i\n", "unable to decode the command line argument #%i\n",
i + 1); i + 1);
@ -59,7 +59,7 @@ main(int argc, char **argv)
argv_copy2[argc] = argv_copy[argc] = NULL; argv_copy2[argc] = argv_copy[argc] = NULL;
setlocale(LC_ALL, oldloc); setlocale(LC_ALL, oldloc);
free(oldloc); PyMem_RawFree(oldloc);
res = Py_Main(argc, argv_copy); res = Py_Main(argc, argv_copy);
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
PyMem_RawFree(argv_copy2[i]); PyMem_RawFree(argv_copy2[i]);

View File

@ -294,6 +294,34 @@ PyMem_Free(void *ptr)
_PyMem.free(_PyMem.ctx, 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 * void *
PyObject_Malloc(size_t size) PyObject_Malloc(size_t size)
{ {

View File

@ -174,7 +174,7 @@ get_codec_name(const char *encoding)
name_utf8 = _PyUnicode_AsString(name); name_utf8 = _PyUnicode_AsString(name);
if (name_utf8 == NULL) if (name_utf8 == NULL)
goto error; goto error;
name_str = strdup(name_utf8); name_str = _PyMem_RawStrdup(name_utf8);
Py_DECREF(name); Py_DECREF(name);
if (name_str == NULL) { if (name_str == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
@ -626,7 +626,7 @@ Py_Finalize(void)
/* reset file system default encoding */ /* reset file system default encoding */
if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) { if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
free((char*)Py_FileSystemDefaultEncoding); PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
Py_FileSystemDefaultEncoding = NULL; Py_FileSystemDefaultEncoding = NULL;
} }
@ -1081,7 +1081,11 @@ initstdio(void)
encoding = Py_GETENV("PYTHONIOENCODING"); encoding = Py_GETENV("PYTHONIOENCODING");
errors = NULL; errors = NULL;
if (encoding) { if (encoding) {
encoding = strdup(encoding); encoding = _PyMem_Strdup(encoding);
if (encoding == NULL) {
PyErr_NoMemory();
goto error;
}
errors = strchr(encoding, ':'); errors = strchr(encoding, ':');
if (errors) { if (errors) {
*errors = '\0'; *errors = '\0';
@ -1140,10 +1144,10 @@ initstdio(void)
when import.c tries to write to stderr in verbose mode. */ when import.c tries to write to stderr in verbose mode. */
encoding_attr = PyObject_GetAttrString(std, "encoding"); encoding_attr = PyObject_GetAttrString(std, "encoding");
if (encoding_attr != NULL) { if (encoding_attr != NULL) {
const char * encoding; const char * std_encoding;
encoding = _PyUnicode_AsString(encoding_attr); std_encoding = _PyUnicode_AsString(encoding_attr);
if (encoding != NULL) { if (std_encoding != NULL) {
PyObject *codec_info = _PyCodec_Lookup(encoding); PyObject *codec_info = _PyCodec_Lookup(std_encoding);
Py_XDECREF(codec_info); Py_XDECREF(codec_info);
} }
Py_DECREF(encoding_attr); Py_DECREF(encoding_attr);
@ -1160,8 +1164,7 @@ initstdio(void)
status = -1; status = -1;
} }
if (encoding) PyMem_Free(encoding);
free(encoding);
Py_XDECREF(bimod); Py_XDECREF(bimod);
Py_XDECREF(iomod); Py_XDECREF(iomod);
return status; return status;