Add markAsInvalid to the various assemblies.

This commit is contained in:
Daniel Kirchner 2020-07-15 11:32:34 +02:00 committed by chriseth
parent 579e4b5a69
commit 92cd1ddb7d
9 changed files with 31 additions and 5 deletions

View File

@ -521,6 +521,7 @@ map<u256, u256> Assembly::optimiseInternal(
LinkerObject const& Assembly::assemble() const LinkerObject const& Assembly::assemble() const
{ {
assertThrow(!m_invalid, AssemblyException, "Attempted to assemble invalid Assembly object.");
// Return the already assembled object, if present. // Return the already assembled object, if present.
if (!m_assembledObject.bytecode.empty()) if (!m_assembledObject.bytecode.empty())
return m_assembledObject; return m_assembledObject;

View File

@ -142,6 +142,9 @@ public:
std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>() std::map<std::string, unsigned> const& _sourceIndices = std::map<std::string, unsigned>()
) const; ) const;
/// Mark this assembly as invalid. Calling ``assemble`` on it will throw.
void markAsInvalid() { m_invalid = true; }
protected: protected:
/// Does the same operations as @a optimise, but should only be applied to a sub and /// Does the same operations as @a optimise, but should only be applied to a sub and
/// returns the replaced tags. Also takes an argument containing the tags of this assembly /// returns the replaced tags. Also takes an argument containing the tags of this assembly
@ -161,6 +164,7 @@ private:
); );
static std::string toStringInHex(u256 _value); static std::string toStringInHex(u256 _value);
bool m_invalid = false;
protected: protected:
/// 0 is reserved for exception /// 0 is reserved for exception
unsigned m_usedTags = 1; unsigned m_usedTags = 1;

View File

@ -111,6 +111,9 @@ public:
virtual void appendImmutable(std::string const& _identifier) = 0; virtual void appendImmutable(std::string const& _identifier) = 0;
/// Appends an assignment to an immutable variable. /// Appends an assignment to an immutable variable.
virtual void appendImmutableAssignment(std::string const& _identifier) = 0; virtual void appendImmutableAssignment(std::string const& _identifier) = 0;
/// Mark this assembly as invalid. Any attempt to request bytecode from it should throw.
virtual void markAsInvalid() = 0;
}; };
enum class IdentifierContext { LValue, RValue, VariableDeclaration }; enum class IdentifierContext { LValue, RValue, VariableDeclaration };

View File

@ -182,6 +182,11 @@ void EthAssemblyAdapter::appendImmutableAssignment(std::string const& _identifie
m_assembly.appendImmutableAssignment(_identifier); m_assembly.appendImmutableAssignment(_identifier);
} }
void EthAssemblyAdapter::markAsInvalid()
{
m_assembly.markAsInvalid();
}
EthAssemblyAdapter::LabelID EthAssemblyAdapter::assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag) EthAssemblyAdapter::LabelID EthAssemblyAdapter::assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag)
{ {
u256 id = _tag.data(); u256 id = _tag.data();

View File

@ -64,6 +64,8 @@ public:
void appendImmutable(std::string const& _identifier) override; void appendImmutable(std::string const& _identifier) override;
void appendImmutableAssignment(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override;
void markAsInvalid() override;
private: private:
static LabelID assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag); static LabelID assemblyTagToIdentifier(evmasm::AssemblyItem const& _tag);
void appendJumpInstruction(evmasm::Instruction _instruction, JumpType _jumpType); void appendJumpInstruction(evmasm::Instruction _instruction, JumpType _jumpType);

View File

@ -156,6 +156,7 @@ void EVMAssembly::appendReturnsub(int _returns, int _stackDiffAfter)
evmasm::LinkerObject EVMAssembly::finalize() evmasm::LinkerObject EVMAssembly::finalize()
{ {
yulAssert(!m_invalid, "Attempted to finalize invalid assembly object.");
size_t bytecodeSize = m_bytecode.size(); size_t bytecodeSize = m_bytecode.size();
for (auto const& ref: m_assemblySizePositions) for (auto const& ref: m_assemblySizePositions)
updateReference(ref, assemblySizeReferenceSize, u256(bytecodeSize)); updateReference(ref, assemblySizeReferenceSize, u256(bytecodeSize));

View File

@ -86,6 +86,8 @@ public:
void appendImmutable(std::string const& _identifier) override; void appendImmutable(std::string const& _identifier) override;
void appendImmutableAssignment(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override;
void markAsInvalid() override { m_invalid = true; }
/// Resolves references inside the bytecode and returns the linker object. /// Resolves references inside the bytecode and returns the linker object.
evmasm::LinkerObject finalize(); evmasm::LinkerObject finalize();
@ -102,6 +104,7 @@ private:
std::map<LabelID, size_t> m_labelPositions; std::map<LabelID, size_t> m_labelPositions;
std::map<size_t, LabelID> m_labelReferences; std::map<size_t, LabelID> m_labelReferences;
std::vector<size_t> m_assemblySizePositions; std::vector<size_t> m_assemblySizePositions;
bool m_invalid = false;
}; };
} }

View File

@ -237,6 +237,7 @@ void CodeTransform::stackError(StackTooDeepError _error, int _targetStackHeight)
m_assembly.appendConstant(u256(0)); m_assembly.appendConstant(u256(0));
// Store error. // Store error.
m_stackErrors.emplace_back(std::move(_error)); m_stackErrors.emplace_back(std::move(_error));
m_assembly.markAsInvalid();
} }
void CodeTransform::operator()(Assignment const& _assignment) void CodeTransform::operator()(Assignment const& _assignment)
@ -448,11 +449,15 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
m_context m_context
); );
subTransform(_function.body); subTransform(_function.body);
for (auto& stackError: subTransform.m_stackErrors) if (!subTransform.m_stackErrors.empty())
{ {
if (stackError.functionName.empty()) m_assembly.markAsInvalid();
stackError.functionName = _function.name; for (StackTooDeepError& stackError: subTransform.m_stackErrors)
m_stackErrors.emplace_back(std::move(stackError)); {
if (stackError.functionName.empty())
stackError.functionName = _function.name;
m_stackErrors.emplace_back(std::move(stackError));
}
} }
m_assembly.appendLabel(m_context->functionExitPoints.top().label); m_assembly.appendLabel(m_context->functionExitPoints.top().label);
@ -718,7 +723,7 @@ size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString
to_string(heightDiff - limit) + to_string(heightDiff - limit) +
" slot(s) too deep inside the stack." " slot(s) too deep inside the stack."
); );
// TODO: maybe make this return something special that results in producing INVALID instead. m_assembly.markAsInvalid();
return _forSwap ? 2 : 1; return _forSwap ? 2 : 1;
} }
return heightDiff; return heightDiff;

View File

@ -74,6 +74,8 @@ public:
void appendImmutable(std::string const& _identifier) override; void appendImmutable(std::string const& _identifier) override;
void appendImmutableAssignment(std::string const& _identifier) override; void appendImmutableAssignment(std::string const& _identifier) override;
void markAsInvalid() override {}
private: private:
bool m_evm15 = false; ///< if true, switch to evm1.5 mode bool m_evm15 = false; ///< if true, switch to evm1.5 mode
int m_stackHeight = 0; int m_stackHeight = 0;