From ace0203455724ed568c75ec83f0097562480b1dd Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Wed, 6 May 2026 16:52:21 +0200 Subject: [PATCH] [TPython] Fix `LoadMacro` for filenames containing special characters The implementation inserted the file name argument directly into a Python string literal delimited by double quotes, so any `"` in the name terminated the literal early and made the constructed source invalid (or, with a carefully crafted name, a different program than intended). Escape `\`, `"`, `\n` and `\r` in the name before using it, so that the whole name is used as a literal. Also add test coverage for filenames containing these special characters. (cherry picked from commit fac6e65bbfe0eab2780ed3e73fa71853f3729873) --- bindings/tpython/src/TPython.cxx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/bindings/tpython/src/TPython.cxx b/bindings/tpython/src/TPython.cxx index ac6a85a3bdbcf..1242178eda4e6 100644 --- a/bindings/tpython/src/TPython.cxx +++ b/bindings/tpython/src/TPython.cxx @@ -269,11 +269,25 @@ void TPython::LoadMacro(const char *name) // obtain a reference to look for new classes later PyObject *old = PyDict_Values(gMainDict); + // escape characters in the file name that would otherwise terminate or + // alter the Python string literal we put the file name into below + std::string escapedName; + escapedName.reserve(std::char_traits::length(name)); + for (const char *p = name; *p; ++p) { + switch (*p) { + case '\\': escapedName += "\\\\"; break; + case '"': escapedName += "\\\""; break; + case '\n': escapedName += "\\n"; break; + case '\r': escapedName += "\\r"; break; + default: escapedName += *p; break; + } + } + // actual execution #if PY_VERSION_HEX < 0x03000000 - Exec((std::string("execfile(\"") + name + "\")").c_str()); + Exec((std::string("execfile(\"") + escapedName + "\")").c_str()); #else - Exec((std::string("__pyroot_f = open(\"") + name + "\"); " + Exec((std::string("__pyroot_f = open(\"") + escapedName + "\"); " "exec(__pyroot_f.read()); " "__pyroot_f.close(); del __pyroot_f") .c_str());