-
-
Notifications
You must be signed in to change notification settings - Fork 209
Closed
Description
Hi, I identified an instance of undefined behavior due to an unaligned access in the C implementation, in the parse_row_binary() function. I've captured a backtrace from the unit test on a platform that does not permit unaligned access, and then ran the same test with UBSAN to demonstrate that the issue is present and invokes undefined behavior on all platforms. I believe this is the code at fault:
https://github.com/psycopg/psycopg/blob/3.1.17/psycopg_c/psycopg_c/_psycopg/copy.pyx#L194-L195
Complete test run: https://924180.bugs.gentoo.org/attachment.cgi?id=884637
Relevant backtrace:
(gdb) bt full 9
#0 0xfff8000100d9249c in ?? () from /lib64/libc.so.6
No symbol table info available.
#1 0xfff8000100d42eb4 in raise () from /lib64/libc.so.6
No symbol table info available.
#2 0xfff8000100780224 in faulthandler_fatal_error (signum=10) at ./Modules/faulthandler.c:384
fd = 9
i = 0
handler = 0xfff8000100b2d2b0 <faulthandler_handlers>
save_errno = 0
found = 1
#3 <signal handler called>
No symbol table info available.
#4 __pyx_pf_9psycopg_c_8_psycopg_4parse_row_binary (__pyx_self=<_cython_3_0_8.cython_function_or_method at remote 0xfff8000107d806c0>,
__pyx_v_data=<memoryview at remote 0xfff800010a84ea40>, __pyx_v_tx=0xfff800010a84df00) at psycopg_c/_psycopg.c:19288
__pyx_v_ptr = 0x1000091e6c3 ""
__pyx_v_bufsize = 67
__pyx_v_bufend = 0x1000091e706 ""
__pyx_v_benfields = 24920
__pyx_v_nfields = -524287
__pyx_v_row = 0x0
__pyx_v_col = -524287
__pyx_v_belength = -524287
__pyx_v_length = 1099519657312
__pyx_v_field = 0x0
__pyx_r = 0x0
__pyx_t_1 = 0
__pyx_t_2 = 0x0
__pyx_t_3 = 169188592
__pyx_t_4 = 176482864
__pyx_t_5 = 11692416
__pyx_t_6 = 0x0
__pyx_t_7 = 0x0
__pyx_t_8 = -524287
__pyx_lineno = 0
__pyx_filename = 0x0
__pyx_clineno = 0
#5 0xfff800010a3196a4 in __pyx_pw_9psycopg_c_8_psycopg_5parse_row_binary (__pyx_self=<_cython_3_0_8.cython_function_or_method at remote 0xfff8000107d806c0>, __pyx_args=0xfff800010009fa90,
__pyx_nargs=2, __pyx_kwds=0x0) at psycopg_c/_psycopg.c:19220
__pyx_v_data = <memoryview at remote 0xfff800010a84ea40>
__pyx_v_tx = 0xfff800010a84df00
__pyx_kwvalues = 0xfff800010009faa0
values = {<memoryview at remote 0xfff800010a84ea40>, <psycopg_c._psycopg.Transformer at remote 0xfff800010a84df00>}
__pyx_lineno = 0
__pyx_filename = 0x0
__pyx_clineno = 0
__pyx_r = 0x0
#6 0xfff800010a427d0c in __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS (func=<_cython_3_0_8.cython_function_or_method at remote 0xfff8000107d806c0>, args=0xfff800010009fa90,
nargsf=9223372036854775810, kwnames=0x0) at psycopg_c/_psycopg.c:95554
cyfunc = 0xfff8000107d806c0
def = 0xfff800010a601f90 <__pyx_mdef_9psycopg_c_8_psycopg_5parse_row_binary>
nargs = 2
self = <_cython_3_0_8.cython_function_or_method at remote 0xfff8000107d806c0>
#7 0xfff80001004a2538 in _PyObject_VectorcallTstate (tstate=0xfff8000100c2e568 <_PyRuntime+166328>, callable=<_cython_3_0_8.cython_function_or_method at remote 0xfff8000107d806c0>,
args=0xfff800010009fa90, nargsf=9223372036854775810, kwnames=0x0) at ./Include/internal/pycore_call.h:92
func = 0xfff800010a427c38 <__Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS>
res = <dict_keys at remote 0xfff8000100b00000>
__PRETTY_FUNCTION__ = "_PyObject_VectorcallTstate"
#8 0xfff80001004a3818 in PyObject_Vectorcall (callable=<_cython_3_0_8.cython_function_or_method at remote 0xfff8000107d806c0>, args=0xfff800010009fa90, nargsf=9223372036854775810,
kwnames=0x0) at Objects/call.c:299
tstate = 0xfff8000100c2e568 <_PyRuntime+166328>
(More stack frames follow...)
UBSAN run of the relevant test:
$ UBSAN_OPTIONS=halt_on_error=1 PSYCOPG_TEST_DSN="host=$(realpath ../..) dbname=test" PYTHONPATH=../psycopg-3.1.17-python3_11/install/usr/lib/python3.11/site-packages/ PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 PSYCOPG_IMPL=c /usr/bin/python3.11 -m pytest -vv -ra -l -Wdefault --color=yes -o console_output_style=count -o tmp_path_retention_count=0 -o tmp_path_retention_policy=failed -p anyio tests/test_copy_async.py::test_read_rows -s
===================================================================================== test session starts ======================================================================================
platform linux -- Python 3.11.7, pytest-7.4.4, pluggy-1.3.0 -- /usr/bin/python3.11
cachedir: .pytest_cache
default selector: EpollSelector
Server version: PostgreSQL 16.2 on powerpc64le-unknown-linux-gnu, compiled by powerpc64le-unknown-linux-gnu-gcc (Gentoo 13.2.1_p20240113-r1 p12) 13.2.1 20240113, 64-bit
libpq wrapper implementation: c
libpq used: 160002
libpq compiled: 160002
rootdir: /var/tmp/portage/dev-python/psycopg-3.1.17/work/psycopg-3.1.17
configfile: pyproject.toml
plugins: anyio-4.2.0
collected 4 items
tests/test_copy_async.py::test_read_rows[asyncio-names-0] PASSED
tests/test_copy_async.py::test_read_rows[asyncio-names-1] psycopg_c/_psycopg.c:19287:21: runtime error: load of misaligned address 0x000144ecf413 for type 'uint16_t', which requires 2 byte alignment
0x000144ecf413: note: pointer points here
00 00 00 00 00 03 00 00 00 04 00 00 00 0a 00 00 00 05 68 65 6c 6c 6f 00 00 00 2c 00 00 00 01 00
^
2024-02-09 22:05:25.696 GMT [16183] LOG: unexpected EOF on client connection with an open transaction
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels