Python: fixing incorrect function object dereference.

The __call__ method can be native and not be a PyFunction type.  A type check
is thus required before accessing op_code and other fields.

Reproduced on Ubuntu 21.04, Python 3.9.4 and Falcon framework: here, the
App.__call__ method is compiled with Cython, so accessing op_code->co_flags is
invalid; accidentally, the COROUTINE bit is set which forces the Python module
into the ASGI mode.

The workaround is explicit protocol specification.

Note: it is impossible to specify the legacy mode for ASGI.
This commit is contained in:
Max Romanov
2022-02-08 12:04:41 +03:00
parent e53ce40c58
commit 2b5941df74
2 changed files with 19 additions and 6 deletions

View File

@@ -43,6 +43,13 @@ some Spring Boot applications failed to start, notably with Grails.
</para>
</change>
<change type="bugfix">
<para>
incorrect Python protocol auto detection (ASGI or WSGI) for native callable
object, notably with Falcon.
</para>
</change>
</changes>

View File

@@ -117,15 +117,20 @@ nxt_python_asgi_get_func(PyObject *obj)
if (PyMethod_Check(call)) {
obj = PyMethod_GET_FUNCTION(call);
Py_INCREF(obj);
Py_DECREF(call);
if (PyFunction_Check(obj)) {
Py_INCREF(obj);
return obj;
} else {
obj = NULL;
}
} else {
obj = NULL;
}
Py_DECREF(call);
return NULL;
return obj;
}
@@ -161,8 +166,9 @@ nxt_python_asgi_init(nxt_unit_init_t *init, nxt_python_proto_t *proto)
for (i = 0; i < nxt_py_targets->count; i++) {
func = nxt_python_asgi_get_func(nxt_py_targets->target[i].application);
if (nxt_slow_path(func == NULL)) {
nxt_unit_alert(NULL, "Python cannot find function for callable");
return NXT_UNIT_ERROR;
nxt_unit_debug(NULL, "asgi: cannot find function for callable, "
"unable to check for legacy mode (#%d)", i);
continue;
}
code = (PyCodeObject *) PyFunction_GET_CODE(func);