TF2: CUtlBuffer crash when loading local loadout
When running Frog Fortress 2 from the launcher (mod_tf_win64.exe), the game opens fine, but then asserts when retrieving my local loadout from the item servers. If I ignore the assert, it immediately re-appears. Ignoring all assertions crashes the game.
The callstack references functions I do not have access to.
The assertion:
The callstack:
The last function on the callstack before running into functions i don't have the sourcecode for:
Where it stops specifically:
After I ignore all assertions, it crashes here:
Presumably because whatever 'AddLocalSOCache' was doing failed.
Compile under Release, Debug enables assertions.
Release build does indeed fix it, but debug should not crash the game
I read this while the game was compiling under Debug mode! Ty for letting me know, ig I'll restart the build
I got it to fail gracefully by replacing line 968 of tf_item_inventory.cpp with
CEconItem* socData = pItem->GetSOCData();
if (socData)
socData->Equip(iClass, iSlot);
granted, this makes your inventory inaccessible in a debug build still as it doesn't solve the root cause of the issue, but at least it makes a debug build usable at all
P.S. the assert can be fixed by changing it to check for it being >= 0 instead, as per https://developer.valvesoftware.com/wiki/SDK_Known_Issues_List#Assertion_Failed_in_utlbuffer.cpp
GCSDK::CGCClientSharedObjectTypeCache::BParseCacheSubscribedMsg(
const CMsgSOCacheSubscribed_SubscribedType &msg,
CUtlVector<GCSDK::CSharedObjectt*,CUtlMemory<GCSDK::CSharedObject *,int>> &vecCreatedObjects,
CUtlVector<GCSDK::CSharedObject *,CUtlMemory<GCSDK::CSharedObject *,int>> &vecUpdatedObjects,
CUtlVector<GCSDK::CSharedObject *,CUtlMemory<GCSDK::CSharedObject *,int>> &vecObjectsToDestroy
)
src\gcsdk\gcclient_sharedobjectcache.cpp:153 is reading data from [r8+10h] to pass, but for some reason on debug builds, this address just contains 0x00000000 which it then uses in GCSDK::CGCClientSharedObjectTypeCache::BCreateFromMsg(const void *)
(Probably a const void * because it's inlined, see public header below.)
Here is the public header for the class. https://github.com/ValveSoftware/source-sdk-2013/blob/aea94b32cbefeba5d16ef6fc70eff9508cf11673/src/public/gcsdk/gcclient_sharedobjectcache.h#L154-L174 Not sure what's not properly setting the buffer size. But it's probably the root cause of CUtlBuffer screwing up.
Accidentally opened a duplicate issue for this bug but I wrote a bit about how the crash occurs in case it helps.
Ok so a quick update on this issue, I've managed to compile a debug build against the release build of libprotobuf (not without it and the linker kicking and screaming.) which suggests it's an issue somewhere between the GCSDK and Protobuf (or maybe just protobuf.)
How I managed to get it to compile
Previous preprocessor configuration
With the new SDK code in place ("SDK 2025"), a bunch of preprocessor definitions was changed, meaning for whatever reason only release builds allows for iterator debug level mismatch etc. (???)
On debug builds, these mismatch settings are absent. However on the previous SDK code ("SDK 2013") the following preprocessor definitions are present on both Release and Debug
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
_ALLOW_RUNTIME_LIBRARY_MISMATCH
_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH
_ALLOW_MSC_VER_MISMATCH
One big difference is _HAS_ITERATOR_DEBUGGING=0 only being in the debug configuration, I'll come back to this.
Current preprocessor configuration
On the SDK 2025 it's been split into the following:
Shared (Release/Debug):
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
Release:
_ALLOW_RUNTIME_LIBRARY_MISMATCH
_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH
_ALLOW_MSC_VER_MISMATCH
Debug:
_SCL_SECURE_NO_WARNINGS
The main takeaway is that
- A bunch of the "allow mismatch" defines were moved to Release (weren't this meant for Debug?)
- A new
_SCL_SECURE_NO_WARNINGSdefine was added to Debug. _HAS_ITERATOR_DEBUGGING=0was removed.
Why is this suddenly an issue
Well technically this isn't an issue, ideally you wouldn't want to mix and mismatch stuff. But in our case if we try to compile on debug using the release version of libprotobuf we'll get something like this:
libprotobuf.lib(...) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in ...
To get around this we can just add _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH to our preprocessor.
However then we'll run into this instead:
some.lib(other.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' in libprotobuf.lib(common.obj)
... So to get around that we have to add _HAS_ITERATOR_DEBUGGING=0 to our (debug build) preprocessor as well.
As you can tell it suggests someone at some point (most likely at Valve) had the same issue and disabled iterator debugging.
Solution
I've made a commit at zxz41@ce00728 that temporarily gets around the issue, and link against the release version of libprotobuf. However this is not an ideal solution since it applies _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH;_ITERATOR_DEBUG_LEVEL=0 to every project as a blanket solution. I'll consider opening PR and see where it goes from there.
https://github.com/ValveSoftware/source-sdk-2013/blob/ce00728b4aaa64156b03632cefdd7549462b8d5e/src/vpc_scripts/source_dll_win32_debug.vpc#L79-L80 https://github.com/ValveSoftware/source-sdk-2013/blob/ce00728b4aaa64156b03632cefdd7549462b8d5e/src/game/protobuf_include.vpc#L18-L49
Can we just recompile protobruh with the same configuration as it was?
Can we just recompile protobruh with the same configuration as it was?
IIRC when I tried compiling a custom build of protobuf in debug mode, it would still crash.
You could try compile release with _ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH but you would still likely get complaints from other libraries that there's _ITERATOR_DEBUG_LEVEL mismatches.
Also there's some complications (i think) since it's a partial copy of a non-redistributable repository. https://github.com/ValveSoftware/source-sdk-2013/blob/39f6dde8fbc238727c020d13b05ecadd31bda4c0/src/thirdparty/protobuf-2.6.1/README.valve#L1-L5
Also yeah accepting compiled library files from pull requests is a recipe for disaster. (hidden malicious code, wrong compiler params etc.)
is it possible to patch the the actual lib? sigmatching or something else?
local_loadout.txt