]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-96005: Handle WASI ENOTCAPABLE in getpath (GH-96006) (GH-96034) (GH-96038)
authorChristian Heimes <christian@python.org>
Tue, 13 Sep 2022 11:00:45 +0000 (13:00 +0200)
committerGitHub <noreply@github.com>
Tue, 13 Sep 2022 11:00:45 +0000 (13:00 +0200)
- On WASI `ENOTCAPABLE` is now mapped to `PermissionError`.
- The `errno` modules exposes the new error number.
- `getpath.py` now ignores `PermissionError` when it cannot open landmark
  files `pybuilddir.txt` and `pyenv.cfg`.

Doc/library/errno.rst
Doc/library/exceptions.rst
Lib/test/test_exception_hierarchy.py
Misc/NEWS.d/next/Core and Builtins/2022-08-15-21-08-11.gh-issue-96005.6eoc8k.rst [new file with mode: 0644]
Modules/errnomodule.c
Modules/getpath.py
Objects/exceptions.c

index 035340e256874f05102de251b22cbf512be0ef98..5122c69697ef91416a8fd2bb2af7643cc0dd3b87 100644 (file)
@@ -657,3 +657,12 @@ defined by the module.  The specific list of defined symbols is available as
    Interface output queue is full
 
    .. versionadded:: 3.11
+
+.. data:: ENOTCAPABLE
+
+   Capabilities insufficient. This error is mapped to the exception
+   :exc:`PermissionError`.
+
+   .. availability:: WASI, FreeBSD
+
+   .. versionadded:: 3.11.1
index 2eccbd17c482c04ccde83e29d0df6ff4186d5e72..fc856277d67b2ec7af6175bf751df66b0db36e31 100644 (file)
@@ -746,7 +746,12 @@ depending on the system error code.
 
    Raised when trying to run an operation without the adequate access
    rights - for example filesystem permissions.
-   Corresponds to :c:data:`errno` :py:data:`~errno.EACCES` and :py:data:`~errno.EPERM`.
+   Corresponds to :c:data:`errno` :py:data:`~errno.EACCES`,
+   :py:data:`~errno.EPERM`, and :py:data:`~errno.ENOTCAPABLE`.
+
+   .. versionchanged:: 3.11.1
+      WASI's :py:data:`~errno.ENOTCAPABLE` is now mapped to
+      :exc:`PermissionError`.
 
 .. exception:: ProcessLookupError
 
index 89fe9ddcefba3ee14ec434474cc9800181eded99..3318fa8e7746f7a8f5dc4cf6cb5f7cabde24efb4 100644 (file)
@@ -63,7 +63,7 @@ class HierarchyTest(unittest.TestCase):
         +-- InterruptedError                                            EINTR
         +-- IsADirectoryError                                          EISDIR
         +-- NotADirectoryError                                        ENOTDIR
-        +-- PermissionError                                     EACCES, EPERM
+        +-- PermissionError                        EACCES, EPERM, ENOTCAPABLE
         +-- ProcessLookupError                                          ESRCH
         +-- TimeoutError                                            ETIMEDOUT
     """
@@ -75,6 +75,8 @@ class HierarchyTest(unittest.TestCase):
                 continue
             excname, _, errnames = line.partition(' ')
             for errname in filter(None, errnames.strip().split(', ')):
+                if errname == "ENOTCAPABLE" and not hasattr(errno, errname):
+                    continue
                 _map[getattr(errno, errname)] = getattr(builtins, excname)
         return _map
     _map = _make_map(_pep_map)
@@ -91,7 +93,7 @@ class HierarchyTest(unittest.TestCase):
         othercodes = set(errno.errorcode) - set(self._map)
         for errcode in othercodes:
             e = OSError(errcode, "Some message")
-            self.assertIs(type(e), OSError)
+            self.assertIs(type(e), OSError, repr(e))
 
     def test_try_except(self):
         filename = "some_hopefully_non_existing_file"
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-15-21-08-11.gh-issue-96005.6eoc8k.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-15-21-08-11.gh-issue-96005.6eoc8k.rst
new file mode 100644 (file)
index 0000000..06e414b
--- /dev/null
@@ -0,0 +1,4 @@
+On WASI :data:`~errno.ENOTCAPABLE` is now mapped to :exc:`PermissionError`.
+The :mod:`errno` modules exposes the new error number. ``getpath.py`` now
+ignores :exc:`PermissionError` when it cannot open landmark files
+``pybuilddir.txt`` and ``pyenv.cfg``.
index 0516e7367050c2f187ccf928a74233c61c7ccefd..4de4144520aa48efda5ee71659ccda783d93b03e 100644 (file)
@@ -927,6 +927,10 @@ errno_exec(PyObject *module)
 #ifdef EQFULL
     add_errcode("EQFULL", EQFULL, "Interface output queue is full");
 #endif
+#ifdef ENOTCAPABLE
+    // WASI extension
+    add_errcode("ENOTCAPABLE", ENOTCAPABLE, "Capabilities insufficient");
+#endif
 
     Py_DECREF(error_dict);
     return 0;
index dceeed7702c0bef1124e6575b9f230b1b2a925ba..e09fda9eb38def874100c15963f1d3ab439d7f89 100644 (file)
@@ -351,11 +351,11 @@ if not home and not py_setpath:
         try:
             # Read pyvenv.cfg from one level above executable
             pyvenvcfg = readlines(joinpath(venv_prefix, VENV_LANDMARK))
-        except FileNotFoundError:
+        except (FileNotFoundError, PermissionError):
             # Try the same directory as executable
             pyvenvcfg = readlines(joinpath(venv_prefix2, VENV_LANDMARK))
             venv_prefix = venv_prefix2
-    except FileNotFoundError:
+    except (FileNotFoundError, PermissionError):
         venv_prefix = None
         pyvenvcfg = []
 
@@ -475,7 +475,7 @@ if ((not home_was_set and real_executable_dir and not py_setpath)
         # File exists but is empty
         platstdlib_dir = real_executable_dir
         build_prefix = joinpath(real_executable_dir, VPATH)
-    except FileNotFoundError:
+    except (FileNotFoundError, PermissionError):
         if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)):
             build_prefix = joinpath(real_executable_dir, VPATH)
             if os_name == 'nt':
index 3c4df2facfe2e2a53015f4eec04414ddb0f5617c..319eb238ecf5706db521cdba6fa1ef6f19594f35 100644 (file)
@@ -3644,6 +3644,11 @@ _PyExc_InitState(PyInterpreterState *interp)
     ADD_ERRNO(InterruptedError, EINTR);
     ADD_ERRNO(PermissionError, EACCES);
     ADD_ERRNO(PermissionError, EPERM);
+#ifdef ENOTCAPABLE
+    // Extension for WASI capability-based security. Process lacks
+    // capability to access a resource.
+    ADD_ERRNO(PermissionError, ENOTCAPABLE);
+#endif
     ADD_ERRNO(ProcessLookupError, ESRCH);
     ADD_ERRNO(TimeoutError, ETIMEDOUT);