summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_capi/test_file.py25
-rw-r--r--Modules/_testcapi/clinic/file.c.h25
-rw-r--r--Modules/_testcapi/file.c8
3 files changed, 33 insertions, 25 deletions
diff --git a/Lib/test/test_capi/test_file.py b/Lib/test/test_capi/test_file.py
index 8a08a0a..a67a512 100644
--- a/Lib/test/test_capi/test_file.py
+++ b/Lib/test/test_capi/test_file.py
@@ -5,6 +5,8 @@ from test.support import import_helper, os_helper
_testcapi = import_helper.import_module('_testcapi')
+NULL = None
+
class CAPIFileTest(unittest.TestCase):
def test_py_fopen(self):
@@ -25,7 +27,9 @@ class CAPIFileTest(unittest.TestCase):
os_helper.TESTFN,
os.fsencode(os_helper.TESTFN),
]
- # TESTFN_UNDECODABLE cannot be used to create a file on macOS/WASI.
+ if os_helper.TESTFN_UNDECODABLE is not None:
+ filenames.append(os_helper.TESTFN_UNDECODABLE)
+ filenames.append(os.fsdecode(os_helper.TESTFN_UNDECODABLE))
if os_helper.TESTFN_UNENCODABLE is not None:
filenames.append(os_helper.TESTFN_UNENCODABLE)
for filename in filenames:
@@ -33,7 +37,12 @@ class CAPIFileTest(unittest.TestCase):
try:
with open(filename, "wb") as fp:
fp.write(source)
-
+ except OSError:
+ # TESTFN_UNDECODABLE cannot be used to create a file
+ # on macOS/WASI.
+ filename = None
+ continue
+ try:
data = _testcapi.py_fopen(filename, "rb")
self.assertEqual(data, source[:256])
finally:
@@ -47,7 +56,14 @@ class CAPIFileTest(unittest.TestCase):
# non-ASCII mode failing with "Invalid argument"
with self.assertRaises(OSError):
- _testcapi.py_fopen(__file__, "\xe9")
+ _testcapi.py_fopen(__file__, b"\xc2\x80")
+ with self.assertRaises(OSError):
+ # \x98 is invalid in cp1250, cp1251, cp1257
+ # \x9d is invalid in cp1252-cp1255, cp1258
+ _testcapi.py_fopen(__file__, b"\xc2\x98\xc2\x9d")
+ # UnicodeDecodeError can come from the audit hook code
+ with self.assertRaises((UnicodeDecodeError, OSError)):
+ _testcapi.py_fopen(__file__, b"\x98\x9d")
# invalid filename type
for invalid_type in (123, object()):
@@ -60,7 +76,8 @@ class CAPIFileTest(unittest.TestCase):
# On Windows, the file mode is limited to 10 characters
_testcapi.py_fopen(__file__, "rt+, ccs=UTF-8")
- # CRASHES py_fopen(__file__, None)
+ # CRASHES _testcapi.py_fopen(NULL, 'rb')
+ # CRASHES _testcapi.py_fopen(__file__, NULL)
if __name__ == "__main__":
diff --git a/Modules/_testcapi/clinic/file.c.h b/Modules/_testcapi/clinic/file.c.h
index 2ca21ff..fddbf48 100644
--- a/Modules/_testcapi/clinic/file.c.h
+++ b/Modules/_testcapi/clinic/file.c.h
@@ -14,7 +14,8 @@ PyDoc_STRVAR(_testcapi_py_fopen__doc__,
{"py_fopen", _PyCFunction_CAST(_testcapi_py_fopen), METH_FASTCALL, _testcapi_py_fopen__doc__},
static PyObject *
-_testcapi_py_fopen_impl(PyObject *module, PyObject *path, const char *mode);
+_testcapi_py_fopen_impl(PyObject *module, PyObject *path, const char *mode,
+ Py_ssize_t mode_length);
static PyObject *
_testcapi_py_fopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
@@ -22,27 +23,15 @@ _testcapi_py_fopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
PyObject *return_value = NULL;
PyObject *path;
const char *mode;
-
- if (!_PyArg_CheckPositional("py_fopen", nargs, 2, 2)) {
- goto exit;
- }
- path = args[0];
- if (!PyUnicode_Check(args[1])) {
- _PyArg_BadArgument("py_fopen", "argument 2", "str", args[1]);
- goto exit;
- }
Py_ssize_t mode_length;
- mode = PyUnicode_AsUTF8AndSize(args[1], &mode_length);
- if (mode == NULL) {
- goto exit;
- }
- if (strlen(mode) != (size_t)mode_length) {
- PyErr_SetString(PyExc_ValueError, "embedded null character");
+
+ if (!_PyArg_ParseStack(args, nargs, "Oz#:py_fopen",
+ &path, &mode, &mode_length)) {
goto exit;
}
- return_value = _testcapi_py_fopen_impl(module, path, mode);
+ return_value = _testcapi_py_fopen_impl(module, path, mode, mode_length);
exit:
return return_value;
}
-/*[clinic end generated code: output=c9fe964c3e5a0c32 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c4dc92400306c3eb input=a9049054013a1b77]*/
diff --git a/Modules/_testcapi/file.c b/Modules/_testcapi/file.c
index 4bad430..d15173f 100644
--- a/Modules/_testcapi/file.c
+++ b/Modules/_testcapi/file.c
@@ -14,16 +14,18 @@ module _testcapi
_testcapi.py_fopen
path: object
- mode: str
+ mode: str(zeroes=True, accept={robuffer, str, NoneType})
/
Call Py_fopen(), fread(256) and Py_fclose(). Return read bytes.
[clinic start generated code]*/
static PyObject *
-_testcapi_py_fopen_impl(PyObject *module, PyObject *path, const char *mode)
-/*[clinic end generated code: output=5a900af000f759de input=d7e7b8f0fd151953]*/
+_testcapi_py_fopen_impl(PyObject *module, PyObject *path, const char *mode,
+ Py_ssize_t mode_length)
+/*[clinic end generated code: output=69840d0cfd8b7fbb input=f3a579dd7eb60926]*/
{
+ NULLABLE(path);
FILE *fp = Py_fopen(path, mode);
if (fp == NULL) {
return NULL;