• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             return 0;
860         }
861         *registry = PyDict_New();
862         if (*registry == NULL)
863             return 0;
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     /* filename not XDECREF'ed here as there is no way to jump here with a
890        dangling reference. */
891     Py_XDECREF(*registry);
892     Py_XDECREF(*module);
893     return 0;
894 }
895 
896 static PyObject *
get_category(PyObject * message,PyObject * category)897 get_category(PyObject *message, PyObject *category)
898 {
899     int rc;
900 
901     /* Get category. */
902     rc = PyObject_IsInstance(message, PyExc_Warning);
903     if (rc == -1)
904         return NULL;
905 
906     if (rc == 1)
907         category = (PyObject*)message->ob_type;
908     else if (category == NULL || category == Py_None)
909         category = PyExc_UserWarning;
910 
911     /* Validate category. */
912     rc = PyObject_IsSubclass(category, PyExc_Warning);
913     /* category is not a subclass of PyExc_Warning or
914        PyObject_IsSubclass raised an error */
915     if (rc == -1 || rc == 0) {
916         PyErr_Format(PyExc_TypeError,
917                      "category must be a Warning subclass, not '%s'",
918                      Py_TYPE(category)->tp_name);
919         return NULL;
920     }
921 
922     return category;
923 }
924 
925 static PyObject *
do_warn(PyObject * message,PyObject * category,Py_ssize_t stack_level,PyObject * source)926 do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
927         PyObject *source)
928 {
929     PyObject *filename, *module, *registry, *res;
930     int lineno;
931 
932     if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
933         return NULL;
934 
935     res = warn_explicit(category, message, filename, lineno, module, registry,
936                         NULL, source);
937     Py_DECREF(filename);
938     Py_DECREF(registry);
939     Py_DECREF(module);
940     return res;
941 }
942 
943 /*[clinic input]
944 warn as warnings_warn
945 
946     message: object
947     category: object = None
948     stacklevel: Py_ssize_t = 1
949     source: object = None
950 
951 Issue a warning, or maybe ignore it or raise an exception.
952 [clinic start generated code]*/
953 
954 static PyObject *
warnings_warn_impl(PyObject * module,PyObject * message,PyObject * category,Py_ssize_t stacklevel,PyObject * source)955 warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
956                    Py_ssize_t stacklevel, PyObject *source)
957 /*[clinic end generated code: output=31ed5ab7d8d760b2 input=bfdf5cf99f6c4edd]*/
958 {
959     category = get_category(message, category);
960     if (category == NULL)
961         return NULL;
962     return do_warn(message, category, stacklevel, source);
963 }
964 
965 static PyObject *
get_source_line(PyObject * module_globals,int lineno)966 get_source_line(PyObject *module_globals, int lineno)
967 {
968     _Py_IDENTIFIER(get_source);
969     _Py_IDENTIFIER(__loader__);
970     _Py_IDENTIFIER(__name__);
971     PyObject *loader;
972     PyObject *module_name;
973     PyObject *get_source;
974     PyObject *source;
975     PyObject *source_list;
976     PyObject *source_line;
977 
978     /* Check/get the requisite pieces needed for the loader. */
979     loader = _PyDict_GetItemIdWithError(module_globals, &PyId___loader__);
980     if (loader == NULL) {
981         return NULL;
982     }
983     Py_INCREF(loader);
984     module_name = _PyDict_GetItemIdWithError(module_globals, &PyId___name__);
985     if (!module_name) {
986         Py_DECREF(loader);
987         return NULL;
988     }
989     Py_INCREF(module_name);
990 
991     /* Make sure the loader implements the optional get_source() method. */
992     (void)_PyObject_LookupAttrId(loader, &PyId_get_source, &get_source);
993     Py_DECREF(loader);
994     if (!get_source) {
995         Py_DECREF(module_name);
996         return NULL;
997     }
998     /* Call get_source() to get the source code. */
999     source = PyObject_CallFunctionObjArgs(get_source, module_name, NULL);
1000     Py_DECREF(get_source);
1001     Py_DECREF(module_name);
1002     if (!source) {
1003         return NULL;
1004     }
1005     if (source == Py_None) {
1006         Py_DECREF(source);
1007         return NULL;
1008     }
1009 
1010     /* Split the source into lines. */
1011     source_list = PyUnicode_Splitlines(source, 0);
1012     Py_DECREF(source);
1013     if (!source_list) {
1014         return NULL;
1015     }
1016 
1017     /* Get the source line. */
1018     source_line = PyList_GetItem(source_list, lineno-1);
1019     Py_XINCREF(source_line);
1020     Py_DECREF(source_list);
1021     return source_line;
1022 }
1023 
1024 static PyObject *
warnings_warn_explicit(PyObject * self,PyObject * args,PyObject * kwds)1025 warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
1026 {
1027     static char *kwd_list[] = {"message", "category", "filename", "lineno",
1028                                 "module", "registry", "module_globals",
1029                                 "source", 0};
1030     PyObject *message;
1031     PyObject *category;
1032     PyObject *filename;
1033     int lineno;
1034     PyObject *module = NULL;
1035     PyObject *registry = NULL;
1036     PyObject *module_globals = NULL;
1037     PyObject *sourceobj = NULL;
1038     PyObject *source_line = NULL;
1039     PyObject *returned;
1040 
1041     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOUi|OOOO:warn_explicit",
1042                 kwd_list, &message, &category, &filename, &lineno, &module,
1043                 &registry, &module_globals, &sourceobj))
1044         return NULL;
1045 
1046     if (module_globals && module_globals != Py_None) {
1047         if (!PyDict_Check(module_globals)) {
1048             PyErr_Format(PyExc_TypeError,
1049                          "module_globals must be a dict, not '%.200s'",
1050                          Py_TYPE(module_globals)->tp_name);
1051             return NULL;
1052         }
1053 
1054         source_line = get_source_line(module_globals, lineno);
1055         if (source_line == NULL && PyErr_Occurred()) {
1056             return NULL;
1057         }
1058     }
1059     returned = warn_explicit(category, message, filename, lineno, module,
1060                              registry, source_line, sourceobj);
1061     Py_XDECREF(source_line);
1062     return returned;
1063 }
1064 
1065 static PyObject *
warnings_filters_mutated(PyObject * self,PyObject * args)1066 warnings_filters_mutated(PyObject *self, PyObject *args)
1067 {
1068     WarningsState *st = _Warnings_GetState();
1069     if (st == NULL) {
1070         return NULL;
1071     }
1072     st->filters_version++;
1073     Py_RETURN_NONE;
1074 }
1075 
1076 
1077 /* Function to issue a warning message; may raise an exception. */
1078 
1079 static int
warn_unicode(PyObject * category,PyObject * message,Py_ssize_t stack_level,PyObject * source)1080 warn_unicode(PyObject *category, PyObject *message,
1081              Py_ssize_t stack_level, PyObject *source)
1082 {
1083     PyObject *res;
1084 
1085     if (category == NULL)
1086         category = PyExc_RuntimeWarning;
1087 
1088     res = do_warn(message, category, stack_level, source);
1089     if (res == NULL)
1090         return -1;
1091     Py_DECREF(res);
1092 
1093     return 0;
1094 }
1095 
1096 static int
_PyErr_WarnFormatV(PyObject * source,PyObject * category,Py_ssize_t stack_level,const char * format,va_list vargs)1097 _PyErr_WarnFormatV(PyObject *source,
1098                    PyObject *category, Py_ssize_t stack_level,
1099                    const char *format, va_list vargs)
1100 {
1101     PyObject *message;
1102     int res;
1103 
1104     message = PyUnicode_FromFormatV(format, vargs);
1105     if (message == NULL)
1106         return -1;
1107 
1108     res = warn_unicode(category, message, stack_level, source);
1109     Py_DECREF(message);
1110     return res;
1111 }
1112 
1113 int
PyErr_WarnFormat(PyObject * category,Py_ssize_t stack_level,const char * format,...)1114 PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level,
1115                  const char *format, ...)
1116 {
1117     int res;
1118     va_list vargs;
1119 
1120 #ifdef HAVE_STDARG_PROTOTYPES
1121     va_start(vargs, format);
1122 #else
1123     va_start(vargs);
1124 #endif
1125     res = _PyErr_WarnFormatV(NULL, category, stack_level, format, vargs);
1126     va_end(vargs);
1127     return res;
1128 }
1129 
1130 int
PyErr_ResourceWarning(PyObject * source,Py_ssize_t stack_level,const char * format,...)1131 PyErr_ResourceWarning(PyObject *source, Py_ssize_t stack_level,
1132                       const char *format, ...)
1133 {
1134     int res;
1135     va_list vargs;
1136 
1137 #ifdef HAVE_STDARG_PROTOTYPES
1138     va_start(vargs, format);
1139 #else
1140     va_start(vargs);
1141 #endif
1142     res = _PyErr_WarnFormatV(source, PyExc_ResourceWarning,
1143                              stack_level, format, vargs);
1144     va_end(vargs);
1145     return res;
1146 }
1147 
1148 
1149 int
PyErr_WarnEx(PyObject * category,const char * text,Py_ssize_t stack_level)1150 PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
1151 {
1152     int ret;
1153     PyObject *message = PyUnicode_FromString(text);
1154     if (message == NULL)
1155         return -1;
1156     ret = warn_unicode(category, message, stack_level, NULL);
1157     Py_DECREF(message);
1158     return ret;
1159 }
1160 
1161 /* PyErr_Warn is only for backwards compatibility and will be removed.
1162    Use PyErr_WarnEx instead. */
1163 
1164 #undef PyErr_Warn
1165 
1166 int
PyErr_Warn(PyObject * category,const char * text)1167 PyErr_Warn(PyObject *category, const char *text)
1168 {
1169     return PyErr_WarnEx(category, text, 1);
1170 }
1171 
1172 /* Warning with explicit origin */
1173 int
PyErr_WarnExplicitObject(PyObject * category,PyObject * message,PyObject * filename,int lineno,PyObject * module,PyObject * registry)1174 PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
1175                          PyObject *filename, int lineno,
1176                          PyObject *module, PyObject *registry)
1177 {
1178     PyObject *res;
1179     if (category == NULL)
1180         category = PyExc_RuntimeWarning;
1181     res = warn_explicit(category, message, filename, lineno,
1182                         module, registry, NULL, NULL);
1183     if (res == NULL)
1184         return -1;
1185     Py_DECREF(res);
1186     return 0;
1187 }
1188 
1189 int
PyErr_WarnExplicit(PyObject * category,const char * text,const char * filename_str,int lineno,const char * module_str,PyObject * registry)1190 PyErr_WarnExplicit(PyObject *category, const char *text,
1191                    const char *filename_str, int lineno,
1192                    const char *module_str, PyObject *registry)
1193 {
1194     PyObject *message = PyUnicode_FromString(text);
1195     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1196     PyObject *module = NULL;
1197     int ret = -1;
1198 
1199     if (message == NULL || filename == NULL)
1200         goto exit;
1201     if (module_str != NULL) {
1202         module = PyUnicode_FromString(module_str);
1203         if (module == NULL)
1204             goto exit;
1205     }
1206 
1207     ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
1208                                    module, registry);
1209 
1210  exit:
1211     Py_XDECREF(message);
1212     Py_XDECREF(module);
1213     Py_XDECREF(filename);
1214     return ret;
1215 }
1216 
1217 int
PyErr_WarnExplicitFormat(PyObject * category,const char * filename_str,int lineno,const char * module_str,PyObject * registry,const char * format,...)1218 PyErr_WarnExplicitFormat(PyObject *category,
1219                          const char *filename_str, int lineno,
1220                          const char *module_str, PyObject *registry,
1221                          const char *format, ...)
1222 {
1223     PyObject *message;
1224     PyObject *module = NULL;
1225     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
1226     int ret = -1;
1227     va_list vargs;
1228 
1229     if (filename == NULL)
1230         goto exit;
1231     if (module_str != NULL) {
1232         module = PyUnicode_FromString(module_str);
1233         if (module == NULL)
1234             goto exit;
1235     }
1236 
1237 #ifdef HAVE_STDARG_PROTOTYPES
1238     va_start(vargs, format);
1239 #else
1240     va_start(vargs);
1241 #endif
1242     message = PyUnicode_FromFormatV(format, vargs);
1243     if (message != NULL) {
1244         PyObject *res;
1245         res = warn_explicit(category, message, filename, lineno,
1246                             module, registry, NULL, NULL);
1247         Py_DECREF(message);
1248         if (res != NULL) {
1249             Py_DECREF(res);
1250             ret = 0;
1251         }
1252     }
1253     va_end(vargs);
1254 exit:
1255     Py_XDECREF(module);
1256     Py_XDECREF(filename);
1257     return ret;
1258 }
1259 
1260 void
_PyErr_WarnUnawaitedCoroutine(PyObject * coro)1261 _PyErr_WarnUnawaitedCoroutine(PyObject *coro)
1262 {
1263     /* First, we attempt to funnel the warning through
1264        warnings._warn_unawaited_coroutine.
1265 
1266        This could raise an exception, due to:
1267        - a bug
1268        - some kind of shutdown-related brokenness
1269        - succeeding, but with an "error" warning filter installed, so the
1270          warning is converted into a RuntimeWarning exception
1271 
1272        In the first two cases, we want to print the error (so we know what it
1273        is!), and then print a warning directly as a fallback. In the last
1274        case, we want to print the error (since it's the warning!), but *not*
1275        do a fallback. And after we print the error we can't check for what
1276        type of error it was (because PyErr_WriteUnraisable clears it), so we
1277        need a flag to keep track.
1278 
1279        Since this is called from __del__ context, it's careful to never raise
1280        an exception.
1281     */
1282     _Py_IDENTIFIER(_warn_unawaited_coroutine);
1283     int warned = 0;
1284     PyObject *fn = get_warnings_attr(&PyId__warn_unawaited_coroutine, 1);
1285     if (fn) {
1286         PyObject *res = PyObject_CallFunctionObjArgs(fn, coro, NULL);
1287         Py_DECREF(fn);
1288         if (res || PyErr_ExceptionMatches(PyExc_RuntimeWarning)) {
1289             warned = 1;
1290         }
1291         Py_XDECREF(res);
1292     }
1293 
1294     if (PyErr_Occurred()) {
1295         PyErr_WriteUnraisable(coro);
1296     }
1297     if (!warned) {
1298         if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
1299                              "coroutine '%.50S' was never awaited",
1300                              ((PyCoroObject *)coro)->cr_qualname) < 0)
1301         {
1302             PyErr_WriteUnraisable(coro);
1303         }
1304     }
1305 }
1306 
1307 PyDoc_STRVAR(warn_explicit_doc,
1308 "Low-level interface to warnings functionality.");
1309 
1310 static PyMethodDef warnings_functions[] = {
1311     WARNINGS_WARN_METHODDEF
1312     {"warn_explicit", (PyCFunction)(void(*)(void))warnings_warn_explicit,
1313         METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
1314     {"_filters_mutated", (PyCFunction)warnings_filters_mutated, METH_NOARGS,
1315         NULL},
1316     /* XXX(brett.cannon): add showwarning? */
1317     /* XXX(brett.cannon): Reasonable to add formatwarning? */
1318     {NULL, NULL}                /* sentinel */
1319 };
1320 
1321 
1322 static struct PyModuleDef warningsmodule = {
1323         PyModuleDef_HEAD_INIT,
1324         MODULE_NAME,            /* m_name */
1325         warnings__doc__,        /* m_doc */
1326         0,                      /* m_size */
1327         warnings_functions,     /* m_methods */
1328         NULL,                   /* m_reload */
1329         NULL,                   /* m_traverse */
1330         NULL,                   /* m_clear */
1331         NULL                    /* m_free */
1332 };
1333 
1334 
1335 PyMODINIT_FUNC
_PyWarnings_Init(void)1336 _PyWarnings_Init(void)
1337 {
1338     PyObject *m;
1339 
1340     m = PyModule_Create(&warningsmodule);
1341     if (m == NULL) {
1342         return NULL;
1343     }
1344 
1345     WarningsState *st = _Warnings_GetState();
1346     if (st == NULL) {
1347         goto error;
1348     }
1349     if (_Warnings_InitState(st) < 0) {
1350         goto error;
1351     }
1352 
1353     Py_INCREF(st->filters);
1354     if (PyModule_AddObject(m, "filters", st->filters) < 0) {
1355         goto error;
1356     }
1357 
1358     Py_INCREF(st->once_registry);
1359     if (PyModule_AddObject(m, "_onceregistry", st->once_registry) < 0) {
1360         goto error;
1361     }
1362 
1363     Py_INCREF(st->default_action);
1364     if (PyModule_AddObject(m, "_defaultaction", st->default_action) < 0) {
1365         goto error;
1366     }
1367 
1368     return m;
1369 
1370 error:
1371     if (st != NULL) {
1372         _Warnings_ClearState(st);
1373     }
1374     Py_DECREF(m);
1375     return NULL;
1376 }
1377 
1378 // We need this to ensure that warnings still work until late in finalization.
1379 void
_PyWarnings_Fini(PyInterpreterState * interp)1380 _PyWarnings_Fini(PyInterpreterState *interp)
1381 {
1382     _Warnings_ClearState(&interp->warnings);
1383 }
1384