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