source-sdk-2013 icon indicating copy to clipboard operation
source-sdk-2013 copied to clipboard

TF2: CUtlBuffer crash when loading local loadout

Open ClayHanson opened this issue 10 months ago • 6 comments

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: Image

The callstack: Image

The last function on the callstack before running into functions i don't have the sourcecode for: Image

Where it stops specifically: Image

After I ignore all assertions, it crashes here: Image

Presumably because whatever 'AddLocalSOCache' was doing failed.

ClayHanson avatar Feb 19 '25 14:02 ClayHanson

Compile under Release, Debug enables assertions.

Marioiscool246 avatar Feb 19 '25 14:02 Marioiscool246

Release build does indeed fix it, but debug should not crash the game

ClayHanson avatar Feb 19 '25 14:02 ClayHanson

I read this while the game was compiling under Debug mode! Ty for letting me know, ig I'll restart the build

995qa avatar Feb 23 '25 05:02 995qa

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

TorutheRedFox avatar Feb 24 '25 20:02 TorutheRedFox

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.)

Image

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.

zxz41 avatar Mar 01 '25 22:03 zxz41

Accidentally opened a duplicate issue for this bug but I wrote a bit about how the crash occurs in case it helps.

Tkain avatar Mar 19 '25 01:03 Tkain

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_WARNINGS define was added to Debug.
  • _HAS_ITERATOR_DEBUGGING=0 was 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

zxz41 avatar May 22 '25 14:05 zxz41

Can we just recompile protobruh with the same configuration as it was?

SanyaSho avatar May 22 '25 15:05 SanyaSho

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.)

zxz41 avatar May 22 '25 16:05 zxz41

is it possible to patch the the actual lib? sigmatching or something else?

Nbc66 avatar Jul 04 '25 23:07 Nbc66

local_loadout.txt

Gchipunov avatar Jul 07 '25 01:07 Gchipunov