Description
The engine crashes with SIGABRT due to a libstdc++ hardening assertion failure (__glibcxx_assert_fail) inside CQuadField::GetQuadsOnRay. A laser beam's length calculation yields an inverted negative distance value, which violates the downstream std::clamp invariant (lo <= hi).
Environment
- OS: Linux (Arch Linux / CachyOS package build)
- Engine Build:
recoil-engine-rc (systemwide_managed_by_pkgmngr-2026.06.08-RC.local) (build from the AUR PKGBUILD (full build instructions used are below)
- Game: Beyond All Reason
- Toolchain State: Built with GCC runtime assertions enabled (
-D_GLIBCXX_ASSERTIONS)
Build Instructions used
cmake3 -S "${srcdir}/${pkgname%-git}" -G Ninja \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O3 -g -DNDEBUG -fdiagnostics-color=always" \
-DCMAKE_C_FLAGS_RELWITHDEBINFO="-O3 -g -DNDEBUG -fdiagnostics-color=always" \
-DCMAKE_BUILD_TYPE=RELWITHDEBINFO \
-DAI_TYPES=NATIVE \
-DINSTALL_PORTABLE=ON \
-DCMAKE_USE_RELATIVE_PATHS:BOOL=1 \
-DBINDIR:PATH=./ \
-DLIBDIR:PATH=./ \
-DDATADIR:PATH=./ \
-DCMAKE_INSTALL_PREFIX="$(pwd)/install"
### Disabled in favor of using the settings from makepkg.conf
# -DCMAKE_TOOLCHAIN_FILE="toolchain/clang_x86_64-pc-linux-gnu.cmake" \
# V=1 make VERBOSE=1 -j1
cd "${srcdir}"; ninja #--verbose
And here what makepkg.conf introduces
#-- Compiler and Linker Flags
#CPPFLAGS=""
CFLAGS="-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions \
-Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security \
-fstack-clash-protection -fcf-protection \
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now \
-Wl,-z,pack-relative-relocs"
LTOFLAGS="-flto=auto"
#-- Make Flags: change this for DistCC/SMP systems
#MAKEFLAGS="-j2"
#-- Debugging flags
DEBUG_CFLAGS="-g"
DEBUG_CXXFLAGS="$DEBUG_CFLAGS"
Context & Diagnostic Data
Inspecting the core dump isolates the frame parameter conflict inside CBeamLaser::FireInternal where the negative distance value originates:
(gdb) frame 7
#7 CBeamLaser::FireInternal (...) at rts/Sim/Weapons/BeamLaser.cpp:360
360 TraceRay::TraceRayShields(this, curPos, curDir, beamLength, hitShields);
(gdb) info locals
beamLength = -82.403389
maxLength = 215
hitColQuery = { b0 = 1, b1 = 1, t0 = 83.6559067, t1 = 108.723846, ... }
An intersection query successfully found a collision boundary at hitColQuery.t0 = 83.6559067. However, beamLength evaluates to -82.403389.
The difference between the query distance and the resulting length maps directly to the weapon's muzzle piece offset from the origin axis:
83.6559067 - 82.403389 = 1.2525177
The terms appear to be inverted during calculation (muzzleOffset - hitColQuery.t0 instead of hitColQuery.t0 - muzzleOffset), generating a negative scalar value. This negative value is passed directly down into CQuadField::GetQuadsOnRay:
(gdb) frame 5
#5 CQuadField::GetQuadsOnRay(QuadFieldQuery&, float3 const&, float3 const&, float) at rts/Sim/Misc/QuadField.cpp:264
264 t0 = std::clamp(t0, 0.0f, length);
(gdb) info args
length = -82.403389
Because length is negative, calling std::clamp(t0, 0.0f, length) passes a high bound that is lower than the low bound (0.0f). On hardened distributions, this immediately triggers a runtime abort via __glibcxx_assert_fail.
Call Stack
#0 0x00007f05f74adfbb pthread_kill () from /usr/lib/libc.so.6
#1 0x00007f05f7444c88 raise () from /usr/lib/libc.so.6
#2 0x00007f05f7425795 abort () from /usr/lib/libc.so.6
#3 0x00007f05f789e059 _ZSt21__glibcxx_assert_fail... () from /usr/lib/libstdc++.so.6
#4 0x00005595fe675be0 std::clamp<float>(...)
#5 CQuadField::GetQuadsOnRay(...) at QuadField.cpp:264
#6 TraceRay::TraceRayShields(...) at TraceRay.cpp:343
#7 CBeamLaser::FireInternal(...) at BeamLaser.cpp:360
#8 CWeapon::Fire(bool) at Weapon.cpp:227
#9 CWeapon::UpdateSalvo() at Weapon.cpp:228
#10 CBeamLaser::Update() at BeamLaser.cpp:212
full output of me poking around in gdb
https://gist.github.com/Wabuo/d26242b7724c6dca6e9f10ccd905dd8d
Description
The engine crashes with
SIGABRTdue to a libstdc++ hardening assertion failure (__glibcxx_assert_fail) insideCQuadField::GetQuadsOnRay. A laser beam's length calculation yields an inverted negative distance value, which violates the downstreamstd::clampinvariant (lo <= hi).Environment
recoil-engine-rc(systemwide_managed_by_pkgmngr-2026.06.08-RC.local) (build from the AUR PKGBUILD (full build instructions used are below)-D_GLIBCXX_ASSERTIONS)Build Instructions used
And here what makepkg.conf introduces
Context & Diagnostic Data
Inspecting the core dump isolates the frame parameter conflict inside
CBeamLaser::FireInternalwhere the negative distance value originates:An intersection query successfully found a collision boundary at
hitColQuery.t0 = 83.6559067. However,beamLengthevaluates to-82.403389.The difference between the query distance and the resulting length maps directly to the weapon's muzzle piece offset from the origin axis:
83.6559067 - 82.403389 = 1.2525177The terms appear to be inverted during calculation (
muzzleOffset - hitColQuery.t0instead ofhitColQuery.t0 - muzzleOffset), generating a negative scalar value. This negative value is passed directly down intoCQuadField::GetQuadsOnRay:Because
lengthis negative, callingstd::clamp(t0, 0.0f, length)passes a high bound that is lower than the low bound (0.0f). On hardened distributions, this immediately triggers a runtime abort via__glibcxx_assert_fail.Call Stack
full output of me poking around in gdb
https://gist.github.com/Wabuo/d26242b7724c6dca6e9f10ccd905dd8d