Fix bug about incorrect caching on Keccak256 hashes

This commit is contained in:
hrkrshnn 2021-03-22 09:39:19 +01:00 committed by chriseth
parent 21e365321d
commit 2ecb20589b
2 changed files with 17 additions and 10 deletions

View File

@ -166,7 +166,10 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
// We could be a bit more fine-grained here (CALL only invalidates part of // We could be a bit more fine-grained here (CALL only invalidates part of
// memory, etc), but we do not for now. // memory, etc), but we do not for now.
if (invMem) if (invMem)
{
resetMemory(); resetMemory();
resetKnownKeccak256Hashes();
}
if (invStor) if (invStor)
resetStorage(); resetStorage();
if (invMem || invStor) if (invMem || invStor)
@ -376,18 +379,18 @@ KnownState::Id KnownState::applyKeccak256(
// unknown or too large length // unknown or too large length
if (!l || *l > 128) if (!l || *l > 128)
return m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber); return m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber);
unsigned length = unsigned(*l);
vector<Id> arguments; vector<Id> arguments;
for (u256 i = 0; i < *l; i += 32) for (unsigned i = 0; i < length; i += 32)
{ {
Id slot = m_expressionClasses->find( Id slot = m_expressionClasses->find(
AssemblyItem(Instruction::ADD, _location), AssemblyItem(Instruction::ADD, _location),
{_start, m_expressionClasses->find(i)} {_start, m_expressionClasses->find(u256(i))}
); );
arguments.push_back(loadFromMemory(slot, _location)); arguments.push_back(loadFromMemory(slot, _location));
} }
if (m_knownKeccak256Hashes.count(arguments)) if (m_knownKeccak256Hashes.count({arguments, length}))
return m_knownKeccak256Hashes.at(arguments); return m_knownKeccak256Hashes.at({arguments, length});
Id v; Id v;
// If all arguments are known constants, compute the Keccak-256 here // If all arguments are known constants, compute the Keccak-256 here
if (all_of(arguments.begin(), arguments.end(), [this](Id _a) { return !!m_expressionClasses->knownConstant(_a); })) if (all_of(arguments.begin(), arguments.end(), [this](Id _a) { return !!m_expressionClasses->knownConstant(_a); }))
@ -395,12 +398,12 @@ KnownState::Id KnownState::applyKeccak256(
bytes data; bytes data;
for (Id a: arguments) for (Id a: arguments)
data += util::toBigEndian(*m_expressionClasses->knownConstant(a)); data += util::toBigEndian(*m_expressionClasses->knownConstant(a));
data.resize(static_cast<size_t>(*l)); data.resize(length);
v = m_expressionClasses->find(AssemblyItem(u256(util::keccak256(data)), _location)); v = m_expressionClasses->find(AssemblyItem(u256(util::keccak256(data)), _location));
} }
else else
v = m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber); v = m_expressionClasses->find(keccak256Item, {_start, _length}, true, m_sequenceNumber);
return m_knownKeccak256Hashes[arguments] = v; return m_knownKeccak256Hashes[{arguments, length}] = v;
} }
set<u256> KnownState::tagsInExpression(KnownState::Id _expressionId) set<u256> KnownState::tagsInExpression(KnownState::Id _expressionId)

View File

@ -110,10 +110,12 @@ public:
void resetStorage() { m_storageContent.clear(); } void resetStorage() { m_storageContent.clear(); }
/// Resets any knowledge about storage. /// Resets any knowledge about storage.
void resetMemory() { m_memoryContent.clear(); } void resetMemory() { m_memoryContent.clear(); }
/// Resets known Keccak-256 hashes
void resetKnownKeccak256Hashes() { m_knownKeccak256Hashes.clear(); }
/// Resets any knowledge about the current stack. /// Resets any knowledge about the current stack.
void resetStack() { m_stackElements.clear(); m_stackHeight = 0; } void resetStack() { m_stackElements.clear(); m_stackHeight = 0; }
/// Resets any knowledge. /// Resets any knowledge.
void reset() { resetStorage(); resetMemory(); resetStack(); } void reset() { resetStorage(); resetMemory(); resetKnownKeccak256Hashes(); resetStack(); }
unsigned sequenceNumber() const { return m_sequenceNumber; } unsigned sequenceNumber() const { return m_sequenceNumber; }
@ -183,8 +185,10 @@ private:
/// Knowledge about memory content. Keys are memory addresses, note that the values overlap /// Knowledge about memory content. Keys are memory addresses, note that the values overlap
/// and are not contained here if they are not completely known. /// and are not contained here if they are not completely known.
std::map<Id, Id> m_memoryContent; std::map<Id, Id> m_memoryContent;
/// Keeps record of all Keccak-256 hashes that are computed. /// Keeps record of all Keccak-256 hashes that are computed. The first parameter in the
std::map<std::vector<Id>, Id> m_knownKeccak256Hashes; /// std::pair corresponds to memory content and the second parameter corresponds to the length
/// that is accessed.
std::map<std::pair<std::vector<Id>, unsigned>, Id> m_knownKeccak256Hashes;
/// Structure containing the classes of equivalent expressions. /// Structure containing the classes of equivalent expressions.
std::shared_ptr<ExpressionClasses> m_expressionClasses; std::shared_ptr<ExpressionClasses> m_expressionClasses;
/// Container for unions of tags stored on the stack. /// Container for unions of tags stored on the stack.