@@ -183,13 +183,9 @@ should_audit(PyInterpreterState *interp)
183183
184184
185185static int
186- sys_audit_tstate (PyThreadState * ts , const char * event ,
187- const char * argFormat , va_list vargs )
186+ sys_audit_tuple (PyThreadState * ts , const char * event , PyObject * eventArgs )
188187{
189- /* N format is inappropriate, because you do not know
190- whether the reference is consumed by the call.
191- Assert rather than exception for perf reasons */
192- assert (!argFormat || !strchr (argFormat , 'N' ));
188+ assert (PyTuple_Check (eventArgs ));
193189
194190 if (!ts ) {
195191 /* Audit hooks cannot be called with a NULL thread state */
@@ -200,14 +196,19 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
200196 the current Python thread state. */
201197 assert (ts == _PyThreadState_GET ());
202198
199+ if (event == NULL ) {
200+ _PyErr_SetString (ts , PyExc_ValueError ,
201+ "event argument must not be NULL" );
202+ return -1 ;
203+ }
204+
203205 /* Early exit when no hooks are registered */
204206 PyInterpreterState * is = ts -> interp ;
205207 if (!should_audit (is )) {
206208 return 0 ;
207209 }
208210
209211 PyObject * eventName = NULL ;
210- PyObject * eventArgs = NULL ;
211212 PyObject * hooks = NULL ;
212213 PyObject * hook = NULL ;
213214 int res = -1 ;
@@ -217,21 +218,6 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
217218
218219 PyObject * exc = _PyErr_GetRaisedException (ts );
219220
220- /* Initialize event args now */
221- if (argFormat && argFormat [0 ]) {
222- eventArgs = Py_VaBuildValue (argFormat , vargs );
223- if (eventArgs && !PyTuple_Check (eventArgs )) {
224- PyObject * argTuple = PyTuple_Pack (1 , eventArgs );
225- Py_SETREF (eventArgs , argTuple );
226- }
227- }
228- else {
229- eventArgs = PyTuple_New (0 );
230- }
231- if (!eventArgs ) {
232- goto exit ;
233- }
234-
235221 /* Call global hooks
236222 *
237223 * We don't worry about any races on hooks getting added,
@@ -298,7 +284,6 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
298284 Py_XDECREF (hook );
299285 Py_XDECREF (hooks );
300286 Py_XDECREF (eventName );
301- Py_XDECREF (eventArgs );
302287
303288 if (!res ) {
304289 _PyErr_SetRaisedException (ts , exc );
@@ -311,28 +296,85 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
311296 return res ;
312297}
313298
299+ static int
300+ sys_audit_vargs (PyThreadState * tstate , const char * event ,
301+ const char * format , va_list vargs )
302+ {
303+ if (format && strchr (format , 'N' )) {
304+ _PyErr_SetString (tstate , PyExc_ValueError ,
305+ "format argument must not use the 'N' format" );
306+ return -1 ;
307+ }
308+
309+ PyObject * args ;
310+ if (format && format [0 ]) {
311+ args = Py_VaBuildValue (format , vargs );
312+ if (args && !PyTuple_Check (args )) {
313+ PyObject * argTuple = PyTuple_Pack (1 , args );
314+ Py_SETREF (args , argTuple );
315+ }
316+ }
317+ else {
318+ args = PyTuple_New (0 );
319+ }
320+ if (!args ) {
321+ return -1 ;
322+ }
323+
324+ int res = sys_audit_tuple (tstate , event , args );
325+ Py_DECREF (args );
326+ return res ;
327+ }
328+
314329int
315330_PySys_Audit (PyThreadState * tstate , const char * event ,
316- const char * argFormat , ...)
331+ const char * format , ...)
317332{
318333 va_list vargs ;
319- va_start (vargs , argFormat );
320- int res = sys_audit_tstate (tstate , event , argFormat , vargs );
334+ va_start (vargs , format );
335+ int res = sys_audit_vargs (tstate , event , format , vargs );
321336 va_end (vargs );
322337 return res ;
323338}
324339
325340int
326- PySys_Audit (const char * event , const char * argFormat , ...)
341+ PySys_Audit (const char * event , const char * format , ...)
327342{
328343 PyThreadState * tstate = _PyThreadState_GET ();
329344 va_list vargs ;
330- va_start (vargs , argFormat );
331- int res = sys_audit_tstate (tstate , event , argFormat , vargs );
345+ va_start (vargs , format );
346+ int res = sys_audit_vargs (tstate , event , format , vargs );
332347 va_end (vargs );
333348 return res ;
334349}
335350
351+ int
352+ PySys_AuditTuple (const char * event , PyObject * args )
353+ {
354+ PyThreadState * tstate = _PyThreadState_GET ();
355+ int delete_args = 0 ;
356+
357+ if (args == NULL ) {
358+ delete_args = 1 ;
359+ args = PyTuple_New (0 );
360+ if (args == NULL ) {
361+ return -1 ;
362+ }
363+ }
364+ else if (!PyTuple_Check (args )) {
365+ _PyErr_Format (tstate , PyExc_TypeError ,
366+ "expected tuple, got %s" , Py_TYPE (args )-> tp_name );
367+ return -1 ;
368+ }
369+
370+ int res = sys_audit_tuple (tstate , event , args );
371+
372+ if (delete_args ) {
373+ Py_DECREF (args );
374+ }
375+ return res ;
376+ }
377+
336378/* We expose this function primarily for our own cleanup during
337379 * finalization. In general, it should not need to be called,
338380 * and as such the function is not exported.
0 commit comments