Debugger: Fixed emulator crash when entering some invalid watch/debug expressions

This commit is contained in:
Souryo 2016-12-10 15:18:50 -05:00
parent c9c55b2c7e
commit c317179afc
2 changed files with 71 additions and 30 deletions

View file

@ -171,12 +171,37 @@ string ExpressionEvaluator::GetNextToken(string expression, size_t &pos)
return output; return output;
} }
void ExpressionEvaluator::ToRpn(string expression, vector<int> &outputQueue) bool ExpressionEvaluator::ProcessSpecialOperator(EvalOperators evalOp, std::stack<EvalOperators> &opStack, vector<int> &outputQueue)
{
if(opStack.empty()) {
return false;
}
while(opStack.top() != evalOp) {
outputQueue.push_back(opStack.top());
opStack.pop();
if(opStack.empty()) {
return false;
}
}
if(evalOp != EvalOperators::Parenthesis) {
outputQueue.push_back(opStack.top());
}
opStack.pop();
return true;
}
bool ExpressionEvaluator::ToRpn(string expression, vector<int> &outputQueue)
{ {
std::stack<EvalOperators> opStack = std::stack<EvalOperators>(); std::stack<EvalOperators> opStack = std::stack<EvalOperators>();
std::stack<int> precedenceStack; std::stack<int> precedenceStack;
size_t position = 0; size_t position = 0;
int parenthesisCount = 0;
int bracketCount = 0;
int braceCount = 0;
bool previousTokenIsOp = true; bool previousTokenIsOp = true;
while(true) { while(true) {
string token = GetNextToken(expression, position); string token = GetNextToken(expression, position);
@ -203,44 +228,49 @@ void ExpressionEvaluator::ToRpn(string expression, vector<int> &outputQueue)
previousTokenIsOp = true; previousTokenIsOp = true;
} else if(token[0] == '(') { } else if(token[0] == '(') {
parenthesisCount++;
opStack.push(EvalOperators::Parenthesis); opStack.push(EvalOperators::Parenthesis);
precedenceStack.push(0); precedenceStack.push(0);
previousTokenIsOp = true; previousTokenIsOp = true;
} else if(token[0] == ')') { } else if(token[0] == ')') {
while(opStack.top() != EvalOperators::Parenthesis) { parenthesisCount--;
outputQueue.push_back(opStack.top()); if(!ProcessSpecialOperator(EvalOperators::Parenthesis, opStack, outputQueue)) {
opStack.pop(); return false;
} }
opStack.pop();
} else if(token[0] == '[') { } else if(token[0] == '[') {
bracketCount++;
opStack.push(EvalOperators::Bracket); opStack.push(EvalOperators::Bracket);
precedenceStack.push(0); precedenceStack.push(0);
} else if(token[0] == ']') { } else if(token[0] == ']') {
while(opStack.top() != EvalOperators::Bracket) { bracketCount--;
outputQueue.push_back(opStack.top()); if(!ProcessSpecialOperator(EvalOperators::Bracket, opStack, outputQueue)) {
opStack.pop(); return false;
} }
outputQueue.push_back(opStack.top());
opStack.pop();
} else if(token[0] == '{') { } else if(token[0] == '{') {
braceCount++;
opStack.push(EvalOperators::Braces); opStack.push(EvalOperators::Braces);
precedenceStack.push(0); precedenceStack.push(0);
} else if(token[0] == '}') { } else if(token[0] == '}') {
while(opStack.top() != EvalOperators::Braces) { braceCount--;
outputQueue.push_back(opStack.top()); if(!ProcessSpecialOperator(EvalOperators::Braces, opStack, outputQueue)){
opStack.pop(); return false;
} }
outputQueue.push_back(opStack.top());
opStack.pop();
} else { } else {
outputQueue.push_back(std::stoi(token)); outputQueue.push_back(std::stoi(token));
} }
} }
if(braceCount || bracketCount || parenthesisCount) {
//Mismatching number of brackets/braces/parenthesis
return false;
}
while(!opStack.empty()) { while(!opStack.empty()) {
outputQueue.push_back(opStack.top()); outputQueue.push_back(opStack.top());
opStack.pop(); opStack.pop();
} }
return true;
} }
int32_t ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr) int32_t ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr)
@ -318,8 +348,9 @@ ExpressionEvaluator::ExpressionEvaluator(Debugger* debugger)
_debugger = debugger; _debugger = debugger;
} }
int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr) int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr, bool& success)
{ {
success = true;
vector<int> output; vector<int> output;
vector<int> *outputQueue = nullptr; vector<int> *outputQueue = nullptr;
@ -335,8 +366,9 @@ int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &stat
if(outputQueue == nullptr && output.empty()) { if(outputQueue == nullptr && output.empty()) {
string fixedExp = expression; string fixedExp = expression;
fixedExp.erase(std::remove(fixedExp.begin(), fixedExp.end(), ' '), fixedExp.end()); fixedExp.erase(std::remove(fixedExp.begin(), fixedExp.end(), ' '), fixedExp.end());
ToRpn(fixedExp, output); success = ToRpn(fixedExp, output);
if(success) {
if(_containsCustomLabels) { if(_containsCustomLabels) {
outputQueue = &output; outputQueue = &output;
} else { } else {
@ -344,6 +376,9 @@ int32_t ExpressionEvaluator::PrivateEvaluate(string expression, DebugState &stat
_outputCache[expression] = output; _outputCache[expression] = output;
outputQueue = &_outputCache[expression]; outputQueue = &_outputCache[expression];
} }
} else {
return 0;
}
} }
if(outputQueue) { if(outputQueue) {
@ -362,11 +397,16 @@ int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, int1
int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr) int32_t ExpressionEvaluator::Evaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr)
{ {
try { try {
return PrivateEvaluate(expression, state, resultType, memoryValue, memoryAddr); bool success;
int32_t result = PrivateEvaluate(expression, state, resultType, memoryValue, memoryAddr, success);
if(success) {
return result;
}
} catch(std::exception e) { } catch(std::exception e) {
}
resultType = EvalResultType::Invalid; resultType = EvalResultType::Invalid;
return 0; return 0;
}
} }
bool ExpressionEvaluator::Validate(string expression) bool ExpressionEvaluator::Validate(string expression)
@ -374,8 +414,9 @@ bool ExpressionEvaluator::Validate(string expression)
try { try {
DebugState state; DebugState state;
EvalResultType type; EvalResultType type;
PrivateEvaluate(expression, state, type, 0, 0); bool success;
return true; PrivateEvaluate(expression, state, type, 0, 0, success);
return success;
} catch(std::exception e) { } catch(std::exception e) {
return false; return false;
} }

View file

@ -93,12 +93,12 @@ private:
bool IsOperator(string token, int &precedence, bool unaryOperator); bool IsOperator(string token, int &precedence, bool unaryOperator);
EvalOperators GetOperator(string token, bool unaryOperator); EvalOperators GetOperator(string token, bool unaryOperator);
int GetOperatorPrecendence(string token);
bool CheckSpecialTokens(string expression, size_t &pos, string &output); bool CheckSpecialTokens(string expression, size_t &pos, string &output);
string GetNextToken(string expression, size_t &pos); string GetNextToken(string expression, size_t &pos);
void ToRpn(string expression, vector<int> &outputQueue); bool ProcessSpecialOperator(EvalOperators evalOp, std::stack<EvalOperators> &opStack, vector<int> &outputQueue);
bool ToRpn(string expression, vector<int> &outputQueue);
int32_t EvaluateExpression(vector<int> *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr); int32_t EvaluateExpression(vector<int> *outputQueue, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr);
int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr); int32_t PrivateEvaluate(string expression, DebugState &state, EvalResultType &resultType, int16_t memoryValue, uint32_t memoryAddr, bool &success);
public: public:
ExpressionEvaluator(Debugger* debugger); ExpressionEvaluator(Debugger* debugger);