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