Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-34784: Posixmodule: Heap StructSequence #9665

Merged
merged 12 commits into from
Nov 13, 2018
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix the implementation of PyStructSequence_NewType in order to create heap
allocated StructSequences.
27 changes: 27 additions & 0 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3310,6 +3310,31 @@ test_decref_doesnt_leak(PyObject *ob, PyObject *Py_UNUSED(ignored))
Py_RETURN_NONE;
}

static PyObject *
test_structseq_newtype_doesnt_leak(PyObject *Py_UNUSED(self),
PyObject *Py_UNUSED(args))
{
PyStructSequence_Desc descr;
PyStructSequence_Field descr_fields[3];

descr_fields[0] = (PyStructSequence_Field){"foo", "foo value"};
descr_fields[1] = (PyStructSequence_Field){NULL, "some hidden value"};
descr_fields[2] = (PyStructSequence_Field){0, NULL};

descr.name = "_testcapi.test_descr";
descr.doc = "This is used to test for memory leaks in NewType";
descr.fields = descr_fields;
descr.n_in_sequence = 1;

PyTypeObject* structseq_type = PyStructSequence_NewType(&descr);
assert(structseq_type != NULL);
assert(PyType_Check(structseq_type));
assert(PyType_FastSubclass(structseq_type, Py_TPFLAGS_TUPLE_SUBCLASS));
Py_DECREF(structseq_type);

Py_RETURN_NONE;
}

static PyObject *
test_incref_decref_API(PyObject *ob, PyObject *Py_UNUSED(ignored))
{
Expand Down Expand Up @@ -4863,6 +4888,8 @@ static PyMethodDef TestMethods[] = {
{"test_incref_doesnt_leak", test_incref_doesnt_leak, METH_NOARGS},
{"test_xdecref_doesnt_leak",test_xdecref_doesnt_leak, METH_NOARGS},
{"test_decref_doesnt_leak", test_decref_doesnt_leak, METH_NOARGS},
{"test_structseq_newtype_doesnt_leak",
test_structseq_newtype_doesnt_leak, METH_NOARGS},
{"test_incref_decref_API", test_incref_decref_API, METH_NOARGS},
{"test_long_and_overflow", test_long_and_overflow, METH_NOARGS},
{"test_long_as_double", test_long_as_double, METH_NOARGS},
Expand Down
94 changes: 53 additions & 41 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1948,14 +1948,14 @@ static PyStructSequence_Desc waitid_result_desc = {
waitid_result_fields,
5
};
static PyTypeObject WaitidResultType;
static PyTypeObject* WaitidResultType;
#endif

static int initialized;
static PyTypeObject StatResultType;
static PyTypeObject StatVFSResultType;
static PyTypeObject* StatResultType;
static PyTypeObject* StatVFSResultType;
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
static PyTypeObject SchedParamType;
static PyTypeObject* SchedParamType;
#endif
static newfunc structseq_new;

Expand Down Expand Up @@ -2029,7 +2029,7 @@ static PyObject*
_pystat_fromstructstat(STRUCT_STAT *st)
{
unsigned long ansec, mnsec, cnsec;
PyObject *v = PyStructSequence_New(&StatResultType);
PyObject *v = PyStructSequence_New(StatResultType);
if (v == NULL)
return NULL;

Expand Down Expand Up @@ -4407,7 +4407,7 @@ static PyStructSequence_Desc uname_result_desc = {
5
};

static PyTypeObject UnameResultType;
static PyTypeObject* UnameResultType;


#ifdef HAVE_UNAME
Expand Down Expand Up @@ -4435,7 +4435,7 @@ os_uname_impl(PyObject *module)
if (res < 0)
return posix_error();

value = PyStructSequence_New(&UnameResultType);
value = PyStructSequence_New(UnameResultType);
if (value == NULL)
return NULL;

Expand Down Expand Up @@ -5941,7 +5941,7 @@ os_sched_getscheduler_impl(PyObject *module, pid_t pid)

#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
/*[clinic input]
class os.sched_param "PyObject *" "&SchedParamType"
class os.sched_param "PyObject *" "SchedParamType"

@classmethod
os.sched_param.__new__
Expand All @@ -5954,7 +5954,7 @@ Current has only one field: sched_priority");

static PyObject *
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
/*[clinic end generated code: output=48f4067d60f48c13 input=73a4c22f7071fc62]*/
/*[clinic end generated code: output=48f4067d60f48c13 input=ab4de35a9a7811f2]*/
{
PyObject *res;

Expand Down Expand Up @@ -5986,7 +5986,7 @@ convert_sched_param(PyObject *param, struct sched_param *res)
{
long priority;

if (Py_TYPE(param) != &SchedParamType) {
if (Py_TYPE(param) != SchedParamType) {
PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
return 0;
}
Expand Down Expand Up @@ -6057,7 +6057,7 @@ os_sched_getparam_impl(PyObject *module, pid_t pid)

if (sched_getparam(pid, &param))
return posix_error();
result = PyStructSequence_New(&SchedParamType);
result = PyStructSequence_New(SchedParamType);
if (!result)
return NULL;
priority = PyLong_FromLong(param.sched_priority);
Expand Down Expand Up @@ -7422,7 +7422,7 @@ os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
if (si.si_pid == 0)
Py_RETURN_NONE;

result = PyStructSequence_New(&WaitidResultType);
result = PyStructSequence_New(WaitidResultType);
if (!result)
return NULL;

Expand Down Expand Up @@ -7857,7 +7857,7 @@ static PyStructSequence_Desc times_result_desc = {
5
};

static PyTypeObject TimesResultType;
static PyTypeObject* TimesResultType;

#ifdef MS_WINDOWS
#define HAVE_TIMES /* mandatory, for the method table */
Expand All @@ -7870,7 +7870,7 @@ build_times_result(double user, double system,
double children_user, double children_system,
double elapsed)
{
PyObject *value = PyStructSequence_New(&TimesResultType);
PyObject *value = PyStructSequence_New(TimesResultType);
if (value == NULL)
return NULL;

Expand Down Expand Up @@ -9950,7 +9950,7 @@ os_WSTOPSIG_impl(PyObject *module, int status)

static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st) {
PyObject *v = PyStructSequence_New(&StatVFSResultType);
PyObject *v = PyStructSequence_New(StatVFSResultType);
if (v == NULL)
return NULL;

Expand Down Expand Up @@ -11703,7 +11703,7 @@ os_urandom_impl(PyObject *module, Py_ssize_t size)

/* Terminal size querying */

static PyTypeObject TerminalSizeType;
static PyTypeObject* TerminalSizeType;

PyDoc_STRVAR(TerminalSize_docstring,
"A tuple of (columns, lines) for holding terminal window size");
Expand Down Expand Up @@ -11795,7 +11795,7 @@ get_terminal_size(PyObject *self, PyObject *args)
}
#endif /* TERMSIZE_USE_CONIO */

termsize = PyStructSequence_New(&TerminalSizeType);
termsize = PyStructSequence_New(TerminalSizeType);
if (termsize == NULL)
return NULL;
PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
Expand Down Expand Up @@ -13912,23 +13912,28 @@ INITFUNC(void)
if (!initialized) {
#if defined(HAVE_WAITID) && !defined(__APPLE__)
waitid_result_desc.name = MODNAME ".waitid_result";
if (PyStructSequence_InitType2(&WaitidResultType, &waitid_result_desc) < 0)
WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);
if (WaitidResultType == NULL) {
return NULL;
}
#endif

stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
if (PyStructSequence_InitType2(&StatResultType, &stat_result_desc) < 0)
StatResultType = PyStructSequence_NewType(&stat_result_desc);
if (StatResultType == NULL) {
return NULL;
structseq_new = StatResultType.tp_new;
StatResultType.tp_new = statresult_new;
}
structseq_new = StatResultType->tp_new;
StatResultType->tp_new = statresult_new;

statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
if (PyStructSequence_InitType2(&StatVFSResultType,
&statvfs_result_desc) < 0)
StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);
if (StatVFSResultType == NULL) {
return NULL;
}
#ifdef NEED_TICKS_PER_SECOND
# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
ticks_per_second = sysconf(_SC_CLK_TCK);
Expand All @@ -13941,15 +13946,18 @@ INITFUNC(void)

#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
sched_param_desc.name = MODNAME ".sched_param";
if (PyStructSequence_InitType2(&SchedParamType, &sched_param_desc) < 0)
SchedParamType = PyStructSequence_NewType(&sched_param_desc);
if (SchedParamType == NULL) {
return NULL;
SchedParamType.tp_new = os_sched_param;
}
SchedParamType->tp_new = os_sched_param;
#endif

/* initialize TerminalSize_info */
if (PyStructSequence_InitType2(&TerminalSizeType,
&TerminalSize_desc) < 0)
TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
if (TerminalSizeType == NULL) {
return NULL;
}

/* initialize scandir types */
if (PyType_Ready(&ScandirIteratorType) < 0)
Expand All @@ -13958,29 +13966,33 @@ INITFUNC(void)
return NULL;
}
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_INCREF((PyObject*) &WaitidResultType);
PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType);
Py_INCREF((PyObject*) WaitidResultType);
PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);
#endif
Py_INCREF((PyObject*) &StatResultType);
PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
Py_INCREF((PyObject*) &StatVFSResultType);
Py_INCREF((PyObject*) StatResultType);
PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);
Py_INCREF((PyObject*) StatVFSResultType);
PyModule_AddObject(m, "statvfs_result",
(PyObject*) &StatVFSResultType);
(PyObject*) StatVFSResultType);

#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
Py_INCREF(&SchedParamType);
PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType);
Py_INCREF(SchedParamType);
PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);
#endif

times_result_desc.name = MODNAME ".times_result";
if (PyStructSequence_InitType2(&TimesResultType, &times_result_desc) < 0)
TimesResultType = PyStructSequence_NewType(&times_result_desc);
if (TimesResultType == NULL) {
return NULL;
PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType);
}
PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType);

uname_result_desc.name = MODNAME ".uname_result";
if (PyStructSequence_InitType2(&UnameResultType, &uname_result_desc) < 0)
UnameResultType = PyStructSequence_NewType(&uname_result_desc);
if (UnameResultType == NULL) {
return NULL;
PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType);
}
PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);

#ifdef __APPLE__
/*
Expand Down Expand Up @@ -14020,8 +14032,8 @@ INITFUNC(void)

#endif /* __APPLE__ */

Py_INCREF(&TerminalSizeType);
PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType);
Py_INCREF(TerminalSizeType);
PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);

billion = PyLong_FromLong(1000000000);
if (!billion)
Expand Down
Loading