sourcemod icon indicating copy to clipboard operation
sourcemod copied to clipboard

Don't OOB arguments

Open Kenzzer opened this issue 9 months ago • 0 comments

Here's how numArgs is retrieved

std::vector<DataTypeSized_t> &argTypes = callingConvention->m_vecArgTypes;
size_t numArgs = argTypes.size();

Here's the loop

size_t firstArg = 0;
if (callConv == CallConv_THISCALL)
	firstArg = 1;
for (size_t i = 0; i < numArgs; i++) {
[...]
void *regAddr = callingConvention->GetArgumentPtr(i + firstArg, m_pDetour->m_pRegisters);
memcpy(paramAddr, regAddr, size);

Consider x86GccThiscall and function void Foo::Test(void)

x86GccThiscall::x86GccThiscall(std::vector<DataTypeSized_t> &vecArgTypes, DataTypeSized_t returnType, int iAlignment) :
	x86GccCdecl(vecArgTypes, returnType, iAlignment)
{
	// Always add the |this| pointer.
	DataTypeSized_t type;
	type.type = DATA_TYPE_POINTER;
	type.size = GetDataTypeSize(type, iAlignment);
	type.custom_register = None;
	m_vecArgTypes.insert(m_vecArgTypes.begin(), type);
}

So

std::vector<DataTypeSized_t> &argTypes = callingConvention->m_vecArgTypes;
size_t numArgs = argTypes.size();

Will return numArgs = 1

Let's go to the loop

size_t firstArg = 0;
if (callConv == CallConv_THISCALL) // true
	firstArg = 1;
for (size_t i = 0; i < 1; i++) {
[...]
void *regAddr = callingConvention->GetArgumentPtr(i + firstArg, m_pDetour->m_pRegisters);
memcpy(paramAddr, regAddr, size);

So callingConvention->GetArgumentPtr(0 + 1)

Here's definition of GetArgumentPtr (x86GccThiscall inherits from x86GccCdecl, and x86GccCdecl is an alias of x86MsCdecl)

void* x86MsCdecl::GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters)
{
	if (iIndex >= m_vecArgTypes.size())
		return NULL;
	[...]
}

iIndex is 1, m_vecArgTypes.size() is 1. nullptr is returned, this is then used on memcpy, this is wrong, it must be fixed.

Kenzzer avatar Mar 02 '25 13:03 Kenzzer