PEP 551 and PEP 7 (#392)
This commit is contained in:
parent
ebbb636b7b
commit
f41260ee2d
143
pep-0551.rst
143
pep-0551.rst
|
@ -269,7 +269,10 @@ The new public C API for the verified open hook is::
|
|||
# Set the handler
|
||||
typedef PyObject *(*handler_func)(const char *narrow,
|
||||
const wchar_t *wide)
|
||||
int Py_SetOpenForExecuteHandler(handler_func handler)
|
||||
int PyOS_SetOpenForExecuteHandler(handler_func handler)
|
||||
|
||||
# Open a file using the handler
|
||||
PyObject *PyOS_OpenForExec(PyObject *path)
|
||||
|
||||
The new public Python API for the verified open hook is::
|
||||
|
||||
|
@ -356,101 +359,144 @@ should be considered part of the rationale for including the hook.
|
|||
:widths: 2, 2, 3, 6
|
||||
|
||||
``PySys_AddAuditHook``, ``sys.addaudithook``, "", "Detect when new
|
||||
audit hooks are being added."
|
||||
audit hooks are being added.
|
||||
"
|
||||
``_PySys_ClearAuditHooks``, ``sys._clearaudithooks``, "", "Notifies
|
||||
hooks they are being cleaned up, mainly in case the event is
|
||||
triggered unexpectedly. This event cannot be aborted."
|
||||
triggered unexpectedly. This event cannot be aborted.
|
||||
"
|
||||
``Py_SetOpenForExecuteHandler``, ``setopenforexecutehandler``, "", "
|
||||
Detects any attempt to set the ``open_for_execute`` handler."
|
||||
Detects any attempt to set the ``open_for_execute`` handler.
|
||||
"
|
||||
"``compile``, ``exec``, ``eval``, ``PyAst_CompileString``,
|
||||
``PyAST_obj2mod``", ``compile``, "``(code, filename_or_none)``", "
|
||||
Detect dynamic code compilation, where ``code`` could be a string or
|
||||
AST. Note that this will be called for regular imports of source
|
||||
code, including those that were opened with ``open_for_exec``."
|
||||
code, including those that were opened with ``open_for_exec``.
|
||||
"
|
||||
"``exec``, ``eval``, ``run_mod``", ``exec``, "``(code_object,)``", "
|
||||
Detect dynamic execution of code objects. This only occurs for
|
||||
explicit calls, and is not raised for normal function invocation."
|
||||
explicit calls, and is not raised for normal function invocation.
|
||||
"
|
||||
``import``, ``import``, "``(module, filename, sys.path,
|
||||
sys.meta_path, sys.path_hooks)``", "Detect when modules are
|
||||
imported. This is raised before the module name is resolved to a
|
||||
file. All arguments other than the module name may be ``None`` if
|
||||
they are not used or available."
|
||||
they are not used or available.
|
||||
"
|
||||
``code_new``, ``code.__new__``, "``(bytecode, filename, name)``", "
|
||||
Detect dynamic creation of code objects. This only occurs for
|
||||
direct instantiation, and is not raised for normal compilation."
|
||||
direct instantiation, and is not raised for normal compilation.
|
||||
"
|
||||
``func_new_impl``, ``function.__new__``, "``(code,)``", "Detect
|
||||
dynamic creation of function objects. This only occurs for direct
|
||||
instantiation, and is not raised for normal compilation.
|
||||
"
|
||||
"``_ctypes.dlopen``, ``_ctypes.LoadLibrary``", ``ctypes.dlopen``, "
|
||||
``(module_or_path,)``", "Detect when native modules are used."
|
||||
``(module_or_path,)``", "Detect when native modules are used.
|
||||
"
|
||||
``_ctypes._FuncPtr``, ``ctypes.dlsym``, "``(lib_object, name)``", "
|
||||
Collect information about specific symbols retrieved from native
|
||||
modules."
|
||||
modules.
|
||||
"
|
||||
``_ctypes._CData``, ``ctypes.cdata``, "``(ptr_as_int,)``", "Detect
|
||||
when code is accessing arbitrary memory using ``ctypes``"
|
||||
when code is accessing arbitrary memory using ``ctypes``.
|
||||
"
|
||||
``id``, ``id``, "``(id_as_int,)``", "Detect when code is accessing
|
||||
the id of objects, which in CPython reveals information about
|
||||
memory layout."
|
||||
memory layout.
|
||||
"
|
||||
``sys._getframe``, ``sys._getframe``, "``(frame_object,)``", "Detect
|
||||
when code is accessing frames directly"
|
||||
when code is accessing frames directly.
|
||||
"
|
||||
``sys._current_frames``, ``sys._current_frames``, "", "Detect when
|
||||
code is accessing frames directly"
|
||||
code is accessing frames directly.
|
||||
"
|
||||
``PyEval_SetProfile``, ``sys.setprofile``, "", "Detect when code is
|
||||
injecting trace functions. Because of the implementation, exceptions
|
||||
raised from the hook will abort the operation, but will not be
|
||||
raised in Python code. Note that ``threading.setprofile`` eventually
|
||||
calls this function, so the event will be audited for each thread."
|
||||
calls this function, so the event will be audited for each thread.
|
||||
"
|
||||
``PyEval_SetTrace``, ``sys.settrace``, "", "Detect when code is
|
||||
injecting trace functions. Because of the implementation, exceptions
|
||||
raised from the hook will abort the operation, but will not be
|
||||
raised in Python code. Note that ``threading.settrace`` eventually
|
||||
calls this function, so the event will be audited for each thread."
|
||||
calls this function, so the event will be audited for each thread.
|
||||
"
|
||||
``_PyEval_SetAsyncGenFirstiter``, ``sys.set_async_gen_firstiter``, "
|
||||
", "Detect changes to async generator hooks."
|
||||
", "Detect changes to async generator hooks.
|
||||
"
|
||||
``_PyEval_SetAsyncGenFinalizer``, ``sys.set_async_gen_finalizer``, "
|
||||
", "Detect changes to async generator hooks."
|
||||
", "Detect changes to async generator hooks.
|
||||
"
|
||||
``_PyEval_SetCoroutineWrapper``, ``sys.set_coroutine_wrapper``, "
|
||||
", "Detect changes to the coroutine wrapper."
|
||||
", "Detect changes to the coroutine wrapper.
|
||||
"
|
||||
``Py_SetRecursionLimit``, ``sys.setrecursionlimit``, "
|
||||
``(new_limit,)``", "Detect changes to the recursion limit."
|
||||
``(new_limit,)``", "Detect changes to the recursion limit.
|
||||
"
|
||||
``_PyEval_SetSwitchInterval``, ``sys.setswitchinterval``, "
|
||||
``(interval_us,)``", "Detect changes to the switching interval."
|
||||
``(interval_us,)``", "Detect changes to the switching interval.
|
||||
"
|
||||
"``socket.bind``, ``socket.connect``, ``socket.connect_ex``,
|
||||
``socket.getaddrinfo``, ``socket.getnameinfo``, ``socket.sendmsg``,
|
||||
``socket.sendto``", ``socket.address``, "``(address,)``", "Detect
|
||||
access to network resources. The address is unmodified from the
|
||||
original call."
|
||||
original call.
|
||||
"
|
||||
``socket.__init__``, "socket()", "``(family, type, proto)``", "
|
||||
Detect creation of sockets. The arguments will be int values."
|
||||
Detect creation of sockets. The arguments will be int values.
|
||||
"
|
||||
``socket.gethostname``, ``socket.gethostname``, "", "Detect attempts
|
||||
to retrieve the current host name."
|
||||
to retrieve the current host name.
|
||||
"
|
||||
``socket.sethostname``, ``socket.sethostname``, "``(name,)``", "
|
||||
Detect attempts to change the current host name. The name argument
|
||||
is passed as a bytes object."
|
||||
is passed as a bytes object.
|
||||
"
|
||||
"``socket.gethostbyname``, ``socket.gethostbyname_ex``",
|
||||
"``socket.gethostbyname``", "``(name,)``", "Detect host name
|
||||
resolution. The name argument is a str or bytes object."
|
||||
resolution. The name argument is a str or bytes object.
|
||||
"
|
||||
``socket.gethostbyaddr``, ``socket.gethostbyaddr``, "
|
||||
``(address,)``", "Detect host resolution. The address argument is a
|
||||
str or bytes object."
|
||||
str or bytes object.
|
||||
"
|
||||
``socket.getservbyname``, ``socket.getservbyname``, "``(name,
|
||||
protocol)``", "Detect service resolution. The arguments are str
|
||||
objects."
|
||||
``socket.getservbyport``, ``socket.getservbyport``, "``(port,
|
||||
objects.
|
||||
"
|
||||
"``socket.getservbyport``", ``socket.getservbyport``, "``(port,
|
||||
protocol)``", "Detect service resolution. The port argument is an
|
||||
int and protocol is a str."
|
||||
int and protocol is a str.
|
||||
"
|
||||
"``member_get``, ``func_get_code``, ``func_get_[kw]defaults``
|
||||
",``object.__getattr__``,"``(object, attr)``","Detect access to
|
||||
restricted attributes. This event is raised for any built-in
|
||||
members that are marked as restricted, and members that may allow
|
||||
bypassing imports.
|
||||
"
|
||||
"``_PyObject_GenericSetAttr``, ``check_set_special_type_attr``,
|
||||
``object_set_class``",``object.__setattr__``,"``(object, attr,
|
||||
value)``","Detect monkey patching of types and objects. This event
|
||||
``object_set_class``, ``func_set_code``, ``func_set_[kw]defaults``","
|
||||
``object.__setattr__``","``(object, attr, value)``","Detect monkey
|
||||
patching of types and objects. This event
|
||||
is raised for the ``__class__`` attribute and any attribute on
|
||||
``type`` objects."
|
||||
``_PyObject_GenericSetAttr``,``object.__delattr__``,"``(object,
|
||||
``type`` objects.
|
||||
"
|
||||
"``_PyObject_GenericSetAttr``",``object.__delattr__``,"``(object,
|
||||
attr)``","Detect deletion of object attributes. This event is raised
|
||||
for any attribute on ``type`` objects."
|
||||
``Unpickler.find_class``,``pickle.find_class``,"``(module_name,
|
||||
for any attribute on ``type`` objects.
|
||||
"
|
||||
"``Unpickler.find_class``",``pickle.find_class``,"``(module_name,
|
||||
global_name)``","Detect imports and global name lookup when
|
||||
unpickling."
|
||||
unpickling.
|
||||
"
|
||||
"``array_new``",``array.__new__``,"``(typecode, initial_value)``", "
|
||||
Detects creation of array objects.
|
||||
"
|
||||
|
||||
TODO - more hooks in ``_socket``, ``_ssl``, others?
|
||||
* code objects
|
||||
* function objects
|
||||
|
||||
SPython Entry Point
|
||||
===================
|
||||
|
@ -523,16 +569,19 @@ events unless explicitly added, and so they will continue to be allowed.
|
|||
Performance Impact
|
||||
==================
|
||||
|
||||
**TODO**
|
||||
The important performance impact is the case where events are being
|
||||
raised but there are no hooks attached. This is the unavoidable case -
|
||||
once a distributor or sysadmin begins adding audit hooks they have
|
||||
explicitly chosen to trade performance for functionality. Performance
|
||||
impact using ``spython`` or with hooks added are not of interest here,
|
||||
since this is considered opt-in functionality.
|
||||
|
||||
Full impact analysis still requires investigation. Preliminary testing
|
||||
shows that calling ``sys.audit`` with no hooks added does not
|
||||
significantly affect any existing benchmarks, though targeted
|
||||
microbenchmarks can observe an impact.
|
||||
|
||||
Performance impact using ``spython`` or with hooks added are not of
|
||||
interest here, since this is considered opt-in functionality.
|
||||
Analysis using the ``performance`` tool shows no significant impact,
|
||||
with the vast majority of benchmarks showing between 1.05x faster to
|
||||
1.05x slower.
|
||||
|
||||
In our opinion, the performance impact of the set of auditing points
|
||||
described in this PEP is negligible.
|
||||
|
||||
Recommendations
|
||||
===============
|
||||
|
|
Loading…
Reference in New Issue