ExprEngine: Temporary hardcoding for calloc

This commit is contained in:
Daniel Marjamäki 2019-09-24 22:22:16 +02:00
parent 7cf8327b31
commit 0011fb5a36
3 changed files with 44 additions and 6 deletions

View File

@ -191,7 +191,7 @@ namespace {
unsigned int size = 1; unsigned int size = 1;
for (const auto &dim : tok->variable()->dimensions()) for (const auto &dim : tok->variable()->dimensions())
size *= dim.num; size *= dim.num;
auto val = std::make_shared<ExprEngine::ArrayValue>(getNewSymbolName(), size); auto val = std::make_shared<ExprEngine::ArrayValue>(getNewSymbolName(), size, size);
memory[tok->varId()] = val; memory[tok->varId()] = val;
return val; return val;
} }
@ -249,6 +249,13 @@ void ExprEngine::ArrayValue::assign(ExprEngine::ValuePtr index, ExprEngine::Valu
} }
} }
void ExprEngine::ArrayValue::clear()
{
auto zero = std::make_shared<ExprEngine::IntRange>("0", 0, 0);
for (int i = 0; i < data.size(); ++i)
data[i] = zero;
}
ExprEngine::ValuePtr ExprEngine::ArrayValue::read(ExprEngine::ValuePtr index) ExprEngine::ValuePtr ExprEngine::ArrayValue::read(ExprEngine::ValuePtr index)
{ {
auto i1 = std::dynamic_pointer_cast<ExprEngine::IntRange>(index); auto i1 = std::dynamic_pointer_cast<ExprEngine::IntRange>(index);
@ -602,8 +609,10 @@ static ExprEngine::ValuePtr executeAssign(const Token *tok, Data &data)
static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data) static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data)
{ {
std::vector<ExprEngine::ValuePtr> argValues;
for (const Token *argtok : getArguments(tok)) { for (const Token *argtok : getArguments(tok)) {
auto val = executeExpression(argtok, data); auto val = executeExpression(argtok, data);
argValues.push_back(val);
if (!argtok->valueType() || (argtok->valueType()->constness & 1) == 1) if (!argtok->valueType() || (argtok->valueType()->constness & 1) == 1)
continue; continue;
if (auto arrayValue = std::dynamic_pointer_cast<ExprEngine::ArrayValue>(val)) { if (auto arrayValue = std::dynamic_pointer_cast<ExprEngine::ArrayValue>(val)) {
@ -619,6 +628,20 @@ static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data)
data.memory[addressOf->varId] = getValueRangeFromValueType(data.getNewSymbolName(), &vt, *data.settings); data.memory[addressOf->varId] = getValueRangeFromValueType(data.getNewSymbolName(), &vt, *data.settings);
} }
} }
// TODO Fix this hardcoding..
if (Token::simpleMatch(tok->astOperand1(), "calloc (") && argValues.size() == 2 && argValues[0] && argValues[1]) {
auto bufferSize = std::make_shared<ExprEngine::BinOpResult>("*", argValues[0], argValues[1]);
ExprEngine::BinOpResult::IntOrFloatValue minValue, maxValue;
bufferSize->getRange(&minValue, &maxValue);
if (!minValue.isFloat()) {
auto buffer = std::make_shared<ExprEngine::ArrayValue>(data.getNewSymbolName(), minValue.intValue, maxValue.intValue);
buffer->clear();
call(data.callbacks, tok, buffer);
return buffer;
}
}
auto val = getValueRangeFromValueType(data.getNewSymbolName(), tok->valueType(), *data.settings); auto val = getValueRangeFromValueType(data.getNewSymbolName(), tok->valueType(), *data.settings);
call(data.callbacks, tok, val); call(data.callbacks, tok, val);
return val; return val;
@ -764,7 +787,7 @@ static void execute(const Token *start, const Token *end, Data &data)
data.trackProgramState(tok); data.trackProgramState(tok);
if (tok->variable() && tok->variable()->nameToken() == tok) { if (tok->variable() && tok->variable()->nameToken() == tok) {
if (tok->variable()->isArray() && tok->variable()->dimensions().size() == 1 && tok->variable()->dimensions()[0].known) { if (tok->variable()->isArray() && tok->variable()->dimensions().size() == 1 && tok->variable()->dimensions()[0].known) {
data.memory[tok->varId()] = std::make_shared<ExprEngine::ArrayValue>(data.getNewSymbolName(), tok->variable()->dimension(0)); data.memory[tok->varId()] = std::make_shared<ExprEngine::ArrayValue>(data.getNewSymbolName(), tok->variable()->dimension(0), tok->variable()->dimension(0));
} }
if (Token::Match(tok, "%name% [")) if (Token::Match(tok, "%name% ["))
tok = tok->linkAt(1); tok = tok->linkAt(1);

View File

@ -158,9 +158,15 @@ namespace ExprEngine {
public: public:
const int MAXSIZE = 0x100000; const int MAXSIZE = 0x100000;
ArrayValue(const std::string &name, size_t size) ArrayValue(const std::string &name, int minSize, int maxSize)
: Value(name) { : Value(name)
data.resize((size < MAXSIZE) ? size : MAXSIZE, , minSize(minSize)
, maxSize(maxSize) {
if (minSize < 1)
minSize = 1;
// Known size..
if (minSize == maxSize)
data.resize((minSize < MAXSIZE) ? minSize : MAXSIZE,
std::make_shared<UninitValue>()); std::make_shared<UninitValue>());
} }
@ -170,9 +176,12 @@ namespace ExprEngine {
std::string getRange() const override; std::string getRange() const override;
void assign(ValuePtr index, ValuePtr value); void assign(ValuePtr index, ValuePtr value);
void clear();
ValuePtr read(ValuePtr index); ValuePtr read(ValuePtr index);
std::vector<ValuePtr> data; std::vector<ValuePtr> data;
int minSize;
int maxSize;
}; };
class StringLiteralValue: public Value { class StringLiteralValue: public Value {

View File

@ -36,6 +36,8 @@ private:
TEST_CASE(argSmartPointer); TEST_CASE(argSmartPointer);
TEST_CASE(argStruct); TEST_CASE(argStruct);
TEST_CASE(dynamicAllocation1);
TEST_CASE(expr1); TEST_CASE(expr1);
TEST_CASE(expr2); TEST_CASE(expr2);
TEST_CASE(expr3); TEST_CASE(expr3);
@ -110,6 +112,10 @@ private:
"void f(struct S s) { return s.a + s.b; }", "s.a+s.b")); "void f(struct S s) { return s.a + s.b; }", "s.a+s.b"));
} }
void dynamicAllocation1() {
ASSERT_EQUALS("[0]", getRange("char *f() { char *p = calloc(1,1); return p; }", "p"));
}
void expr1() { void expr1() {
ASSERT_EQUALS("-32768:32767", getRange("void f(short x) { a = x; }", "x")); ASSERT_EQUALS("-32768:32767", getRange("void f(short x) { a = x; }", "x"));
} }