summaryrefslogtreecommitdiffstats
path: root/Modules/_testcapi
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-08-20 21:07:24 (GMT)
committerGitHub <noreply@github.com>2023-08-20 21:07:24 (GMT)
commit97d67e9dabb3d66525a46dc4d802195ced24e6ef (patch)
tree4501b9e9e344524eb8e6f05e43cc0e5bdf897860 /Modules/_testcapi
parent7f5a741a28a7b87c9cdb1db87fcb3f0b9ed8ac2a (diff)
downloadcpython-97d67e9dabb3d66525a46dc4d802195ced24e6ef.zip
cpython-97d67e9dabb3d66525a46dc4d802195ced24e6ef.tar.gz
cpython-97d67e9dabb3d66525a46dc4d802195ced24e6ef.tar.bz2
[3.12] gh-107915: Handle errors in C API functions PyErr_Set*() and PyErr_Format() (GH-107918) (#108134)
* gh-107915: Handle errors in C API functions PyErr_Set*() and PyErr_Format() (GH-107918) Such C API functions as PyErr_SetString(), PyErr_Format(), PyErr_SetFromErrnoWithFilename() and many others no longer crash or ignore errors if it failed to format the error message or decode the filename. Instead, they keep a corresponding error. (cherry picked from commit 633ea217a85f6b6ba5bdbc73094254d5811b3485) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> * Define PY_SSIZE_T_CLEAN. --------- Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Diffstat (limited to 'Modules/_testcapi')
-rw-r--r--Modules/_testcapi/clinic/exceptions.c.h64
-rw-r--r--Modules/_testcapi/exceptions.c42
2 files changed, 105 insertions, 1 deletions
diff --git a/Modules/_testcapi/clinic/exceptions.c.h b/Modules/_testcapi/clinic/exceptions.c.h
index 01730ff..16954a5 100644
--- a/Modules/_testcapi/clinic/exceptions.c.h
+++ b/Modules/_testcapi/clinic/exceptions.c.h
@@ -215,6 +215,68 @@ exit:
return return_value;
}
+PyDoc_STRVAR(_testcapi_err_setstring__doc__,
+"err_setstring($module, exc, value, /)\n"
+"--\n"
+"\n");
+
+#define _TESTCAPI_ERR_SETSTRING_METHODDEF \
+ {"err_setstring", _PyCFunction_CAST(_testcapi_err_setstring), METH_FASTCALL, _testcapi_err_setstring__doc__},
+
+static PyObject *
+_testcapi_err_setstring_impl(PyObject *module, PyObject *exc,
+ const char *value, Py_ssize_t value_length);
+
+static PyObject *
+_testcapi_err_setstring(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *exc;
+ const char *value;
+ Py_ssize_t value_length;
+
+ if (!_PyArg_ParseStack(args, nargs, "Oz#:err_setstring",
+ &exc, &value, &value_length)) {
+ goto exit;
+ }
+ return_value = _testcapi_err_setstring_impl(module, exc, value, value_length);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_testcapi_err_setfromerrnowithfilename__doc__,
+"err_setfromerrnowithfilename($module, error, exc, value, /)\n"
+"--\n"
+"\n");
+
+#define _TESTCAPI_ERR_SETFROMERRNOWITHFILENAME_METHODDEF \
+ {"err_setfromerrnowithfilename", _PyCFunction_CAST(_testcapi_err_setfromerrnowithfilename), METH_FASTCALL, _testcapi_err_setfromerrnowithfilename__doc__},
+
+static PyObject *
+_testcapi_err_setfromerrnowithfilename_impl(PyObject *module, int error,
+ PyObject *exc, const char *value,
+ Py_ssize_t value_length);
+
+static PyObject *
+_testcapi_err_setfromerrnowithfilename(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ int error;
+ PyObject *exc;
+ const char *value;
+ Py_ssize_t value_length;
+
+ if (!_PyArg_ParseStack(args, nargs, "iOz#:err_setfromerrnowithfilename",
+ &error, &exc, &value, &value_length)) {
+ goto exit;
+ }
+ return_value = _testcapi_err_setfromerrnowithfilename_impl(module, error, exc, value, value_length);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(_testcapi_raise_exception__doc__,
"raise_exception($module, exception, num_args, /)\n"
"--\n"
@@ -426,4 +488,4 @@ _testcapi_unstable_exc_prep_reraise_star(PyObject *module, PyObject *const *args
exit:
return return_value;
}
-/*[clinic end generated code: output=fd6aef54f195c77b input=a9049054013a1b77]*/
+/*[clinic end generated code: output=d574342d716e98b5 input=a9049054013a1b77]*/
diff --git a/Modules/_testcapi/exceptions.c b/Modules/_testcapi/exceptions.c
index a627bf1..4ae9ba4 100644
--- a/Modules/_testcapi/exceptions.c
+++ b/Modules/_testcapi/exceptions.c
@@ -1,6 +1,9 @@
+#define PY_SSIZE_T_CLEAN
#include "parts.h"
#include "clinic/exceptions.c.h"
+#define NULLABLE(x) do { if (x == Py_None) x = NULL; } while (0);
+
/*[clinic input]
module _testcapi
[clinic start generated code]*/
@@ -130,6 +133,43 @@ _testcapi_exc_set_object_fetch_impl(PyObject *module, PyObject *exc,
}
/*[clinic input]
+_testcapi.err_setstring
+ exc: object
+ value: str(zeroes=True, accept={robuffer, str, NoneType})
+ /
+[clinic start generated code]*/
+
+static PyObject *
+_testcapi_err_setstring_impl(PyObject *module, PyObject *exc,
+ const char *value, Py_ssize_t value_length)
+/*[clinic end generated code: output=fba8705e5703dd3f input=e8a95fad66d9004b]*/
+{
+ NULLABLE(exc);
+ PyErr_SetString(exc, value);
+ return NULL;
+}
+
+/*[clinic input]
+_testcapi.err_setfromerrnowithfilename
+ error: int
+ exc: object
+ value: str(zeroes=True, accept={robuffer, str, NoneType})
+ /
+[clinic start generated code]*/
+
+static PyObject *
+_testcapi_err_setfromerrnowithfilename_impl(PyObject *module, int error,
+ PyObject *exc, const char *value,
+ Py_ssize_t value_length)
+/*[clinic end generated code: output=d02df5749a01850e input=ff7c384234bf097f]*/
+{
+ NULLABLE(exc);
+ errno = error;
+ PyErr_SetFromErrnoWithFilename(exc, value);
+ return NULL;
+}
+
+/*[clinic input]
_testcapi.raise_exception
exception as exc: object
num_args: int
@@ -338,6 +378,8 @@ static PyMethodDef test_methods[] = {
_TESTCAPI_MAKE_EXCEPTION_WITH_DOC_METHODDEF
_TESTCAPI_EXC_SET_OBJECT_METHODDEF
_TESTCAPI_EXC_SET_OBJECT_FETCH_METHODDEF
+ _TESTCAPI_ERR_SETSTRING_METHODDEF
+ _TESTCAPI_ERR_SETFROMERRNOWITHFILENAME_METHODDEF
_TESTCAPI_RAISE_EXCEPTION_METHODDEF
_TESTCAPI_RAISE_MEMORYERROR_METHODDEF
_TESTCAPI_SET_EXC_INFO_METHODDEF