$GIT/scripts/LEVEL15.cpp: In function ‘void aMatCenPuzzleInit()’:
$GIT/scripts/LEVEL15.cpp:833:38: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
833 | #define MagicMatCenSwitchSequence (*((int *)(&User_vars[17])))
$GIT/scripts/LEVEL15.cpp:834:25: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
834 | #define MatCenStateA (*((int *)(&User_vars[0])))
...
$GIT/scripts/Level6.cpp: In function ‘void aPriestKeyEnter(int)’:
$GIT/scripts/Level6.cpp:910:47: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
910 | #define Var_ThereIsPlayerInPriestKeyPuzzle (*((int *)(&User_vars[7])))
Turn ``User_var`` into an array of std::variant, the latter of which can hold
either float or int. Savegames do not carry the necessary type information
which variant (float/int) is in use; instead, this is statically decided by
the level DLL logic on a per-index basis. This approach is retained for now.
A lot of ``Var_something = 0`` is used despite Var_something being
logically used as float, so we need to override op= to keep the
variant type as-is.
Due to ``#include "DallasFuncs.cpp"``, DF is recompiled 52 times.
Rework it to build just once. The compile time goes down for me
from 1m45.3s to 1m38.8s on my 1135G7 CPU running make -j8.
The switcheroo involving OSIRISEXTERN is unnecessary; if it is empty,
it is "extern" anyway.
One function, ``osicommon_Initialize``, is present twice and can lead
to duplicate definitions in the linker stage, which is probably what
the DallasFuncs.cpp comment alluded to. It is moved away into its own
.cpp file.
Both e.g. AIGame3.cpp and DallasFuncs.cpp include
``osiris_vector.h``. Right now, this is not a problem because
DallasFuncs.cpp is not compiled itself, but included from
AIGame3.cpp, in other words, it is all just one translation unit.
I have a plan to do away with ``#include "DallasFuncs.cpp"``, which
means the linker invocation for AIGame3.so will have at least two
translation units, and thus two definitions of the osiris vector
functions, which is not allowed.
This also has the side-effect to reduce compile-time a little,
from 1m57.5s to 1m48.7s on my 1135G7 CPU using `make -j8`.
I want to namespace the stuff in DallasFuncs.cpp, and when I do that,
there comes about an ambiguity between ``NewNamespace::aUserFlagSet``
and the ``::aUserFlagSet`` declared by LEVEL15 (also ``qUserFlag``).
Due to ``#include "DallasFuncs.cpp"``, LEVEL15.cpp already has a
declaration (and definition) for ``aUserFlagSet``, and so we can jsut
remove the two lines.
gcc warns about strict aliasing violations in fix.cpp:
fix/fix.cpp: In function "int FloatRound(float)":
fix/fix.cpp:157:14: warning: dereferencing type-punned pointer will
break strict-aliasing rules [-Wstrict-aliasing]
157 | return ((*((int *)&nf)) & 0x7FFFFF) - 2048;
But these functions and then some are unused, so delete them altogether.
vp[26] is `int *`, so it tries to read 4 bytes on amd64, even though
TCP_Active, which is behind vp[26] is just a bool and 1 byte.
==95927==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000004734f40 at pc 0x7f4f8d93b952 bp 0x7ffc57f191b0 sp 0x7ffc57f191a8
READ of size 4 at 0x000004734f40 thread T0
f0 DLLMultiInit $GIT/netcon/includes/mdllinit.h:314
f1 LoadMultiDLL(char const*) $GIT/Descent3/multi_dll_mgr.cpp:690
f2 RunServerConfigs $GIT/Descent3/dedicated_server.cpp:236
f3 LoadServerConfigFile() $GIT/Descent3/dedicated_server.cpp:357
f4 InitDedicatedServer $GIT/Descent3/init.cpp:1778
f5 InitD3Systems2(bool) $GIT/Descent3/init.cpp:1952
f6 Descent3() $GIT/Descent3/descent.cpp:504
f7 oeD3LnxApp::run() $GIT/Descent3/sdlmain.cpp:151
0x000004734f41 is located 0 bytes after global variable 'TCP_active' defined in '$GIT/networking/networking.cpp:383:6' (0x4734f40) of size 1
SUMMARY: AddressSanitizer: global-buffer-overflow $GIT/netcon/includes/mdllinit.h:314 in DLLMultiInit
Resolve an out-of-bounds write in LoadServerConfigFile.
A sufficiently long path,
descent3 -dedicated /home/jengelh/.config/descent3/dedicated.conf
causes the game server to exit with
Error loading connection DLL 'cated.conf'
Which hints at a buffer overflow.
ASAN reports:
$GIT/Descent3/dedicated_server.cpp:350:24: runtime error: index 1024
out of bounds for type 'cvar_entry [36]'
$GIT/Descent3/dedicated_server.cpp:350:14: runtime error: load of
address 0x000001e677c0 with insufficient space for an object of type
'const char *'
This can happen if a line in the .cfg starts with a '#'.
Descent3/render.cpp:2989:8: warning: type "struct obj_sort_item" violates the C++ One Definition Rule [-Wodr]
2989 | struct obj_sort_item {
Descent3/terrainrender.cpp:943:8: note: a different type is defined in another translation unit
During Retribution level 13, after about 5 minutes when some timed
level script seems to run and the message "GB: Engine malfunction" is
printed, there is also an assert:
Assertion failure at msafe_CallFunction ($GIT/Descent3/multisafe.cpp:1719), triggered 1 time:
'mstruct->id != -1'
The result from SpewCreate is -1 because there are no more gun slots
available, i.e. this condition is where the function exited thru:
if (spew->gp.gunpoint < 0 || spew->gp.gunpoint >= pm->n_guns)
ASAN complained:
$GIT/Descent3/BOA.cpp:443:54: runtime error: index -1 out of bounds for type 'float [40]'
At that particular time, important variables had these values:
cur_room=36 this_portal=-1
(Happened during Retribution level 8 in the ship hangar with the docking clamps.)
Descent3/AIGoal.cpp:938:28: runtime error: index -1 out of bounds for type 'goal [10]'
Occurs in Retribution level 7 whenever a FS440 "Six Gun" robot
is destroyed.
smfaces[facenum=0].texnum=-1
Descent3/splinter.cpp:73:74: runtime error: index -1 out of bounds for type "short int [35]"
Adding to ``total`` can cause signed integer overflow, which is
undefined, and ASAN warns:
Descent3/terrain.cpp:300:11: runtime error: signed integer overflow:
2147421608 + 65586 cannot be represented in type 'int'
Switch the variable unsigned; the bit patterns in practice will be
the same, but unsigned wraparound is well-defined. Finally, convert
the result back to signed, which should be allowed, cf.
http://eel.is/c++draft/conv.integral#3 .
Descent3/WeaponFire.cpp:2130:7: runtime error: signed integer overflow:
520857 * 5000 cannot be represented in type "int"
This is about how the Omega's gun ray is animated, and given there is
some sine wave stuff going on, it is fair to say that the intent was
for the value to wraparound. However, wraparound in C++ is only
well-defined for unsigned types, so switch it.
ASAN says:
linux/lnxcontroller.cpp:484:12: runtime error: left shift of negative value -1
(in other words, "-1 << x", not "x << (-1)")
Bitwise AND/OR often only make sense for unsigned quantities, so
enforce exactly that kind of treatment.