π€ AI: Split out of #3884 at pljones's request β this is the crasher of the three off-by-one range checks reported there.
The client reads customdirectoryindex from the ini with an inclusive upper bound of MAX_NUM_SERVER_ADDR_ITEMS, then uses it as a subscript into a vector of exactly that many elements, so the accepted value one past the end crashes the client at startup.
src/settings.cpp:786 accepts 0..MAX_NUM_SERVER_ADDR_ITEMS, and GetNumericIniSet's upper bound is inclusive (src/settings.cpp:144). MAX_NUM_SERVER_ADDR_ITEMS is 12 (src/global.h:218) and vstrDirectoryAddress holds 12 elements (src/settings.h:178), so 12 is accepted and 12 is out of range. Two call sites subscript with it unguarded: src/connectdlg.cpp:320 and src/clientrpc.cpp:211.
Both keys are needed to reach it: the index is only read when directorytype is 7 (AT_CUSTOM), and winviscon=1 opens the connect dialog at startup. Measured with QT_QPA_PLATFORM=offscreen, Qt 5.15.3, on main @ 8b667a3a; line numbers re-verified unchanged against origin/main @ 11a28d57e33506fc84cb9b5ee02097931c1e35a3 on 2026-08-21.
customdirectoryindex |
result |
connect dialog drawn |
| 11 |
runs normally |
yes |
| 12 |
SIGSEGV, exit 139 |
no |
Under valgrind the 12 arm reports, and the 11 arm reports no invalid access at all:
Invalid read of size 8
at NetworkUtil::GetDirectoryAddress(EDirectoryType, QString const&)
by CConnectDlg::RequestServerList()
by QWidget::event(QEvent*)
Invalid read of size 4
(same two frames)
The client's own writer only ever emits 0..11 (src/settings.cpp:1006), so reaching this needs a hand-edited or corrupted ini rather than ordinary use. The range check exists to make that safe, and it is off by one.
Fix: GetNumericIniSet ( ..., 0, MAX_NUM_SERVER_ADDR_ITEMS - 1, iValue ). Rebuilt with only that change, same rig, both arms:
customdirectoryindex |
unpatched |
with - 1 |
| 11 |
runs, dialog drawn |
runs, dialog drawn |
| 12 |
SIGSEGV |
runs, dialog drawn |
π€ This message was written by AI and reviewed by @mcfnord.
π€ AI: Split out of #3884 at pljones's request β this is the crasher of the three off-by-one range checks reported there.
The client reads
customdirectoryindexfrom the ini with an inclusive upper bound ofMAX_NUM_SERVER_ADDR_ITEMS, then uses it as a subscript into a vector of exactly that many elements, so the accepted value one past the end crashes the client at startup.src/settings.cpp:786accepts0..MAX_NUM_SERVER_ADDR_ITEMS, andGetNumericIniSet's upper bound is inclusive (src/settings.cpp:144).MAX_NUM_SERVER_ADDR_ITEMSis 12 (src/global.h:218) andvstrDirectoryAddressholds 12 elements (src/settings.h:178), so 12 is accepted and 12 is out of range. Two call sites subscript with it unguarded:src/connectdlg.cpp:320andsrc/clientrpc.cpp:211.Both keys are needed to reach it: the index is only read when
directorytypeis 7 (AT_CUSTOM), andwinviscon=1opens the connect dialog at startup. Measured withQT_QPA_PLATFORM=offscreen, Qt 5.15.3, onmain@8b667a3a; line numbers re-verified unchanged againstorigin/main@11a28d57e33506fc84cb9b5ee02097931c1e35a3on 2026-08-21.customdirectoryindexUnder valgrind the 12 arm reports, and the 11 arm reports no invalid access at all:
The client's own writer only ever emits
0..11(src/settings.cpp:1006), so reaching this needs a hand-edited or corrupted ini rather than ordinary use. The range check exists to make that safe, and it is off by one.Fix:
GetNumericIniSet ( ..., 0, MAX_NUM_SERVER_ADDR_ITEMS - 1, iValue ). Rebuilt with only that change, same rig, both arms:customdirectoryindex- 1π€ This message was written by AI and reviewed by @mcfnord.