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