]> granicus.if.org Git - python/commitdiff
Fixed possible abort in ceval loop if _PyUnicode_FromId() fails.
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 8 Nov 2016 21:13:36 +0000 (23:13 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Tue, 8 Nov 2016 21:13:36 +0000 (23:13 +0200)
Every opcode should end with DISPATCH() or goto error.

1  2 
Python/ceval.c

diff --cc Python/ceval.c
index 0add7ecc09383506359c0b3d72836b405a1f6155,7b405188d38c662696fcd1638bac05767a8b698f..b2c90cc3b48d4313064df7808113a92f32dfb2fa
@@@ -2621,162 -2641,87 +2621,162 @@@ _PyEval_EvalFrameDefault(PyFrameObject 
              DISPATCH();
          }
  
 -        TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack)
 -        TARGET(BUILD_MAP_UNPACK)
 -        _build_map_unpack: {
 -            int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL;
 -            int num_maps;
 -            int i;
 -            PyObject *sum = PyDict_New();
 -            if (sum == NULL)
 +        TARGET(SETUP_ANNOTATIONS) {
 +            _Py_IDENTIFIER(__annotations__);
 +            int err;
 +            PyObject *ann_dict;
 +            if (f->f_locals == NULL) {
 +                PyErr_Format(PyExc_SystemError,
 +                             "no locals found when setting up annotations");
                  goto error;
 -            if (with_call) {
 -                num_maps = oparg & 0xff;
              }
 -            else {
 -                num_maps = oparg;
 +            /* check if __annotations__ in locals()... */
 +            if (PyDict_CheckExact(f->f_locals)) {
 +                ann_dict = _PyDict_GetItemId(f->f_locals,
 +                                             &PyId___annotations__);
 +                if (ann_dict == NULL) {
 +                    /* ...if not, create a new one */
 +                    ann_dict = PyDict_New();
 +                    if (ann_dict == NULL) {
 +                        goto error;
 +                    }
 +                    err = _PyDict_SetItemId(f->f_locals,
 +                                            &PyId___annotations__, ann_dict);
 +                    Py_DECREF(ann_dict);
 +                    if (err != 0) {
 +                        goto error;
 +                    }
 +                }
              }
 -
 -            for (i = num_maps; i > 0; i--) {
 -                PyObject *arg = PEEK(i);
 -                if (with_call) {
 -                    PyObject *intersection = _PyDictView_Intersect(sum, arg);
 -
 -                    if (intersection == NULL) {
 -                        if (PyErr_ExceptionMatches(PyExc_AttributeError) ||
 -                            !PyMapping_Check(arg)) {
 -                            int function_location = (oparg>>8) & 0xff;
 -                            PyObject *func = (
 -                                    PEEK(function_location + num_maps));
 -                            PyErr_Format(PyExc_TypeError,
 -                                    "%.200s%.200s argument after ** "
 -                                    "must be a mapping, not %.200s",
 -                                    PyEval_GetFuncName(func),
 -                                    PyEval_GetFuncDesc(func),
 -                                    arg->ob_type->tp_name);
 -                        }
 -                        Py_DECREF(sum);
 +            else {
 +                /* do the same if locals() is not a dict */
 +                PyObject *ann_str = _PyUnicode_FromId(&PyId___annotations__);
 +                if (ann_str == NULL) {
-                     break;
++                    goto error;
 +                }
 +                ann_dict = PyObject_GetItem(f->f_locals, ann_str);
 +                if (ann_dict == NULL) {
 +                    if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
                          goto error;
                      }
 -
 -                    if (PySet_GET_SIZE(intersection)) {
 -                        Py_ssize_t idx = 0;
 -                        PyObject *key;
 -                        int function_location = (oparg>>8) & 0xff;
 -                        PyObject *func = PEEK(function_location + num_maps);
 -                        Py_hash_t hash;
 -                        _PySet_NextEntry(intersection, &idx, &key, &hash);
 -                        if (!PyUnicode_Check(key)) {
 -                            PyErr_Format(PyExc_TypeError,
 -                                    "%.200s%.200s keywords must be strings",
 -                                    PyEval_GetFuncName(func),
 -                                    PyEval_GetFuncDesc(func));
 -                        } else {
 -                            PyErr_Format(PyExc_TypeError,
 -                                    "%.200s%.200s got multiple "
 -                                    "values for keyword argument '%U'",
 -                                    PyEval_GetFuncName(func),
 -                                    PyEval_GetFuncDesc(func),
 -                                    key);
 -                        }
 -                        Py_DECREF(intersection);
 -                        Py_DECREF(sum);
 +                    PyErr_Clear();
 +                    ann_dict = PyDict_New();
 +                    if (ann_dict == NULL) {
 +                        goto error;
 +                    }
 +                    err = PyObject_SetItem(f->f_locals, ann_str, ann_dict);
 +                    Py_DECREF(ann_dict);
 +                    if (err != 0) {
                          goto error;
                      }
 -                    Py_DECREF(intersection);
                  }
 +                else {
 +                    Py_DECREF(ann_dict);
 +                }
 +            }
 +            DISPATCH();
 +        }
 +
 +        TARGET(BUILD_CONST_KEY_MAP) {
 +            Py_ssize_t i;
 +            PyObject *map;
 +            PyObject *keys = TOP();
 +            if (!PyTuple_CheckExact(keys) ||
 +                PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
 +                PyErr_SetString(PyExc_SystemError,
 +                                "bad BUILD_CONST_KEY_MAP keys argument");
 +                goto error;
 +            }
 +            map = _PyDict_NewPresized((Py_ssize_t)oparg);
 +            if (map == NULL) {
 +                goto error;
 +            }
 +            for (i = oparg; i > 0; i--) {
 +                int err;
 +                PyObject *key = PyTuple_GET_ITEM(keys, oparg - i);
 +                PyObject *value = PEEK(i + 1);
 +                err = PyDict_SetItem(map, key, value);
 +                if (err != 0) {
 +                    Py_DECREF(map);
 +                    goto error;
 +                }
 +            }
 +
 +            Py_DECREF(POP());
 +            while (oparg--) {
 +                Py_DECREF(POP());
 +            }
 +            PUSH(map);
 +            DISPATCH();
 +        }
 +
 +        TARGET(BUILD_MAP_UNPACK) {
 +            Py_ssize_t i;
 +            PyObject *sum = PyDict_New();
 +            if (sum == NULL)
 +                goto error;
  
 +            for (i = oparg; i > 0; i--) {
 +                PyObject *arg = PEEK(i);
                  if (PyDict_Update(sum, arg) < 0) {
                      if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
 -                        if (with_call) {
 -                            int function_location = (oparg>>8) & 0xff;
 -                            PyObject *func = PEEK(function_location + num_maps);
 -                            PyErr_Format(PyExc_TypeError,
 -                                    "%.200s%.200s argument after ** "
 -                                    "must be a mapping, not %.200s",
 -                                    PyEval_GetFuncName(func),
 -                                    PyEval_GetFuncDesc(func),
 -                                    arg->ob_type->tp_name);
 +                        PyErr_Format(PyExc_TypeError,
 +                                "'%.200s' object is not a mapping",
 +                                arg->ob_type->tp_name);
 +                    }
 +                    Py_DECREF(sum);
 +                    goto error;
 +                }
 +            }
 +
 +            while (oparg--)
 +                Py_DECREF(POP());
 +            PUSH(sum);
 +            DISPATCH();
 +        }
 +
 +        TARGET(BUILD_MAP_UNPACK_WITH_CALL) {
 +            Py_ssize_t i;
 +            PyObject *sum = PyDict_New();
 +            if (sum == NULL)
 +                goto error;
 +
 +            for (i = oparg; i > 0; i--) {
 +                PyObject *arg = PEEK(i);
 +                if (_PyDict_MergeEx(sum, arg, 2) < 0) {
 +                    PyObject *func = PEEK(2 + oparg);
 +                    if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
 +                        PyErr_Format(PyExc_TypeError,
 +                                "%.200s%.200s argument after ** "
 +                                "must be a mapping, not %.200s",
 +                                PyEval_GetFuncName(func),
 +                                PyEval_GetFuncDesc(func),
 +                                arg->ob_type->tp_name);
 +                    }
 +                    else if (PyErr_ExceptionMatches(PyExc_KeyError)) {
 +                        PyObject *exc, *val, *tb;
 +                        PyErr_Fetch(&exc, &val, &tb);
 +                        if (val && PyTuple_Check(val) && PyTuple_GET_SIZE(val) == 1) {
 +                            PyObject *key = PyTuple_GET_ITEM(val, 0);
 +                            if (!PyUnicode_Check(key)) {
 +                                PyErr_Format(PyExc_TypeError,
 +                                        "%.200s%.200s keywords must be strings",
 +                                        PyEval_GetFuncName(func),
 +                                        PyEval_GetFuncDesc(func));
 +                            } else {
 +                                PyErr_Format(PyExc_TypeError,
 +                                        "%.200s%.200s got multiple "
 +                                        "values for keyword argument '%U'",
 +                                        PyEval_GetFuncName(func),
 +                                        PyEval_GetFuncDesc(func),
 +                                        key);
 +                            }
 +                            Py_XDECREF(exc);
 +                            Py_XDECREF(val);
 +                            Py_XDECREF(tb);
                          }
                          else {
 -                            PyErr_Format(PyExc_TypeError,
 -                                    "'%.200s' object is not a mapping",
 -                                    arg->ob_type->tp_name);
 +                            PyErr_Restore(exc, val, tb);
                          }
                      }
                      Py_DECREF(sum);