1 #include "Python.h"
2 #include "pycore_initconfig.h"
3 #include "pycore_interp.h"        // PyInterpreterState.warnings
4 #include "pycore_long.h"          // _PyLong_GetZero()
5 #include "pycore_pyerrors.h"
6 #include "pycore_pystate.h"       // _PyThreadState_GET()
7 #include "pycore_frame.h"
8 #include "clinic/_warnings.c.h"
9 
10 #define MODULE_NAME "_warnings"
11 
12 PyDoc_STRVAR(warnings__doc__,
13 MODULE_NAME " provides basic warning filtering support.\n"
14 "It is a helper module to speed up interpreter start-up.");
15 
16 
17 /*************************************************************************/
18 
19 typedef struct _warnings_runtime_state WarningsState;
20 
21 static inline int
check_interp(PyInterpreterState * interp)22 check_interp(PyInterpreterState *interp)
23 {
24     if (interp == NULL) {
25         PyErr_SetString(PyExc_RuntimeError,
26                         "warnings_get_state: could not identify "
27                         "current interpreter");
28         return 0;
29     }
30     return 1;
31 }
32 
33 static inline PyInterpreterState *
get_current_interp(void)34 get_current_interp(void)
35 {
36     PyInterpreterState *interp = _PyInterpreterState_GET();
37     return check_interp(interp) ? interp : NULL;
38 }
39 
40 static inline PyThreadState *
get_current_tstate(void)41 get_current_tstate(void)
42 {
43     PyThreadState *tstate = _PyThreadState_GET();
44     if (tstate == NULL) {
45         (void)check_interp(NULL);
46         return NULL;
47     }
48     return check_interp(tstate->interp) ? tstate : NULL;
49 }
50 
51 /* Given a module object, get its per-module state. */
52 static WarningsState *
warnings_get_state(PyInterpreterState * interp)53 warnings_get_state(PyInterpreterState *interp)
54 {
55     return &interp->warnings;
56 }
57 
58 /* Clear the given warnings module state. */
59 static void
warnings_clear_state(WarningsState * st)60 warnings_clear_state(WarningsState *st)
61 {
62     Py_CLEAR(st->filters);
63     Py_CLEAR(st->once_registry);
64     Py_CLEAR(st->default_action);
65 }
66 
67 #ifndef Py_DEBUG
68 static PyObject *
create_filter(PyObject * category,PyObject * action_str,const char * modname)69 create_filter(PyObject *category, PyObject *action_str, const char *modname)
70 {
71     PyObject *modname_obj = NULL;
72 
73     /* Default to "no module name" for initial filter set */
74     if (modname != NULL) {
75         modname_obj = PyUnicode_InternFromString(modname);
76         if (modname_obj == NULL) {
77             return NULL;
78         }
79     } else {
80         modname_obj = Py_NewRef(Py_None);
81     }
82 
83     /* This assumes the line number is zero for now. */
84     PyObject *filter = PyTuple_Pack(5, action_str, Py_None,
85                                     category, modname_obj, _PyLong_GetZero());
86     Py_DECREF(modname_obj);
87     return filter;
88 }
89 #endif
90 
91 static PyObject *
init_filters(PyInterpreterState * interp)92 init_filters(PyInterpreterState *interp)
93 {
94 #ifdef Py_DEBUG
95     /* Py_DEBUG builds show all warnings by default */
96     return PyList_New(0);
97 #else
98     /* Other builds ignore a number of warning categories by default */
99     PyObject *filters = PyList_New(5);
100     if (filters == NULL) {
101         return NULL;
102     }
103 
104     size_t pos = 0;  /* Post-incremented in each use. */
105 #define ADD(TYPE, ACTION, MODNAME) \
106     PyList_SET_ITEM(filters, pos++, \
107                     create_filter(TYPE, &_Py_ID(ACTION), MODNAME));
108     ADD(PyExc_DeprecationWarning, default, "__main__");
109     ADD(PyExc_DeprecationWarning, ignore, NULL);
110     ADD(PyExc_PendingDeprecationWarning, ignore, NULL);
111     ADD(PyExc_ImportWarning, ignore, NULL);
112     ADD(PyExc_ResourceWarning, ignore, NULL);
113 #undef ADD
114 
115     for (size_t x = 0; x < pos; x++) {
116         if (PyList_GET_ITEM(filters, x) == NULL) {
117             Py_DECREF(filters);
118             return NULL;
119         }
120     }
121     return filters;
122 #endif
123 }
124 
125 /* Initialize the given warnings module state. */
126 int
_PyWarnings_InitState(PyInterpreterState * interp)127 _PyWarnings_InitState(PyInterpreterState *interp)
128 {
129     WarningsState *st = &interp->warnings;
130 
131     if (st->filters == NULL) {
132         st->filters = init_filters(interp);
133         if (st->filters == NULL) {
134             return -1;
135         }
136     }
137 
138     if (st->once_registry == NULL) {
139         st->once_registry = PyDict_New();
140         if (st->once_registry == NULL) {
141             return -1;
142         }
143     }
144 
145     if (st->default_action == NULL) {
146         st->default_action = PyUnicode_FromString("default");
147         if (st->default_action == NULL) {
148             return -1;
149         }
150     }
151 
152     st->filters_version = 0;
153     return 0;
154 }
155 
156 
157 /*************************************************************************/
158 
159 static int
check_matched(PyInterpreterState * interp,PyObject * obj,PyObject * arg)160 check_matched(PyInterpreterState *interp, PyObject *obj, PyObject *arg)
161 {
162     PyObject *result;
163     int rc;
164 
165     /* A 'None' filter always matches */
166     if (obj == Py_None)
167         return 1;
168 
169     /* An internal plain text default filter must match exactly */
170     if (PyUnicode_CheckExact(obj)) {
171         int cmp_result = PyUnicode_Compare(obj, arg);
172         if (cmp_result == -1 && PyErr_Occurred()) {
173             return -1;
174         }
175         return !cmp_result;
176     }
177 
178     /* Otherwise assume a regex filter and call its match() method */
179     result = PyObject_CallMethodOneArg(obj, &_Py_ID(match), arg);
180     if (result == NULL)
181         return -1;
182 
183     rc = PyObject_IsTrue(result);
184     Py_DECREF(result);
185     return rc;
186 }
187 
188 #define GET_WARNINGS_ATTR(interp, ATTR, try_import) \
189     get_warnings_attr(interp, &_Py_ID(ATTR), try_import)
190 
191 /*
192    Returns a new reference.
193    A NULL return value can mean false or an error.
194 */
195 static PyObject *
get_warnings_attr(PyInterpreterState * interp,PyObject * attr,int try_import)196 get_warnings_attr(PyInterpreterState *interp, PyObject *attr, int try_import)
197 {
198     PyObject *warnings_module, *obj;
199 
200     /* don't try to import after the start of the Python finallization */
201     if (try_import && !_Py_IsFinalizing()) {
202         warnings_module = PyImport_Import(&_Py_ID(warnings));
203         if (warnings_module == NULL) {
204             /* Fallback to the C implementation if we cannot get
205                the Python implementation */
206             if (PyErr_ExceptionMatches(PyExc_ImportError)) {
207                 PyErr_Clear();
208             }
209             return NULL;
210         }
211     }
212     else {
213         /* if we're so late into Python finalization that the module dict is
214            gone, then we can't even use PyImport_GetModule without triggering
215            an interpreter abort.
216         */
217         if (!interp->modules) {
218             return NULL;
219         }
220         warnings_module = PyImport_GetModule(&_Py_ID(warnings));
221         if (warnings_module == NULL)
222             return NULL;
223     }
224 
225     (void)_PyObject_LookupAttr(warnings_module, attr, &obj);
226     Py_DECREF(warnings_module);
227     return obj;
228 }
229 
230 
231 static PyObject *
get_once_registry(PyInterpreterState * interp)232 get_once_registry(PyInterpreterState *interp)
233 {
234     PyObject *registry;
235 
236     WarningsState *st = warnings_get_state(interp);
237     if (st == NULL) {
238         return NULL;
239     }
240 
241     registry = GET_WARNINGS_ATTR(interp, onceregistry, 0);
242     if (registry == NULL) {
243         if (PyErr_Occurred())
244             return NULL;
245         assert(st->once_registry);
246         return st->once_registry;
247     }
248     if (!PyDict_Check(registry)) {
249         PyErr_Format(PyExc_TypeError,
250                      MODULE_NAME ".onceregistry must be a dict, "
251                      "not '%.200s'",
252                      Py_TYPE(registry)->tp_name);
253         Py_DECREF(registry);
254         return NULL;
255     }
256     Py_SETREF(st->once_registry, registry);
257     return registry;
258 }
259 
260 
261 static PyObject *
get_default_action(PyInterpreterState * interp)262 get_default_action(PyInterpreterState *interp)
263 {
264     PyObject *default_action;
265 
266     WarningsState *st = warnings_get_state(interp);
267     if (st == NULL) {
268         return NULL;
269     }
270 
271     default_action = GET_WARNINGS_ATTR(interp, defaultaction, 0);
272     if (default_action == NULL) {
273         if (PyErr_Occurred()) {
274             return NULL;
275         }
276         assert(st->default_action);
277         return st->default_action;
278     }
279     if (!PyUnicode_Check(default_action)) {
280         PyErr_Format(PyExc_TypeError,
281                      MODULE_NAME ".defaultaction must be a string, "
282                      "not '%.200s'",
283                      Py_TYPE(default_action)->tp_name);
284         Py_DECREF(default_action);
285         return NULL;
286     }
287     Py_SETREF(st->default_action, default_action);
288     return default_action;
289 }
290 
291 
292 /* The item is a new reference. */
293 static PyObject*
get_filter(PyInterpreterState * interp,PyObject * category,PyObject * text,Py_ssize_t lineno,PyObject * module,PyObject ** item)294 get_filter(PyInterpreterState *interp, PyObject *category,
295            PyObject *text, Py_ssize_t lineno,
296            PyObject *module, PyObject **item)
297 {
298     PyObject *action;
299     Py_ssize_t i;
300     PyObject *warnings_filters;
301     WarningsState *st = warnings_get_state(interp);
302     if (st == NULL) {
303         return NULL;
304     }
305 
306     warnings_filters = GET_WARNINGS_ATTR(interp, filters, 0);
307     if (warnings_filters == NULL) {
308         if (PyErr_Occurred())
309             return NULL;
310     }
311     else {
312         Py_SETREF(st->filters, warnings_filters);
313     }
314 
315     PyObject *filters = st->filters;
316     if (filters == NULL || !PyList_Check(filters)) {
317         PyErr_SetString(PyExc_ValueError,
318                         MODULE_NAME ".filters must be a list");
319         return NULL;
320     }
321 
322     /* WarningsState.filters could change while we are iterating over it. */
323     for (i = 0; i < PyList_GET_SIZE(filters); i++) {
324         PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
325         Py_ssize_t ln;
326         int is_subclass, good_msg, good_mod;
327 
328         tmp_item = PyList_GET_ITEM(filters, i);
329         if (!PyTuple_Check(tmp_item) || PyTuple_GET_SIZE(tmp_item) != 5) {
330             PyErr_Format(PyExc_ValueError,
331                          MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
332             return NULL;
333         }
334 
335         /* Python code: action, msg, cat, mod, ln = item */
336         Py_INCREF(tmp_item);
337         action = PyTuple_GET_ITEM(tmp_item, 0);
338         msg = PyTuple_GET_ITEM(tmp_item, 1);
339         cat = PyTuple_GET_ITEM(tmp_item, 2);
340         mod = PyTuple_GET_ITEM(tmp_item, 3);
341         ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
342 
343         if (!PyUnicode_Check(action)) {
344             PyErr_Format(PyExc_TypeError,
345                          "action must be a string, not '%.200s'",
346                          Py_TYPE(action)->tp_name);
347             Py_DECREF(tmp_item);
348             return NULL;
349         }
350 
351         good_msg = check_matched(interp, msg, text);
352         if (good_msg == -1) {
353             Py_DECREF(tmp_item);
354             return NULL;
355         }
356 
357         good_mod = check_matched(interp, mod, module);
358         if (good_mod == -1) {
359             Py_DECREF(tmp_item);
360             return NULL;
361         }
362 
363         is_subclass = PyObject_IsSubclass(category, cat);
364         if (is_subclass == -1) {
365             Py_DECREF(tmp_item);
366             return NULL;
367         }
368 
369         ln = PyLong_AsSsize_t(ln_obj);
370         if (ln == -1 && PyErr_Occurred()) {
371             Py_DECREF(tmp_item);
372             return NULL;
373         }
374 
375         if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln)) {
376             *item = tmp_item;
377             return action;
378         }
379 
380         Py_DECREF(tmp_item);
381     }
382 
383     action = get_default_action(interp);
384     if (action != NULL) {
385         Py_INCREF(Py_None);
386         *item = Py_None;
387         return action;
388     }
389 
390     return NULL;
391 }
392 
393 
394 static int
already_warned(PyInterpreterState * interp,PyObject * registry,PyObject * key,int should_set)395 already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
396                int should_set)
397 {
398     PyObject *version_obj, *already_warned;
399 
400     if (key == NULL)
401         return -1;
402 
403     WarningsState *st = warnings_get_state(interp);
404     if (st == NULL) {
405         return -1;
406     }
407     version_obj = _PyDict_GetItemWithError(registry, &_Py_ID(version));
408     if (version_obj == NULL
409         || !PyLong_CheckExact(version_obj)
410         || PyLong_AsLong(version_obj) != st->filters_version)
411     {
412         if (PyErr_Occurred()) {
413             return -1;
414         }
415         PyDict_Clear(registry);
416         version_obj = PyLong_FromLong(st->filters_version);
417         if (version_obj == NULL)
418             return -1;
419         if (PyDict_SetItem(registry, &_Py_ID(version), version_obj) < 0) {
420             Py_DECREF(version_obj);
421             return -1;
422         }
423         Py_DECREF(version_obj);
424     }
425     else {
426         already_warned = PyDict_GetItemWithError(registry, key);
427         if (already_warned != NULL) {
428             int rc = PyObject_IsTrue(already_warned);
429             if (rc != 0)
430                 return rc;
431         }
432         else if (PyErr_Occurred()) {
433             return -1;
434         }
435     }
436 
437     /* This warning wasn't found in the registry, set it. */
438     if (should_set)
439         return PyDict_SetItem(registry, key, Py_True);
440     return 0;
441 }
442 
443 /* New reference. */
444 static PyObject *
normalize_module(PyObject * filename)445 normalize_module(PyObject *filename)
446 {
447     PyObject *module;
448     int kind;
449     const void *data;
450     Py_ssize_t len;
451 
452     len = PyUnicode_GetLength(filename);
453     if (len < 0)
454         return NULL;
455 
456     if (len == 0)
457         return PyUnicode_FromString("<unknown>");
458 
459     kind = PyUnicode_KIND(filename);
460     data = PyUnicode_DATA(filename);
461 
462     /* if filename.endswith(".py"): */
463     if (len >= 3 &&
464         PyUnicode_READ(kind, data, len-3) == '.' &&
465         PyUnicode_READ(kind, data, len-2) == 'p' &&
466         PyUnicode_READ(kind, data, len-1) == 'y')
467     {
468         module = PyUnicode_Substring(filename, 0, len-3);
469     }
470     else {
471         module = filename;
472         Py_INCREF(module);
473     }
474     return module;
475 }
476 
477 static int
update_registry(PyInterpreterState * interp,PyObject * registry,PyObject * text,PyObject * category,int add_zero)478 update_registry(PyInterpreterState *interp, PyObject *registry, PyObject *text,
479                 PyObject *category, int add_zero)
480 {
481     PyObject *altkey;
482     int rc;
483 
484     if (add_zero)
485         altkey = PyTuple_Pack(3, text, category, _PyLong_GetZero());
486     else
487         altkey = PyTuple_Pack(2, text, category);
488 
489     rc = already_warned(interp, registry, altkey, 1);
490     Py_XDECREF(altkey);
491     return rc;
492 }
493 
494 static void
show_warning(PyThreadState * tstate,PyObject * filename,int lineno,PyObject * text,PyObject * category,PyObject * sourceline)495 show_warning(PyThreadState *tstate, PyObject *filename, int lineno,
496              PyObject *text, PyObject *category, PyObject *sourceline)
497 {
498     PyObject *f_stderr;
499     PyObject *name;
500     char lineno_str[128];
501 
502     PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
503 
504     name = PyObject_GetAttr(category, &_Py_ID(__name__));
505     if (name == NULL) {
506         goto error;
507     }
508 
509     f_stderr = _PySys_GetAttr(tstate, &_Py_ID(stderr));
510     if (f_stderr == NULL) {
511         fprintf(stderr, "lost sys.stderr\n");
512         goto error;
513     }
514 
515     /* Print "filename:lineno: category: text\n" */
516     if (PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW) < 0)
517         goto error;
518     if (PyFile_WriteString(lineno_str, f_stderr) < 0)
519         goto error;
520     if (PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW) < 0)
521         goto error;
522     if (PyFile_WriteString(": ", f_stderr) < 0)
523         goto error;
524     if (PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW) < 0)
525         goto error;
526     if (PyFile_WriteString("\n", f_stderr) < 0)
527         goto error;
528     Py_CLEAR(name);
529 
530     /* Print "  source_line\n" */
531     if (sourceline) {
532         int kind;
533         const void *data;
534         Py_ssize_t i, len;
535         Py_UCS4 ch;
536         PyObject *truncated;
537 
538         if (PyUnicode_READY(sourceline) < 1)
539             goto error;
540 
541         kind = PyUnicode_KIND(sourceline);
542         data = PyUnicode_DATA(sourceline);
543         len = PyUnicode_GET_LENGTH(sourceline);
544         for (i=0; i<len; i++) {
545             ch = PyUnicode_READ(kind, data, i);
546             if (ch != ' ' && ch != '\t' && ch != '\014')
547                 break;
548         }
549 
550         truncated = PyUnicode_Substring(sourceline, i, len);
551         if (truncated == NULL)
552             goto error;
553 
554         PyFile_WriteObject(sourceline, f_stderr, Py_PRINT_RAW);
555         Py_DECREF(truncated);
556         PyFile_WriteString("\n", f_stderr);
557     }
558     else {
559         _Py_DisplaySourceLine(f_stderr, filename, lineno, 2, NULL, NULL);
560     }
561 
562 error:
563     Py_XDECREF(name);
564     PyErr_Clear();
565 }
566 
567 static int
call_show_warning(PyThreadState * tstate,PyObject * category,PyObject * text,PyObject * message,PyObject * filename,int lineno,PyObject * lineno_obj,PyObject * sourceline,PyObject * source)568 call_show_warning(PyThreadState *tstate, PyObject *category,
569                   PyObject *text, PyObject *message,
570                   PyObject *filename, int lineno, PyObject *lineno_obj,
571                   PyObject *sourceline, PyObject *source)
572 {
573     PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL;
574     PyInterpreterState *interp = tstate->interp;
575 
576     /* If the source parameter is set, try to get the Python implementation.
577        The Python implementation is able to log the traceback where the source
578        was allocated, whereas the C implementation doesn't. */
579     show_fn = GET_WARNINGS_ATTR(interp, _showwarnmsg, source != NULL);
580     if (show_fn == NULL) {
581         if (PyErr_Occurred())
582             return -1;
583         show_warning(tstate, filename, lineno, text, category, sourceline);
584         return 0;
585     }
586 
587     if (!PyCallable_Check(show_fn)) {
588         PyErr_SetString(PyExc_TypeError,
589                 "warnings._showwarnmsg() must be set to a callable");
590         goto error;
591     }
592 
593     warnmsg_cls = GET_WARNINGS_ATTR(interp, WarningMessage, 0);
594     if (warnmsg_cls == NULL) {
595         if (!PyErr_Occurred()) {
596             PyErr_SetString(PyExc_RuntimeError,
597                     "unable to get warnings.WarningMessage");
598         }
599         goto error;
600     }
601 
602     msg = PyObject_CallFunctionObjArgs(warnmsg_cls, message, category,
603             filename, lineno_obj, Py_None, Py_None, source,
604             NULL);
605     Py_DECREF(warnmsg_cls);
606     if (msg == NULL)
607         goto error;
608 
609     res = PyObject_CallOneArg(show_fn, msg);
610     Py_DECREF(show_fn);
611     Py_DECREF(msg);
612 
613     if (res == NULL)
614         return -1;
615 
616     Py_DECREF(res);
617     return 0;
618 
619 error:
620     Py_XDECREF(show_fn);
621     return -1;
622 }
623 
624 static PyObject *
warn_explicit(PyThreadState * tstate,PyObject * category,PyObject * message,PyObject * filename,int lineno,PyObject * module,PyObject * registry,PyObject * sourceline,PyObject * source)625 warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message,
626               PyObject *filename, int lineno,
627               PyObject *module, PyObject *registry, PyObject *sourceline,
628               PyObject *source)
629 {
630     PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
631     PyObject *item = NULL;
632     PyObject *action;
633     int rc;
634     PyInterpreterState *interp = tstate->interp;
635 
636     /* module can be None if a warning is emitted late during Python shutdown.
637        In this case, the Python warnings module was probably unloaded, filters
638        are no more available to choose as action. It is safer to ignore the
639        warning and do nothing. */
640     if (module == Py_None)
641         Py_RETURN_NONE;
642 
643     if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
644         PyErr_SetString(PyExc_TypeError, "'registry' must be a dict or None");
645         return NULL;
646     }
647 
648     /* Normalize module. */
649     if (module == NULL) {
650         module = normalize_module(filename);
651         if (module == NULL)
652             return NULL;
653     }
654     else
655         Py_INCREF(module);
656 
657     /* Normalize message. */
658     Py_INCREF(message);  /* DECREF'ed in cleanup. */
659     rc = PyObject_IsInstance(message, PyExc_Warning);
660     if (rc == -1) {
661         goto cleanup;
662     }
663     if (rc == 1) {
664         text = PyObject_Str(message);
665         if (text == NULL)
666             goto cleanup;
667         category = (PyObject*)Py_TYPE(message);
668     }
669     else {
670         text = message;
671         message = PyObject_CallOneArg(category, message);
672         if (message == NULL)
673             goto cleanup;
674     }
675 
676     lineno_obj = PyLong_FromLong(lineno);
677     if (lineno_obj == NULL)
678         goto cleanup;
679 
680     if (source == Py_None) {
681         source = NULL;
682     }
683 
684     /* Create key. */
685     key = PyTuple_Pack(3, text, category, lineno_obj);
686     if (key == NULL)
687         goto cleanup;
688 
689     if ((registry != NULL) && (registry != Py_None)) {
690         rc = already_warned(interp, registry, key, 0);
691         if (rc == -1)
692             goto cleanup;
693         else if (rc == 1)
694             goto return_none;
695         /* Else this warning hasn't been generated before. */
696     }
697 
698     action = get_filter(interp, category, text, lineno, module, &item);
699     if (action == NULL)
700         goto cleanup;
701 
702     if (_PyUnicode_EqualToASCIIString(action, "error")) {
703         PyErr_SetObject(category, message);
704         goto cleanup;
705     }
706 
707     if (_PyUnicode_EqualToASCIIString(action, "ignore")) {
708         goto return_none;
709     }
710 
711     /* Store in the registry that we've been here, *except* when the action
712        is "always". */
713     rc = 0;
714     if (!_PyUnicode_EqualToASCIIString(action, "always")) {
715         if (registry != NULL && registry != Py_None &&
716             PyDict_SetItem(registry, key, Py_True) < 0)
717         {
718             goto cleanup;
719         }
720 
721         if (_PyUnicode_EqualToASCIIString(action, "once")) {
722             if (registry == NULL || registry == Py_None) {
723                 registry = get_once_registry(interp);
724                 if (registry == NULL)
725                     goto cleanup;
726             }
727             /* WarningsState.once_registry[(text, category)] = 1 */
728             rc = update_registry(interp, registry, text, category, 0);
729         }
730         else if (_PyUnicode_EqualToASCIIString(action, "module")) {
731             /* registry[(text, category, 0)] = 1 */
732             if (registry != NULL && registry != Py_None)
733                 rc = update_registry(interp, registry, text, category, 0);
734         }
735         else if (!_PyUnicode_EqualToASCIIString(action, "default")) {
736             PyErr_Format(PyExc_RuntimeError,
737                         "Unrecognized action (%R) in warnings.filters:\n %R",
738                         action, item);
739             goto cleanup;
740         }
741     }
742 
743     if (rc == 1)  /* Already warned for this module. */
744         goto return_none;
745     if (rc == 0) {
746         if (call_show_warning(tstate, category, text, message, filename,
747                               lineno, lineno_obj, sourceline, source) < 0)
748             goto cleanup;
749     }
750     else /* if (rc == -1) */
751         goto cleanup;
752 
753  return_none:
754     result = Py_None;
755     Py_INCREF(result);
756 
757  cleanup:
758     Py_XDECREF(item);
759     Py_XDECREF(key);
760     Py_XDECREF(text);
761     Py_XDECREF(lineno_obj);
762     Py_DECREF(module);
763     Py_XDECREF(message);
764     return result;  /* Py_None or NULL. */
765 }
766 
767 static int
is_internal_frame(PyFrameObject * frame)768 is_internal_frame(PyFrameObject *frame)
769 {
770     if (frame == NULL) {
771         return 0;
772     }
773 
774     PyCodeObject *code = PyFrame_GetCode(frame);
775     PyObject *filename = code->co_filename;
776     Py_DECREF(code);
777 
778     if (filename == NULL) {
779         return 0;
780     }
781     if (!PyUnicode_Check(filename)) {
782         return 0;
783     }
784 
785     int contains = PyUnicode_Contains(filename, &_Py_ID(importlib));
786     if (contains < 0) {
787         return 0;
788     }
789     else if (contains > 0) {
790         contains = PyUnicode_Contains(filename, &_Py_ID(_bootstrap));
791         if (contains < 0) {
792             return 0;
793         }
794         else if (contains > 0) {
795             return 1;
796         }
797     }
798 
799     return 0;
800 }
801 
802 static PyFrameObject *
next_external_frame(PyFrameObject * frame)803 next_external_frame(PyFrameObject *frame)
804 {
805     do {
806         PyFrameObject *back = PyFrame_GetBack(frame);
807         Py_DECREF(frame);
808         frame = back;
809     } while (frame != NULL && is_internal_frame(frame));
810 
811     return frame;
812 }
813 
814 /* filename, module, and registry are new refs, globals is borrowed */
815 /* Returns 0 on error (no new refs), 1 on success */
816 static int
setup_context(Py_ssize_t stack_level,PyObject ** filename,int * lineno,PyObject ** module,PyObject ** registry)817 setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
818               PyObject **module, PyObject **registry)
819 {
820     PyObject *globals;
821 
822     /* Setup globals, filename and lineno. */
823     PyThreadState *tstate = get_current_tstate();
824     if (tstate == NULL) {
825         return 0;
826     }
827     PyInterpreterState *interp = tstate->interp;
828     PyFrameObject *f = PyThreadState_GetFrame(tstate);
829     // Stack level comparisons to Python code is off by one as there is no
830     // warnings-related stack level to avoid.
831     if (stack_level <= 0 || is_internal_frame(f)) {
832         while (--stack_level > 0 && f != NULL) {
833             PyFrameObject *back = PyFrame_GetBack(f);
834             Py_DECREF(f);
835             f = back;
836         }
837     }
838     else {
839         while (--stack_level > 0 && f != NULL) {
840             f = next_external_frame(f);
841         }
842     }
843 
844     if (f == NULL) {
845         globals = interp->sysdict;
846         *filename = PyUnicode_FromString("sys");
847         *lineno = 1;
848     }
849     else {
850         globals = f->f_frame->f_globals;
851         *filename = f->f_frame->f_code->co_filename;
852         Py_INCREF(*filename);
853         *lineno = PyFrame_GetLineNumber(f);
854         Py_DECREF(f);
855     }
856 
857     *module = NULL;
858 
859     /* Setup registry. */
860     assert(globals != NULL);
861     assert(PyDict_Check(globals));
862     *registry = _PyDict_GetItemWithError(globals, &_Py_ID(__warningregistry__));
863     if (*registry == NULL) {
864         int rc;
865 
866         if (_PyErr_Occurred(tstate)) {
867             goto handle_error;
868         }
869         *registry = PyDict_New();
870         if (*registry == NULL)
871             goto handle_error;
872 
873          rc = PyDict_SetItem(globals, &_Py_ID(__warningregistry__), *registry);
874          if (rc < 0)
875             goto handle_error;
876     }
877     else
878         Py_INCREF(*registry);
879 
880     /* Setup module. */
881     *module = _PyDict_GetItemWithError(globals, &_Py_ID(__name__));
882     if (*module == Py_None || (*module != NULL && PyUnicode_Check(*module))) {
883         Py_INCREF(*module);
884     }
885     else if (_PyErr_Occurred(tstate)) {
886         goto handle_error;
887     }
888     else {
889         *module = PyUnicode_FromString("<string>");
890         if (*module == NULL)
891             goto handle_error;
892     }
893 
894     return 1;
895 
896  handle_error:
897     Py_XDECREF(*registry);
898     Py_XDECREF(*module);
899     Py_DECREF(*filename);
900     return 0;
901 }
902 
903 static PyObject *
get_category(PyObject * message,PyObject * category)904 get_category(PyObject *message, PyObject *category)
905 {
906     int rc;
907 
908     /* Get category. */
909     rc = PyObject_IsInstance(message, PyExc_Warning);
910     if (rc == -1)
911         return NULL;
912 
913     if (rc == 1)
914         category = (PyObject*)Py_TYPE(message);
915     else if (category == NULL || category == Py_None)
916         category = PyExc_UserWarning;
917 
918     /* Validate category. */
919     rc = PyObject_IsSubclass(category, PyExc_Warning);
920     /* category is not a subclass of PyExc_Warning or
921        PyObject_IsSubclass raised an error */
922     if (rc == -1 || rc == 0) {
923         PyErr_Format(PyExc_TypeError,
924                      "category must be a Warning subclass, not '%s'",
925                      Py_TYPE(category)->tp_name);
926         return NULL;
927     }
928 
929     return category;
930 }
931 
932 static PyObject *
do_warn(PyObject * message,PyObject * category,Py_ssize_t stack_level,PyObject * source)933 do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
934         PyObject *source)
935 {
936     PyObject *filename, *module, *registry, *res;
937     int lineno;
938 
939     PyThreadState *tstate = get_current_tstate();
940     if (tstate == NULL) {
941         return NULL;
942     }
943 
944     if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
945         return NULL;
946 
947     res = warn_explicit(tstate, category, message, filename, lineno, module, registry,
948                         NULL, source);
949     Py_DECREF(filename);
950     Py_DECREF(registry);
951     Py_DECREF(module);
952     return res;
953 }
954 
955 /*[clinic input]
956 warn as warnings_warn
957 
958     message: object
959     category: object = None
960     stacklevel: Py_ssize_t = 1
961     source: object = None
962 
963 Issue a warning, or maybe ignore it or raise an exception.
964 [clinic start generated code]*/
965 
966 static PyObject *
warnings_warn_impl(PyObject * module,PyObject * message,PyObject * category,Py_ssize_t stacklevel,PyObject * source)967 warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
968                    Py_ssize_t stacklevel, PyObject *source)
969 /*[clinic end generated code: output=31ed5ab7d8d760b2 input=bfdf5cf99f6c4edd]*/
970 {
971     category = get_category(message, category);
972     if (category == NULL)
973         return NULL;
974     return do_warn(message, category, stacklevel, source);
975 }
976 
977 static PyObject *
get_source_line(PyInterpreterState * interp,PyObject * module_globals,int lineno)978 get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno)
979 {
980     PyObject *loader;
981     PyObject *module_name;
982     PyObject *get_source;
983     PyObject *source;
984     PyObject *source_list;
985     PyObject *source_line;
986 
987     /* Check/get the requisite pieces needed for the loader. */
988     loader = _PyDict_GetItemWithError(module_globals, &_Py_ID(__loader__));
989     if (loader == NULL) {
990         return NULL;
991     }
992     Py_INCREF(loader);
993     module_name = _PyDict_GetItemWithError(module_globals, &_Py_ID(__name__));
994     if (!module_name) {
995         Py_DECREF(loader);
996         return NULL;
997     }
998     Py_INCREF(module_name);
999 
1000     /* Make sure the loader implements the optional get_source() method. */
1001     (void)_PyObject_LookupAttr(loader, &_Py_ID(get_source), &get_source);
1002     Py_DECREF(loader);
1003     if (!get_source) {
1004         Py_DECREF(module_name);
1005         return NULL;
1006     }
1007     /* Call get_source() to get the source code. */
1008     source = PyObject_CallOneArg(get_source, module_name);
1009     Py_DECREF(get_source);
1010     Py_DECREF(module_name);
1011     if (!source) {
1012         return NULL;
1013     }
1014     if (source == Py_None) {
1015         Py_DECREF(source);
1016         return NULL;
1017     }
1018 
1019     /* Split the source into lines. */
1020     source_list = PyUnicode_Splitlines(source, 0);
1021     Py_DECREF(source);
1022     if (!source_list) {
1023         return NULL;
1024     }
1025 
1026     /* Get the source line. */
1027     source_line = PyList_GetItem(source_list, lineno-1);
1028     Py_XINCREF(source_line);
1029     Py_DECREF(source_list);
1030     return source_line;
1031 }
1032 
1033 static PyObject *
warnings_warn_explicit(PyObject * self,PyObject * args,PyObject * kwds)1034 warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
1035 {
1036     static char *kwd_list[] = {"message", "category", "filename", "lineno",
1037                                 "module", "registry", "module_globals",
1038                                 "source", 0};
1039     PyObject *message;
1040     PyObject *category;
1041     PyObject *filename;
1042     int lineno;
1043     PyObject *module = NULL;
1044     PyObject *registry = NULL;
1045     PyObject *module_globals = NULL;
1046     PyObject *sourceobj = NULL;
1047     PyObject *source_line = NULL;
1048     PyObject *returned;
1049 
1050     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit",
1051                 kwd_list, &message, &category, &filename, &lineno, &module,
1052                 &registry, &module_globals, &sourceobj))
1053         return NULL;
1054 
1055     PyThreadState *tstate = get_current_tstate();
1056     if (tstate == NULL) {
1057         return NULL;
1058     }
1059 
1060     if (module_globals && module_globals != Py_None) {
1061         if (!PyDict_Check(module_globals)) {
1062             PyErr_Format(PyExc_TypeError,
1063                          "module_globals must be a dict, not '%.200s'",
1064                          Py_TYPE(module_globals)->tp_name);
1065             return NULL;
1066         }
1067 
1068         source_line = get_source_line(tstate->interp, module_globals, lineno);
1069         if (source_line == NULL && PyErr_Occurred()) {
1070             return NULL;
1071         }
1072     }
1073     returned = warn_explicit(tstate, category, message, filename, lineno, module,
1074                              registry, source_line, sourceobj);
1075     Py_XDECREF(source_line);
1076     return returned;
1077 }
1078 
1079 static PyObject *
warnings_filters_mutated(PyObject * self,PyObject * Py_UNUSED (args))1080 warnings_filters_mutated(PyObject *self, PyObject *Py_UNUSED(args))
1081 {
1082     PyInterpreterState *interp = get_current_interp();
1083     if (interp == NULL) {
1084         return NULL;
1085     }
1086     WarningsState *st = warnings_get_state(interp);
1087     if (st == NULL) {
1088         return NULL;
1089     }
1090     st->filters_version++;
1091     Py_RETURN_NONE;
1092 }
1093 
1094 
1095 /* Function to issue a warning message; may raise an exception. */
1096 
1097 static int
warn_unicode(PyObject * category,PyObject * message,Py_ssize_t stack_level,PyObject * source)1098 warn_unicode(PyObject *category, PyObject *message,
1099              Py_ssize_t stack_level, PyObject *source)
1100 {
1101     PyObject *res;
1102 
1103     if (category == NULL)
1104         category = PyExc_RuntimeWarning;
1105 
1106     res = do_warn(message, category, stack_level, source);
1107     if (res == NULL)
1108         return -1;
1109     Py_DECREF(res);
1110 
1111     return 0;
1112 }
1113 
1114 static int
_PyErr_WarnFormatV(PyObject * source,PyObject * category,Py_ssize_t stack_level,const char * format,va_list vargs)1115 _PyErr_WarnFormatV(PyObject *source,
1116                    PyObject *category, Py_ssize_t stack_level,
1117                    const char *format, va_list vargs)
1118 {
1119     PyObject *message;
1120     int res;
1121 
1122     message = PyUnicode_FromFormatV(format, vargs);
1123     if (message == NULL)
1124         return -1;
1125 
1126     res = warn_unicode(category, message, stack_level, source);
1127     Py_DECREF(message);
1128     return res;
1129 }
1130 
1131 int
PyErr_WarnFormat(PyObject * category,Py_ssize_t stack_level,const char * format,...)1132 PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
1133                  const char *format, ...)
1134 {
1135     int res;
1136     va_list vargs;
1137 
1138 #ifdef HAVE_STDARG_PROTOTYPES
1139     va_start(vargs, format);
1140 #else
1141     va_start(vargs);
1142 #endif
1143     res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
1144     va_end(vargs);
1145     return res;
1146 }
1147 
1148 static int
_PyErr_WarnFormat(PyObject * source,PyObject * category,Py_ssize_t stack_level,const char * format,...)1149 _PyErr_WarnFormat(PyObject *source, PyObject *category, Py_ssize_t stack_level,
1150                   const char *format, ...)
1151 {
1152     int res;
1153     va_list vargs;
1154 
1155 #ifdef HAVE_STDARG_PROTOTYPES
1156     va_start(vargs, format);
1157 #else
1158     va_start(vargs);
1159 #endif
1160     res = _PyErr_WarnFormatV(source, category, stack_level, format, vargs);
1161     va_end(vargs);
1162     return res;
1163 }
1164 
1165 int
PyErr_ResourceWarning(PyObject * source,Py_ssize_t stack_level,const char * format,...)1166 PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
1167                       const char *format, ...)
1168 {
1169     int res;
1170     va_list vargs;
1171 
1172 #ifdef HAVE_STDARG_PROTOTYPES
1173     va_start(vargs, format);
1174 #else
1175     va_start(vargs);
1176 #endif
1177     res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
1178                              stack_level, format, vargs);
1179     va_end(vargs);
1180     return res;
1181 }
1182 
1183 
1184 int
PyErr_WarnEx(PyObject * category,const char * text,Py_ssize_t stack_level)1185 PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
1186 {
1187     int ret;
1188     PyObject *message = PyUnicode_FromString(text);
1189     if (message == NULL)
1190         return -1;
1191     ret = warn_unicode(category, message, stack_level, NULL);
1192     Py_DECREF(message);
1193     return ret;
1194 }
1195 
1196 /* PyErr_Warn is only for backwards compatibility and will be removed.
1197    Use PyErr_WarnEx instead. */
1198 
1199 #undef PyErr_Warn
1200 
1201 int
PyErr_Warn(PyObject * category,const char * text)1202 PyErr_Warn(PyObject *category, const char *text)
1203 {
1204     return PyErr_WarnEx(category, text, 1);
1205 }
1206 
1207 /* Warning with explicit origin */
1208 int
PyErr_WarnExplicitObject(PyObject * category,PyObject * message,PyObject * filename,int lineno,PyObject * module,PyObject * registry)1209 PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
1210                          PyObject *filename, int lineno,
1211                          PyObject *module, PyObject *registry)
1212 {
1213     PyObject *res;
1214     if (category == NULL)
1215         category = PyExc_RuntimeWarning;
1216     PyThreadState *tstate = get_current_tstate();
1217     if (tstate == NULL) {
1218         return -1;
1219     }
1220     res = warn_explicit(tstate, category, message, filename, lineno,
1221                         module, registry, NULL, NULL);
1222     if (res == NULL)
1223         return -1;
1224     Py_DECREF(res);
1225     return 0;
1226 }
1227 
1228 int
PyErr_WarnExplicit(PyObject * category,const char * text,const char * filename_str,int lineno,const char * module_str,PyObject * registry)1229 PyErr_WarnExplicit(PyObject *category, const char *text,
1230                    const char *filename_str, int lineno,
1231                    const char *module_str, PyObject *registry)
1232 {
1233     PyObject *message = PyUnicode_FromString(text);
1234     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1235     PyObject *module = NULL;
1236     int ret = -1;
1237 
1238     if (message == NULL || filename == NULL)
1239         goto exit;
1240     if (module_str != NULL) {
1241         module = PyUnicode_FromString(module_str);
1242         if (module == NULL)
1243             goto exit;
1244     }
1245 
1246     ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
1247                                    module, registry);
1248 
1249  exit:
1250     Py_XDECREF(message);
1251     Py_XDECREF(module);
1252     Py_XDECREF(filename);
1253     return ret;
1254 }
1255 
1256 int
PyErr_WarnExplicitFormat(PyObject * category,const char * filename_str,int lineno,const char * module_str,PyObject * registry,const char * format,...)1257 PyErr_WarnExplicitFormat(PyObject *category,
1258                          const char *filename_str, int lineno,
1259                          const char *module_str, PyObject *registry,
1260                          const char *format, ...)
1261 {
1262     PyObject *message;
1263     PyObject *module = NULL;
1264     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1265     int ret = -1;
1266     va_list vargs;
1267 
1268     if (filename == NULL)
1269         goto exit;
1270     if (module_str != NULL) {
1271         module = PyUnicode_FromString(module_str);
1272         if (module == NULL)
1273             goto exit;
1274     }
1275 
1276 #ifdef HAVE_STDARG_PROTOTYPES
1277     va_start(vargs, format);
1278 #else
1279     va_start(vargs);
1280 #endif
1281     message = PyUnicode_FromFormatV(format, vargs);
1282     if (message != NULL) {
1283         PyObject *res;
1284         PyThreadState *tstate = get_current_tstate();
1285         if (tstate != NULL) {
1286             res = warn_explicit(tstate, category, message, filename, lineno,
1287                                 module, registry, NULL, NULL);
1288             Py_DECREF(message);
1289             if (res != NULL) {
1290                 Py_DECREF(res);
1291                 ret = 0;
1292             }
1293         }
1294     }
1295     va_end(vargs);
1296 exit:
1297     Py_XDECREF(module);
1298     Py_XDECREF(filename);
1299     return ret;
1300 }
1301 
1302 void
_PyErr_WarnUnawaitedCoroutine(PyObject * coro)1303 _PyErr_WarnUnawaitedCoroutine(PyObject *coro)
1304 {
1305     /* First, we attempt to funnel the warning through
1306        warnings._warn_unawaited_coroutine.
1307 
1308        This could raise an exception, due to:
1309        - a bug
1310        - some kind of shutdown-related brokenness
1311        - succeeding, but with an "error" warning filter installed, so the
1312          warning is converted into a RuntimeWarning exception
1313 
1314        In the first two cases, we want to print the error (so we know what it
1315        is!), and then print a warning directly as a fallback. In the last
1316        case, we want to print the error (since it's the warning!), but *not*
1317        do a fallback. And after we print the error we can't check for what
1318        type of error it was (because PyErr_WriteUnraisable clears it), so we
1319        need a flag to keep track.
1320 
1321        Since this is called from __del__ context, it's careful to never raise
1322        an exception.
1323     */
1324     int warned = 0;
1325     PyInterpreterState *interp = _PyInterpreterState_GET();
1326     assert(interp != NULL);
1327     PyObject *fn = GET_WARNINGS_ATTR(interp, _warn_unawaited_coroutine, 1);
1328     if (fn) {
1329         PyObject *res = PyObject_CallOneArg(fn, coro);
1330         Py_DECREF(fn);
1331         if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
1332             warned = 1;
1333         }
1334         Py_XDECREF(res);
1335     }
1336 
1337     if (PyErr_Occurred()) {
1338         PyErr_WriteUnraisable(coro);
1339     }
1340     if (!warned) {
1341         if (_PyErr_WarnFormat(coro, PyExc_RuntimeWarning, 1,
1342                               "coroutine '%S' was never awaited",
1343                               ((PyCoroObject *)coro)->cr_qualname) < 0)
1344         {
1345             PyErr_WriteUnraisable(coro);
1346         }
1347     }
1348 }
1349 
1350 PyDoc_STRVAR(warn_explicit_doc,
1351 "Low-level interface to warnings functionality.");
1352 
1353 static PyMethodDef warnings_functions[] = {
1354     WARNINGS_WARN_METHODDEF
1355     {"warn_explicit", _PyCFunction_CAST(warnings_warn_explicit),
1356         METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
1357     {"_filters_mutated", _PyCFunction_CAST(warnings_filters_mutated), METH_NOARGS,
1358         NULL},
1359     /* XXX(brett.cannon): add showwarning? */
1360     /* XXX(brett.cannon): Reasonable to add formatwarning? */
1361     {NULL, NULL}                /* sentinel */
1362 };
1363 
1364 
1365 static int
warnings_module_exec(PyObject * module)1366 warnings_module_exec(PyObject *module)
1367 {
1368     PyInterpreterState *interp = get_current_interp();
1369     if (interp == NULL) {
1370         return -1;
1371     }
1372     WarningsState *st = warnings_get_state(interp);
1373     if (st == NULL) {
1374         return -1;
1375     }
1376     if (PyModule_AddObjectRef(module, "filters", st->filters) < 0) {
1377         return -1;
1378     }
1379     if (PyModule_AddObjectRef(module, "_onceregistry", st->once_registry) < 0) {
1380         return -1;
1381     }
1382     if (PyModule_AddObjectRef(module, "_defaultaction", st->default_action) < 0) {
1383         return -1;
1384     }
1385     return 0;
1386 }
1387 
1388 
1389 static PyModuleDef_Slot warnings_slots[] = {
1390     {Py_mod_exec, warnings_module_exec},
1391     {0, NULL}
1392 };
1393 
1394 static struct PyModuleDef warnings_module = {
1395     PyModuleDef_HEAD_INIT,
1396     .m_name = MODULE_NAME,
1397     .m_doc = warnings__doc__,
1398     .m_size = 0,
1399     .m_methods = warnings_functions,
1400     .m_slots = warnings_slots,
1401 };
1402 
1403 
1404 PyMODINIT_FUNC
_PyWarnings_Init(void)1405 _PyWarnings_Init(void)
1406 {
1407     return PyModuleDef_Init(&warnings_module);
1408 }
1409 
1410 // We need this to ensure that warnings still work until late in finalization.
1411 void
_PyWarnings_Fini(PyInterpreterState * interp)1412 _PyWarnings_Fini(PyInterpreterState *interp)
1413 {
1414     warnings_clear_state(&interp->warnings);
1415 }
1416