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