Summary
RPC4GlobalRegistration's constructors copy uniqueID into the fixed GlobalRegistration::functionName buffer without guaranteeing a NUL terminator. A uniqueID whose length equals RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH (currently 48, see Source/include/mafianet/defines.h:181) fills the buffer with no terminating '\0'.
RPC4::OnAttach() later passes functionName as a const char* into RegisterFunction / RegisterSlot / RegisterBlockingFunction, where RakString::Assign(const char*) calls strlen — reading past the buffer.
Location
Source/src/RPC4Plugin.cpp, all RPC4GlobalRegistration constructors:
for (i=0; uniqueID[i]; i++)
{
RakAssert(i<=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH-1);
globalRegistrationBuffer[globalRegistrationIndex].functionName[i]=uniqueID[i];
}
// no functionName[i] = '\0'
The RakAssert permits i up to MAX-1, i.e. filling all 48 bytes, and is a no-op in release builds.
Notes
Suggested fix
Tighten the assert to i < MAX-1 and write an explicit terminator after the copy loop, in every constructor:
for (i=0; uniqueID[i]; i++)
{
RakAssert(i < RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH-1);
globalRegistrationBuffer[globalRegistrationIndex].functionName[i]=uniqueID[i];
}
globalRegistrationBuffer[globalRegistrationIndex].functionName[i]='\0';
Summary
RPC4GlobalRegistration's constructors copyuniqueIDinto the fixedGlobalRegistration::functionNamebuffer without guaranteeing a NUL terminator. AuniqueIDwhose length equalsRPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH(currently 48, seeSource/include/mafianet/defines.h:181) fills the buffer with no terminating'\0'.RPC4::OnAttach()later passesfunctionNameas aconst char*intoRegisterFunction/RegisterSlot/RegisterBlockingFunction, whereRakString::Assign(const char*)callsstrlen— reading past the buffer.Location
Source/src/RPC4Plugin.cpp, allRPC4GlobalRegistrationconstructors:The
RakAssertpermitsiup toMAX-1, i.e. filling all 48 bytes, and is a no-op in release builds.Notes
aa9af6a9. Filing separately so it isn't conflated with that feature work.uniqueIDof exactly the max length; the static buffer is zero-initialized, so shorter IDs happen to land on a zero byte.Suggested fix
Tighten the assert to
i < MAX-1and write an explicit terminator after the copy loop, in every constructor: