Mercurial > hgrepos > FreeBSD > ports > www > uwsginl
changeset 85:56fc86d83f6f
python: use consistent key type for opt dict manipulations - fixes #1374.
PyString_FromString is defined as PyBytes_FromString in uwsgi_python.h.
What happens in Python 3 during the population of the opt_dict is that
we first check if a byte object, representing the key is in the dict.
If there is none, we use PyDict_SetItemString to set it. However, as
the docs say, PyDict_SetItemString will convert the key using
PyUnicode_FromString and we actually put a unicode key in the dict[1].
Therefore, when we check the "same" key again, we check again for the
"same" key as bytes object we don't find it and end up overwriting it
instead of doing the list promotion dance.
Attached patch fixes this by using PyDict_SetItem and PyDict_GetItem with
a consistent key type. For Python 3, a unicode object is used as key as
this is the backwards compatible thing to do.
Mini tester:
import uwsgi
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
for k, v in uwsgi.opt.items():
yield "{} {!r} ({})\n".format(k, v, type(v)).encode("utf-8")
yield "{} {}\n".format(uwsgi.version, type(uwsgi.version)).encode("utf-8")
yield "{} {}\n".format(uwsgi.hostname, type(uwsgi.hostname)).encode("utf-8")
yield b"END"
What is a bit rough is that in Python 3 the actual values for uwsgi.opt
entries end-up being all bytes, but that has always been like this...
[1] https://docs.python.org/3.5/c-api/dict.html#c.PyDict_SetItemString
commit 34cc53d0899f874ea1dc1d13d49c054ca1f1757c
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sun, 14 Jun 2020 23:20:32 +0200 |
| parents | 67e3c22ae581 |
| children | 419d764a16b8 |
| files | uwsginl/files/patch-plugins_python_python__plugin.c |
| diffstat | 1 files changed, 37 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uwsginl/files/patch-plugins_python_python__plugin.c Sun Jun 14 23:20:32 2020 +0200 @@ -0,0 +1,37 @@ +--- plugins/python/python_plugin.c.orig 2020-06-14 21:13:51 UTC ++++ plugins/python/python_plugin.c +@@ -779,8 +779,13 @@ void init_uwsgi_embedded_module() { + + PyObject *py_opt_dict = PyDict_New(); + for (i = 0; i < uwsgi.exported_opts_cnt; i++) { +- if (PyDict_Contains(py_opt_dict, PyString_FromString(uwsgi.exported_opts[i]->key))) { +- PyObject *py_opt_item = PyDict_GetItemString(py_opt_dict, uwsgi.exported_opts[i]->key); ++#ifdef PYTHREE ++ PyObject *key = PyUnicode_FromString(uwsgi.exported_opts[i]->key); ++#else ++ PyObject *key = PyString_FromString(uwsgi.exported_opts[i]->key); ++#endif ++ if (PyDict_Contains(py_opt_dict, key)) { ++ PyObject *py_opt_item = PyDict_GetItem(py_opt_dict, key); + if (PyList_Check(py_opt_item)) { + if (uwsgi.exported_opts[i]->value == NULL) { + PyList_Append(py_opt_item, Py_True); +@@ -799,15 +804,15 @@ void init_uwsgi_embedded_module() { + PyList_Append(py_opt_list, PyString_FromString(uwsgi.exported_opts[i]->value)); + } + +- PyDict_SetItemString(py_opt_dict, uwsgi.exported_opts[i]->key, py_opt_list); ++ PyDict_SetItem(py_opt_dict, key, py_opt_list); + } + } + else { + if (uwsgi.exported_opts[i]->value == NULL) { +- PyDict_SetItemString(py_opt_dict, uwsgi.exported_opts[i]->key, Py_True); ++ PyDict_SetItem(py_opt_dict, key, Py_True); + } + else { +- PyDict_SetItemString(py_opt_dict, uwsgi.exported_opts[i]->key, PyString_FromString(uwsgi.exported_opts[i]->value)); ++ PyDict_SetItem(py_opt_dict, key, PyString_FromString(uwsgi.exported_opts[i]->value)); + } + } + }
