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