Skip to content

Commit 4c497b1

Browse files
cmaloneyclaude
andauthored
gh-159446: Avoid TypeError on FileIO construction (#159480)
FileIO can be constructed off a string or an integer file descriptor. It used PyLong_AsInt first to check "is this an integer". That raised a TypeError when passed a string which would then be silenced. Proactively check if it is a number with _PyIndex_Check saving instructions in the common filename path. Callgrind, instructions per `FileIO(path).readall()` + `close()` of a 111-byte file: | Build | base | this change | |------------------|-------:|------------:| | PGO+LTO | 10,641 | 8,918 | | -O3, no PGO | 14,154 | 12,016 | pyperf, the same on a 182-byte file, PGO+LTO, 4 interleaved rounds of 10 processes: | Benchmark | base | this change | |----------------|:-------:|:---------------------:| | fileio_readall | 3.71 us | 3.62 us: 1.02x faster | Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 069aac9 commit 4c497b1

1 file changed

Lines changed: 11 additions & 7 deletions

File tree

‎Modules/_io/fileio.c‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* Author: Daniel Stutzbach */
22

33
#include "Python.h"
4+
#include "pycore_abstract.h" // _PyIndex_Check()
45
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
56
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
67
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
@@ -300,14 +301,17 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
300301
return -1;
301302
}
302303
}
303-
fd = PyLong_AsInt(nameobj);
304-
if (fd < 0) {
305-
if (!PyErr_Occurred()) {
306-
PyErr_SetString(PyExc_ValueError,
307-
"negative file descriptor");
308-
return -1;
304+
if (_PyIndex_Check(nameobj)) {
305+
fd = PyLong_AsInt(nameobj);
306+
if (fd < 0) {
307+
if (!PyErr_Occurred()) {
308+
PyErr_SetString(PyExc_ValueError,
309+
"negative file descriptor");
310+
return -1;
311+
}
312+
/* Failed to convert; try other paths. */
313+
PyErr_Clear();
309314
}
310-
PyErr_Clear();
311315
}
312316

313317
if (fd < 0) {

0 commit comments

Comments
 (0)