Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7f24b99

Browse files
committed
Avoid calling into Python
1 parent 0933591 commit 7f24b99

File tree

2 files changed

+55
-81
lines changed

2 files changed

+55
-81
lines changed

Lib/test/test_import/__init__.py

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -803,34 +803,20 @@ def test_cwd_script_shadowing_stdlib(self):
803803
):
804804
collections.does_not_exist
805805

806-
def test_shadowing_stdlib_edge_cases(self):
807806
with CleanImport('collections'):
808807
import collections
809-
collections.__spec__ = types.SimpleNamespace()
810-
collections.__spec__.origin = os.path.join(os.getcwd(), 'collections.py')
811-
with CleanImport('sys'):
812-
import sys
813-
sys.stdlib_module_names = None
814-
with self.assertRaisesRegex(
815-
AttributeError,
816-
r"module 'collections' has no attribute 'does_not_exist'"
817-
):
818-
collections.does_not_exist
819-
820-
del sys.stdlib_module_names
821-
with self.assertRaisesRegex(
822-
AttributeError,
823-
r"module 'collections' has no attribute 'does_not_exist'"
824-
):
825-
collections.does_not_exist
826-
with CleanImport("os"), CleanImport('os.path'):
827-
import os as clean_os
828-
del clean_os.path.dirname
829-
with self.assertRaisesRegex(
830-
AttributeError,
831-
r"module '.*path' has no attribute 'dirname'"
832-
):
833-
collections.does_not_exist
808+
del collections.__spec__.origin
809+
with self.assertRaisesRegex(
810+
AttributeError,
811+
r"module 'collections' has no attribute 'does_not_exist'$"
812+
):
813+
collections.does_not_exist
814+
del collections.__spec__
815+
with self.assertRaisesRegex(
816+
AttributeError,
817+
r"module 'collections' has no attribute 'does_not_exist'$"
818+
):
819+
collections.does_not_exist
834820

835821

836822
@skip_if_dont_write_bytecode

Objects/moduleobject.c

Lines changed: 43 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33

44
#include "Python.h"
55
#include "pycore_call.h" // _PyObject_CallNoArgs()
6+
#include "pycore_fileutils.h" // _Py_wgetcwd
67
#include "pycore_interp.h" // PyInterpreterState.importlib
78
#include "pycore_modsupport.h" // _PyModule_CreateInitialized()
89
#include "pycore_moduleobject.h" // _PyModule_GetDef()
910
#include "pycore_object.h" // _PyType_AllocNoTrack
1011
#include "pycore_pyerrors.h" // _PyErr_FormatFromCause()
1112
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1213

14+
#include "osdefs.h" // MAXPATHLEN
15+
#include "Python/stdlib_module_names.h" // _Py_stdlib_module_names
1316

1417

1518
static PyMemberDef module_members[] = {
@@ -784,6 +787,20 @@ _PyModuleSpec_IsUninitializedSubmodule(PyObject *spec, PyObject *name)
784787
return rc;
785788
}
786789

790+
// TODO: deduplicate with suggestions.c. Where should this go?
791+
static bool
792+
is_name_stdlib_module(PyObject* name)
793+
{
794+
const char* the_name = PyUnicode_AsUTF8(name);
795+
Py_ssize_t len = Py_ARRAY_LENGTH(_Py_stdlib_module_names);
796+
for (Py_ssize_t i = 0; i < len; i++) {
797+
if (strcmp(the_name, _Py_stdlib_module_names[i]) == 0) {
798+
return 1;
799+
}
800+
}
801+
return 0;
802+
}
803+
787804
PyObject*
788805
_Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
789806
{
@@ -854,62 +871,34 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
854871
int is_script_shadowing_stdlib = 0;
855872
// Check mod.__name__ in sys.stdlib_module_names
856873
// and os.path.dirname(mod.__spec__.origin) == os.getcwd()
857-
PyObject *stdlib = NULL;
858-
if (origin) {
859-
// Checks against mod_name are to avoid bad recursion
860-
if (
861-
PyUnicode_CompareWithASCIIString(mod_name, "sys") != 0
862-
&& PyUnicode_CompareWithASCIIString(mod_name, "builtins") != 0
863-
) {
864-
stdlib = _PyImport_GetModuleAttrString("sys", "stdlib_module_names");
865-
if (!stdlib) {
866-
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
867-
PyErr_Clear();
868-
} else {
869-
goto done;
870-
}
874+
if (origin && is_name_stdlib_module(mod_name)) {
875+
wchar_t cwdbuf[MAXPATHLEN];
876+
if(_Py_wgetcwd(cwdbuf, MAXPATHLEN)) {
877+
PyObject *cwd = PyUnicode_FromWideChar(cwdbuf, wcslen(cwdbuf));
878+
if (!cwd) {
879+
goto done;
871880
}
872-
if (stdlib && PyFrozenSet_Check(stdlib) && PySet_Contains(stdlib, mod_name)) {
873-
if (
874-
PyUnicode_CompareWithASCIIString(mod_name, "os") != 0
875-
&& PyUnicode_CompareWithASCIIString(mod_name, "posixpath") != 0
876-
&& PyUnicode_CompareWithASCIIString(mod_name, "ntpath") != 0
877-
) {
878-
PyObject *os_path = _PyImport_GetModuleAttrString("os", "path");
879-
if (!os_path) {
880-
goto done;
881-
}
882-
PyObject *dirname = PyObject_GetAttrString(os_path, "dirname");
883-
Py_DECREF(os_path);
884-
if (!dirname) {
885-
goto done;
886-
}
887-
PyObject *origin_dir = _PyObject_CallOneArg(dirname, origin);
888-
Py_DECREF(dirname);
889-
if (!origin_dir) {
890-
goto done;
891-
}
892-
893-
PyObject *getcwd = _PyImport_GetModuleAttrString("os", "getcwd");
894-
if (!getcwd) {
895-
Py_DECREF(origin_dir);
896-
goto done;
897-
}
898-
PyObject *cwd = _PyObject_CallNoArgs(getcwd);
899-
Py_DECREF(getcwd);
900-
if (!cwd) {
901-
Py_DECREF(origin_dir);
902-
goto done;
903-
}
904-
905-
is_script_shadowing_stdlib = PyObject_RichCompareBool(origin_dir, cwd, Py_EQ);
906-
Py_DECREF(origin_dir);
907-
Py_DECREF(cwd);
908-
if (is_script_shadowing_stdlib < 0) {
909-
goto done;
910-
}
911-
}
881+
const char sep_char = SEP;
882+
PyObject *sep = PyUnicode_FromStringAndSize(&sep_char, 1);
883+
if (!sep) {
884+
Py_DECREF(cwd);
885+
goto done;
886+
}
887+
PyObject *parts = PyUnicode_RPartition(origin, sep);
888+
Py_DECREF(sep);
889+
if (!parts) {
890+
Py_DECREF(cwd);
891+
goto done;
892+
}
893+
int rc = PyUnicode_Compare(cwd, PyTuple_GET_ITEM(parts, 0));
894+
if (rc == -1 && PyErr_Occurred()) {
895+
Py_DECREF(parts);
896+
Py_DECREF(cwd);
897+
goto done;
912898
}
899+
is_script_shadowing_stdlib = rc == 0;
900+
Py_DECREF(parts);
901+
Py_DECREF(cwd);
913902
}
914903
}
915904

@@ -954,7 +943,6 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
954943
}
955944

956945
done:
957-
Py_XDECREF(stdlib);
958946
Py_XDECREF(origin);
959947
Py_XDECREF(spec);
960948
Py_DECREF(mod_name);

0 commit comments

Comments
 (0)