mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 06:15:37 +03:00
Fixed bug at25472
This commit is contained in:
parent
4369023394
commit
2843c333aa
@ -297,6 +297,7 @@ static cell AMX_NATIVE_CALL invalid_native(AMX *amx, cell *params)
|
||||
//1 - because we're trapping usage
|
||||
if (!pHandler->HandleNative(name, native, 1))
|
||||
{
|
||||
amx->usertags[UT_NATIVE] = (void *)native;
|
||||
LogError(amx, AMX_ERR_INVNATIVE, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
@ -363,53 +363,6 @@ bool Debugger::ErrorExists()
|
||||
return (m_pCalls[m_Top]->m_Error != AMX_ERR_NONE);
|
||||
}
|
||||
|
||||
#define FLAG_INDIRECT (1<<0)
|
||||
|
||||
//vaddr - the address of our current index vector
|
||||
//base - the base address of which the array is offset to
|
||||
//dim - the current dimension to search
|
||||
//dimNum - the number of dimensions total
|
||||
//sizes[] - an array containing the dimension sizes
|
||||
//Indexes[] - an output array to contain each dimension's index
|
||||
int WalkArray(cell *vaddr, unsigned char *base, cell *addr, int dim, int dimNum, int &flags, int sizes[], int Indexes[])
|
||||
{
|
||||
cell *my_addr;
|
||||
int idx = 0;
|
||||
|
||||
//if we are the second to last walker, we only need to check the ranges of our vector.
|
||||
if (dim == dimNum - 2)
|
||||
{
|
||||
my_addr = vaddr;
|
||||
//first check the actual vectors themselves
|
||||
for (int i=0; i<sizes[dim]; i++)
|
||||
{
|
||||
if (addr == my_addr)
|
||||
return i;
|
||||
my_addr++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//otherwise, search lower vectors!
|
||||
//vaddr is the address where we can start reading vectors
|
||||
flags |= FLAG_INDIRECT;
|
||||
for (int i=0; i<sizes[dim]; i++)
|
||||
{
|
||||
//the next vector is offset from the last address!
|
||||
//this is funky but that's the internal implementation
|
||||
my_addr = (cell *)((char *)vaddr + i*sizeof(cell) + vaddr[i]);
|
||||
idx = WalkArray(my_addr, base, addr, dim+1, dimNum, flags, sizes, Indexes);
|
||||
if (idx != -1)
|
||||
{
|
||||
Indexes[dim+1] = idx;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Debugger::FormatError(char *buffer, size_t maxLength)
|
||||
{
|
||||
if (!ErrorExists())
|
||||
@ -450,207 +403,6 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
|
||||
amx_err = AMX_ERR_NOTFOUND;*/
|
||||
//if (!amx_err)
|
||||
size += _snprintf(buffer, maxLength, "(native \"%s\")", native_name);
|
||||
#if 0
|
||||
} else if (error == AMX_ERR_BOUNDS) {
|
||||
tagAMX_DBG *pDbg = m_pAmxDbg;
|
||||
int symbols = pDbg->hdr->symbols;
|
||||
int index = 0;
|
||||
tagAMX_DBG_SYMBOL **pSymbols = pDbg->symboltbl;
|
||||
tagAMX_DBG_SYMBOL *pSymbol, *pLastSymbol=NULL;
|
||||
const tagAMX_DBG_SYMDIM *pDims;
|
||||
ucell addr = 0;
|
||||
int flags = 0;
|
||||
char v_class, i_dent;
|
||||
cell *arr_addr=NULL, *p_addr=NULL;
|
||||
unsigned char *data = m_pAmx->base + ((AMX_HEADER *)m_pAmx->base)->dat;
|
||||
bool valid=false;
|
||||
//we can't really browse the assembly because
|
||||
// we've no idea what the peephole optimizer did.
|
||||
// so we're gonna try to go out on a limb and guess.
|
||||
if (m_pAmx->alt < 0)
|
||||
{
|
||||
//take a guess that it's local
|
||||
addr = m_pAmx->alt - pTrace->frm;
|
||||
v_class = 1;
|
||||
} else {
|
||||
//take a guess that it's a global
|
||||
//it won't be global if it's passed in from the stack frame, however
|
||||
// doing this with a hardcoded array size is quite rare, and is probably passed
|
||||
// as iREFARRAY not iARRAY!
|
||||
addr = m_pAmx->alt;
|
||||
v_class = 0;
|
||||
}
|
||||
bool found = false;
|
||||
bool _found = true;
|
||||
static char _msgbuf[255];
|
||||
size_t _size = 0;
|
||||
//take a pre-emptive guess at the v_class!
|
||||
//are we GLOBAL (0) or LOCAL (1) ?
|
||||
if (m_pAmx->alt < 0)
|
||||
{
|
||||
v_class = 1;
|
||||
i_dent = iARRAY;
|
||||
arr_addr = (cell *)(data + pTrace->frm + m_pAmx->alt);
|
||||
} else {
|
||||
//it's greater than 0, check other things!
|
||||
if (m_pAmx->alt >= m_pAmx->hlw &&
|
||||
m_pAmx->alt <= m_pAmx->stp)
|
||||
{
|
||||
//it's in the stack somewhere... guess that it's a local!
|
||||
v_class = 1;
|
||||
//relocate it
|
||||
m_pAmx->alt -= pTrace->frm;
|
||||
//alt cannot be zero
|
||||
if (m_pAmx->alt < 0)
|
||||
i_dent = iARRAY;
|
||||
else
|
||||
i_dent = iREFARRAY;
|
||||
arr_addr = (cell *)(data + pTrace->frm + m_pAmx->alt);
|
||||
} else {
|
||||
//guess that it's DAT
|
||||
v_class = 0;
|
||||
i_dent = iARRAY;
|
||||
arr_addr = (cell *)(data + m_pAmx->alt);
|
||||
}
|
||||
}
|
||||
for (index = 0; index < symbols; index++)
|
||||
{
|
||||
pSymbol = pSymbols[index];
|
||||
if (pSymbol->codestart <= (ucell)cip &&
|
||||
pSymbol->codeend >= (ucell)cip &&
|
||||
(pSymbol->ident == iARRAY || pSymbol->ident == iREFARRAY))
|
||||
{
|
||||
amx_err = dbg_GetArrayDim(pDbg, pSymbol, &pDims);
|
||||
if (amx_err != AMX_ERR_NONE)
|
||||
continue;
|
||||
//calculate the size of the array. this is important!
|
||||
ucell size = pDims[0].size;
|
||||
ucell aggre = pDims[0].size;
|
||||
valid = false;
|
||||
for (int16_t i=1; i<pSymbol->dim; i++)
|
||||
{
|
||||
aggre *= pDims[i].size;
|
||||
size += aggre;
|
||||
}
|
||||
if (pSymbol->vclass != v_class)
|
||||
continue;
|
||||
if (pSymbol->ident != i_dent)
|
||||
continue;
|
||||
if (v_class == 1)
|
||||
{
|
||||
if (i_dent == iARRAY)
|
||||
{
|
||||
p_addr = (cell *)(data + pTrace->frm + pSymbol->address);
|
||||
} else if (i_dent == iREFARRAY) {
|
||||
//get the variable off the stack, by reference
|
||||
ucell _addr = (ucell)*((cell *)(data + pTrace->frm + pSymbol->address));
|
||||
p_addr = (cell *)(data + _addr);
|
||||
}
|
||||
} else if (v_class == 0) {
|
||||
p_addr = (cell *)(data + pSymbol->address);
|
||||
}
|
||||
//make sure our address is in bounds!
|
||||
if (arr_addr < p_addr || arr_addr > (p_addr + size))
|
||||
continue;
|
||||
int *sizes = new int[pSymbol->dim];
|
||||
int *indexes = new int[pSymbol->dim];
|
||||
for (int i=0; i<pSymbol->dim; i++)
|
||||
{
|
||||
sizes[i] = pDims[i].size;
|
||||
indexes[i] = -1;
|
||||
}
|
||||
flags = 0;
|
||||
if (pSymbol->dim >= 2)
|
||||
{
|
||||
int dims = pSymbol->dim;
|
||||
indexes[0] = WalkArray(p_addr, data, arr_addr, 0, pSymbol->dim, flags, sizes, indexes);
|
||||
if (indexes[0] == -1)
|
||||
{
|
||||
while (indexes[0] == -1 && --dims > 0)
|
||||
{
|
||||
flags = 0;
|
||||
indexes[0] = WalkArray(p_addr, data, arr_addr, 0, dims, flags, sizes, indexes);
|
||||
}
|
||||
}
|
||||
//find the last known good dimension
|
||||
for (dims=pSymbol->dim-1; dims>=0; dims--)
|
||||
{
|
||||
if (indexes[dims] != -1)
|
||||
break;
|
||||
}
|
||||
//check for the "impossible" case.
|
||||
//if we have [X][-1], and X is zero, the array did not walk properly.
|
||||
if (dims >= 0
|
||||
&& indexes[dims] == 0
|
||||
&& !(flags & FLAG_INDIRECT)
|
||||
&& dims < pSymbol->dim - 1)
|
||||
{
|
||||
//here we have the dreaded MIXED CASE. we don't know whether
|
||||
//[-][X] or [0][-] (where - is a bad input) was intended.
|
||||
//first, we take a guess by checking the bounds.
|
||||
cell *_cip = (cell *)_CipAsVa(cip);
|
||||
_cip -= 1;
|
||||
cell bounds = *_cip;
|
||||
if (sizes[dims] != sizes[dims+1])
|
||||
{
|
||||
//we were checking initial bounds
|
||||
if (bounds == sizes[dims] - 1)
|
||||
{
|
||||
indexes[dims] = m_pAmx->pri;
|
||||
} else if (bounds == sizes[dims+1] - 1) {
|
||||
indexes[dims + 1] = m_pAmx->pri;
|
||||
indexes[dims] = 0;
|
||||
} else {
|
||||
//this should really never happen...
|
||||
_found = false;
|
||||
}
|
||||
} else {
|
||||
_found = false;
|
||||
}
|
||||
if (!_found)
|
||||
{
|
||||
//we still don't have a good approximation.
|
||||
//the user did something like:
|
||||
//new X[40][40]
|
||||
//we could do some really complicated and random guesswork
|
||||
// but fact is, we have no way of deterministically knowing
|
||||
// what the user intended.
|
||||
}
|
||||
} else {
|
||||
//set the last know index to our culprit
|
||||
indexes[dims + 1] = m_pAmx->pri;
|
||||
}
|
||||
} else {
|
||||
indexes[0] = m_pAmx->pri;
|
||||
}
|
||||
_size += _snprintf(&(_msgbuf[_size]), sizeof(_msgbuf)-_size, "(array \"%s", pSymbol->name);
|
||||
for (int i=0; i<pSymbol->dim; i++)
|
||||
_size += _snprintf(&(_msgbuf[_size]), sizeof(_msgbuf)-_size, "[%d]", pDims[i].size);
|
||||
if (_found)
|
||||
{
|
||||
_size += _snprintf(&(_msgbuf[_size]), sizeof(_msgbuf)-_size, "\") (indexed \"");
|
||||
for (int i=0; i<pSymbol->dim; i++)
|
||||
{
|
||||
if (indexes[i] == -1)
|
||||
_size += _snprintf(&(_msgbuf[_size]), sizeof(_msgbuf)-_size, "[]");
|
||||
else
|
||||
_size += _snprintf(&(_msgbuf[_size]), sizeof(_msgbuf)-_size, "[%d]", indexes[i]);
|
||||
}
|
||||
_size += _snprintf(&(_msgbuf[_size]), sizeof(_msgbuf)-_size, "\")");
|
||||
} else {
|
||||
_size += _snprintf(&(_msgbuf[_size]), sizeof(_msgbuf)-_size, "\") (unknown index \"%d\")", m_pAmx->pri);
|
||||
}
|
||||
found = true;
|
||||
delete [] indexes;
|
||||
delete [] sizes;
|
||||
break;
|
||||
} /* symbol validation */
|
||||
} /* is in valid ranges */
|
||||
if (!found)
|
||||
_msgbuf[0] = '\0';
|
||||
|
||||
size += _snprintf(buffer, maxLength, "%s", _msgbuf);
|
||||
#endif //0 - NOT USED!
|
||||
}
|
||||
|
||||
return size;
|
||||
|
Loading…
Reference in New Issue
Block a user