summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrew Clayton <a.clayton@nginx.com>2023-05-15 22:48:31 +0100
committerAndrew Clayton <a.clayton@nginx.com>2023-05-18 15:57:11 +0100
commit47683c4704572bbe0efb3b989b35a3912b65ac83 (patch)
treee52c8cd0e1ca8795a8856a19bd2df23f3350528b
parentaa45d17dc610387e6e4f550626005d209fe0a6a0 (diff)
downloadunit-47683c4704572bbe0efb3b989b35a3912b65ac83.tar.gz
unit-47683c4704572bbe0efb3b989b35a3912b65ac83.tar.bz2
Python: Fix ASGI applications accessed over IPv6.
There are a couple of reports on GitHub about issues accessing Python ASGI based applications over IPv6. A request over IPv6 would result in an error like 2023/05/13 17:49:12 [alert] 47202#47202 [unit] #10: Python failed to create 'client' pair 2023/05/13 17:49:12 [alert] 47202#47202 [unit] Python failed to call 'loop.call_soon' ValueError: invalid literal for int() with base 10: 'db8:1:1:1ee7:dead:beef:cafe' The above error was the direct cause of the following exception: Traceback (most recent call last): File "/usr/lib64/python3.11/asyncio/base_events.py", line 765, in call_soon handle = self._call_soon(callback, args, context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib64/python3.11/asyncio/base_events.py", line 781, in _call_soon handle = events.Handle(callback, args, self, context) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SystemError: <class 'asyncio.events.Handle'> returned a result with an exception set This issue occurred in the nxt_py_asgi_create_ip_address() function where it tries to create an IP address / port number pair. It does this by looking for the first ':' in the address and taking everything after it as the port number. Like in the above error message, if we tried to access the server @ 2001:db8:1:1:1ee7:dead:beef:cafe, then we'd end up with the port number as 'db8:1:1:1ee7:dead:beef:cafe'. There are two issues with this 1) The IP address and port number are already flowed through separately. 2) Even if (1) wasn't true, it would still be broken for IPv6 as we'd expect to a get an address literal like [2001:db8:1:1:1ee7:dead:beef:cafe]:8080, however there was no code to handle the []'s. The fix is to simply not try looking for a port number. We pass a port number into this function to use in the case where we don't find a port number, we never will... A further cleanup would be to flow through the server port number when creating the 'server pair' PyTuple, rather than just using the hard coded 80. Closes: <https://github.com/nginx/unit/issues/793> Closes: <https://github.com/nginx/unit/issues/874> Reviewed-by: Alejandro Colomar <alx@nginx.com> Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
-rw-r--r--src/python/nxt_python_asgi.c14
1 files changed, 3 insertions, 11 deletions
diff --git a/src/python/nxt_python_asgi.c b/src/python/nxt_python_asgi.c
index adf03e2b..9f6cde3b 100644
--- a/src/python/nxt_python_asgi.c
+++ b/src/python/nxt_python_asgi.c
@@ -828,7 +828,7 @@ nxt_py_asgi_create_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
static PyObject *
nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
{
- char *p, *s;
+ char *p;
PyObject *pair, *v;
pair = PyTuple_New(2);
@@ -837,9 +837,8 @@ nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
}
p = nxt_unit_sptr_get(sptr);
- s = memchr(p, ':', len);
- v = PyString_FromStringAndSize(p, s == NULL ? len : s - p);
+ v = PyString_FromStringAndSize(p, len);
if (nxt_slow_path(v == NULL)) {
Py_DECREF(pair);
@@ -848,14 +847,7 @@ nxt_py_asgi_create_ip_address(nxt_unit_sptr_t *sptr, uint8_t len, uint16_t port)
PyTuple_SET_ITEM(pair, 0, v);
- if (s != NULL) {
- p += len;
- v = PyLong_FromString(s + 1, &p, 10);
-
- } else {
- v = PyLong_FromLong(port);
- }
-
+ v = PyLong_FromLong(port);
if (nxt_slow_path(v == NULL)) {
Py_DECREF(pair);