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
|
//1 - because we're trapping usage
|
||||||
if (!pHandler->HandleNative(name, native, 1))
|
if (!pHandler->HandleNative(name, native, 1))
|
||||||
{
|
{
|
||||||
|
amx->usertags[UT_NATIVE] = (void *)native;
|
||||||
LogError(amx, AMX_ERR_INVNATIVE, NULL);
|
LogError(amx, AMX_ERR_INVNATIVE, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,53 +363,6 @@ bool Debugger::ErrorExists()
|
||||||
return (m_pCalls[m_Top]->m_Error != AMX_ERR_NONE);
|
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)
|
int Debugger::FormatError(char *buffer, size_t maxLength)
|
||||||
{
|
{
|
||||||
if (!ErrorExists())
|
if (!ErrorExists())
|
||||||
|
@ -450,207 +403,6 @@ int Debugger::FormatError(char *buffer, size_t maxLength)
|
||||||
amx_err = AMX_ERR_NOTFOUND;*/
|
amx_err = AMX_ERR_NOTFOUND;*/
|
||||||
//if (!amx_err)
|
//if (!amx_err)
|
||||||
size += _snprintf(buffer, maxLength, "(native \"%s\")", native_name);
|
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;
|
return size;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user