gh-94808:Improve coverage of PyObject_Print (GH-98749)

This commit is contained in:
MonadChains 2024-04-01 13:52:25 +01:00 committed by GitHub
parent 348cf6e007
commit 90c3c68a65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 197 additions and 2 deletions

View file

@ -162,7 +162,7 @@
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c

133
Modules/_testcapi/object.c Normal file
View file

@ -0,0 +1,133 @@
#include "parts.h"
#include "util.h"
static PyObject *
call_pyobject_print(PyObject *self, PyObject * args)
{
PyObject *object;
PyObject *filename;
PyObject *print_raw;
FILE *fp;
int flags = 0;
if (!PyArg_UnpackTuple(args, "call_pyobject_print", 3, 3,
&object, &filename, &print_raw)) {
return NULL;
}
fp = _Py_fopen_obj(filename, "w+");
if (Py_IsTrue(print_raw)) {
flags = Py_PRINT_RAW;
}
if (PyObject_Print(object, fp, flags) < 0) {
fclose(fp);
return NULL;
}
fclose(fp);
Py_RETURN_NONE;
}
static PyObject *
pyobject_print_null(PyObject *self, PyObject *args)
{
PyObject *filename;
FILE *fp;
if (!PyArg_UnpackTuple(args, "call_pyobject_print", 1, 1, &filename)) {
return NULL;
}
fp = _Py_fopen_obj(filename, "w+");
if (PyObject_Print(NULL, fp, 0) < 0) {
fclose(fp);
return NULL;
}
fclose(fp);
Py_RETURN_NONE;
}
static PyObject *
pyobject_print_noref_object(PyObject *self, PyObject *args)
{
PyObject *test_string;
PyObject *filename;
FILE *fp;
char correct_string[100];
test_string = PyUnicode_FromString("Spam spam spam");
Py_SET_REFCNT(test_string, 0);
PyOS_snprintf(correct_string, 100, "<refcnt %zd at %p>",
Py_REFCNT(test_string), (void *)test_string);
if (!PyArg_UnpackTuple(args, "call_pyobject_print", 1, 1, &filename)) {
return NULL;
}
fp = _Py_fopen_obj(filename, "w+");
if (PyObject_Print(test_string, fp, 0) < 0){
fclose(fp);
return NULL;
}
fclose(fp);
Py_SET_REFCNT(test_string, 1);
Py_DECREF(test_string);
return PyUnicode_FromString(correct_string);
}
static PyObject *
pyobject_print_os_error(PyObject *self, PyObject *args)
{
PyObject *test_string;
PyObject *filename;
FILE *fp;
test_string = PyUnicode_FromString("Spam spam spam");
if (!PyArg_UnpackTuple(args, "call_pyobject_print", 1, 1, &filename)) {
return NULL;
}
// open file in read mode to induce OSError
fp = _Py_fopen_obj(filename, "r");
if (PyObject_Print(test_string, fp, 0) < 0) {
fclose(fp);
return NULL;
}
fclose(fp);
Py_RETURN_NONE;
}
static PyMethodDef test_methods[] = {
{"call_pyobject_print", call_pyobject_print, METH_VARARGS},
{"pyobject_print_null", pyobject_print_null, METH_VARARGS},
{"pyobject_print_noref_object", pyobject_print_noref_object, METH_VARARGS},
{"pyobject_print_os_error", pyobject_print_os_error, METH_VARARGS},
{NULL},
};
int
_PyTestCapi_Init_Object(PyObject *m)
{
if (PyModule_AddFunctions(m, test_methods) < 0) {
return -1;
}
return 0;
}

View file

@ -57,5 +57,6 @@ int _PyTestCapi_Init_Immortal(PyObject *module);
int _PyTestCapi_Init_GC(PyObject *module);
int _PyTestCapi_Init_Hash(PyObject *module);
int _PyTestCapi_Init_Time(PyObject *module);
int _PyTestCapi_Init_Object(PyObject *module);
#endif // Py_TESTCAPI_PARTS_H

View file

@ -4049,6 +4049,9 @@ PyInit__testcapi(void)
if (_PyTestCapi_Init_Time(m) < 0) {
return NULL;
}
if (_PyTestCapi_Init_Object(m) < 0) {
return NULL;
}
PyState_AddModule(m, &_testcapimodule);
return m;