Skip to content

Commit d3e998b

Browse files
committed
bpo-42800: audit hooks for frame and code attrs
* Accessing the following attributes will now fire PEP 578 style audit hooks as ("object.__getattr__", obj, name): * PyTracebackObject: tb_frame * PyFrameObject: f_code * PyGenObject: gi_code, gi_frame * PyCoroObject: cr_code, cr_frame * PyAsyncGenObject: ag_code, ag_frame * Document audit hooks for tb_frame, f_code, and __code__ * Add an AUDIT_READ attribute flag aliased to READ_RESTRICTED. * Update obsolete RESTRICTED flag documentation.
1 parent 0e2a0f7 commit d3e998b

11 files changed

Lines changed: 24 additions & 15 deletions

File tree

Doc/extending/newtypes.rst

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,8 @@ combined using bitwise-OR.
287287
+===========================+==============================================+
288288
| :const:`READONLY` | Never writable. |
289289
+---------------------------+----------------------------------------------+
290-
| :const:`READ_RESTRICTED` | Not readable in restricted mode. |
291-
+---------------------------+----------------------------------------------+
292-
| :const:`WRITE_RESTRICTED` | Not writable in restricted mode. |
293-
+---------------------------+----------------------------------------------+
294-
| :const:`RESTRICTED` | Not readable or writable in restricted mode. |
290+
| :const:`AUDIT_READ` | Emit a :pep:`578` ``object.__getattr__`` |
291+
| | audit event before read. |
295292
+---------------------------+----------------------------------------------+
296293

297294
.. index::

Doc/library/audit_events.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Audit events table
77

88
This table contains all events raised by :func:`sys.audit` or
99
:c:func:`PySys_Audit` calls throughout the CPython runtime and the
10-
standard library. These calls were added in 3.8.0 or later.
10+
standard library. These calls were added in 3.8.0 or later (see :pep:`578`).
1111

1212
See :func:`sys.addaudithook` and :c:func:`PySys_AddAuditHook` for
1313
information on handling these events.

Doc/library/stdtypes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5206,6 +5206,9 @@ environment. Code objects are returned by the built-in :func:`compile` function
52065206
and can be extracted from function objects through their :attr:`__code__`
52075207
attribute. See also the :mod:`code` module.
52085208

5209+
Accessing ``__code__`` raises an :ref:`auditing event <auditing>`
5210+
``object.__getattr__`` with arguments ``obj`` and ``"__code__"``.
5211+
52095212
.. index::
52105213
builtin: exec
52115214
builtin: eval

Doc/reference/datamodel.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,9 @@ Internal types
10051005
:attr:`f_lasti` gives the precise instruction (this is an index into the
10061006
bytecode string of the code object).
10071007

1008+
Accessing ``f_code`` raises an :ref:`auditing event <auditing>`
1009+
``object.__getattr__`` with arguments ``obj`` and ``"f_code"``.
1010+
10081011
.. index::
10091012
single: f_trace (frame attribute)
10101013
single: f_trace_lines (frame attribute)
@@ -1089,6 +1092,9 @@ Internal types
10891092
:keyword:`try` statement with no matching except clause or with a
10901093
finally clause.
10911094

1095+
Accessing ``tb_frame`` raises an :ref:`auditing event <auditing>`
1096+
``object.__getattr__`` with arguments ``obj`` and ``"tb_frame"``.
1097+
10921098
.. index::
10931099
single: tb_next (traceback attribute)
10941100

Include/structmember.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ typedef struct PyMemberDef {
6262
#define PY_WRITE_RESTRICTED 4
6363
#define RESTRICTED (READ_RESTRICTED | PY_WRITE_RESTRICTED)
6464

65+
#define AUDIT_READ READ_RESTRICTED
6566

6667
/* Current API, use this */
6768
PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *);

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ Kevan Heydon
718718
Wouter van Heyst
719719
Kelsey Hightower
720720
Jason Hildebrand
721+
Ryan Hileman
721722
Aaron Hill
722723
Joel Hillacre
723724
Richie Hindle
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Audit hooks are now fired for frame.f_code, traceback.tb_frame, and generator code/frame attribute access.

Objects/descrobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
164164
if (descr_check((PyDescrObject *)descr, obj, &res))
165165
return res;
166166

167-
if (descr->d_member->flags & READ_RESTRICTED) {
167+
if (descr->d_member->flags & AUDIT_READ) {
168168
if (PySys_Audit("object.__getattr__", "Os",
169169
obj ? obj : Py_None, descr->d_member->name) < 0) {
170170
return NULL;

Objects/frameobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
static PyMemberDef frame_memberlist[] = {
1515
{"f_back", T_OBJECT, OFF(f_back), READONLY},
16-
{"f_code", T_OBJECT, OFF(f_code), READONLY},
16+
{"f_code", T_OBJECT, OFF(f_code), READONLY|AUDIT_READ},
1717
{"f_builtins", T_OBJECT, OFF(f_builtins), READONLY},
1818
{"f_globals", T_OBJECT, OFF(f_globals), READONLY},
1919
{"f_lasti", T_INT, OFF(f_lasti), READONLY},

Objects/genobject.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,8 @@ static PyGetSetDef gen_getsetlist[] = {
756756
};
757757

758758
static PyMemberDef gen_memberlist[] = {
759-
{"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
760-
{"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
759+
{"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY|AUDIT_READ},
760+
{"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY|AUDIT_READ},
761761
{NULL} /* Sentinel */
762762
};
763763

@@ -993,8 +993,8 @@ static PyGetSetDef coro_getsetlist[] = {
993993
};
994994

995995
static PyMemberDef coro_memberlist[] = {
996-
{"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY},
997-
{"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY},
996+
{"cr_frame", T_OBJECT, offsetof(PyCoroObject, cr_frame), READONLY|AUDIT_READ},
997+
{"cr_code", T_OBJECT, offsetof(PyCoroObject, cr_code), READONLY|AUDIT_READ},
998998
{"cr_origin", T_OBJECT, offsetof(PyCoroObject, cr_origin), READONLY},
999999
{NULL} /* Sentinel */
10001000
};
@@ -1375,10 +1375,10 @@ static PyGetSetDef async_gen_getsetlist[] = {
13751375
};
13761376

13771377
static PyMemberDef async_gen_memberlist[] = {
1378-
{"ag_frame", T_OBJECT, offsetof(PyAsyncGenObject, ag_frame), READONLY},
1378+
{"ag_frame", T_OBJECT, offsetof(PyAsyncGenObject, ag_frame), READONLY|AUDIT_READ},
13791379
{"ag_running", T_BOOL, offsetof(PyAsyncGenObject, ag_running_async),
13801380
READONLY},
1381-
{"ag_code", T_OBJECT, offsetof(PyAsyncGenObject, ag_code), READONLY},
1381+
{"ag_code", T_OBJECT, offsetof(PyAsyncGenObject, ag_code), READONLY|AUDIT_READ},
13821382
{NULL} /* Sentinel */
13831383
};
13841384

0 commit comments

Comments
 (0)