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

[tf2][server] Undefined behavior by shifting (1 << 32) introduced in 46b8c3a

Open dimhotepus opened this issue 10 months ago • 1 comments

First of all, great catch in https://github.com/ValveSoftware/source-sdk-2013/commit/46b8c3a544ef453285b1652c58c201f6f40aa32c @copperpixel, thank you!

Unfortunately, shifting (1 << 32) is undefined behavior (UB), see C++ standard:

(C++11, 5.8p1) "The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand."

On latest MSVC you get (warning C4293: '<<': shift count negative or too big, undefined behavior): https://godbolt.org/z/6vfj8cozj On latest GCC you get (warning: left shift count >= width of type [-Wshift-count-overflow]): https://godbolt.org/z/E791fcM6T

Technically it is better to not rely on UB as compilers behavior may change (undefined means exactly this :)).

Suggest either shift by 31 if 31 bits are enough or promote operand to long long if all 32 bits are used (1U << 32 is still UB):

// Use long long since PLAYER_FLAG_BITS is 32 and (int)1 << 32 is undefined behavior.
long long mask = ( 1LL << PLAYER_FLAG_BITS ) - 1;
long long data = *( int* )pVarData;

pOut->m_Int = static_cast<int>( data & mask );

See https://stackoverflow.com/questions/9860538/unexpected-c-c-bitwise-shift-operators-outcome

dimhotepus avatar Feb 27 '25 09:02 dimhotepus

Addressed in PR https://github.com/ValveSoftware/source-sdk-2013/pull/876 Thanks for bringing this up!

copperpixel avatar Feb 27 '25 11:02 copperpixel

Function in PR has been dropped in latest sources: https://github.com/ValveSoftware/source-sdk-2013/blob/a62efecf624923d3bacc67b8ee4b7f8a9855abfd/src/game/server/player.cpp

dimhotepus avatar Mar 08 '25 20:03 dimhotepus