Skip to content

Commit

Permalink
fix: fix issue when the receive function calls an internal function. c…
Browse files Browse the repository at this point in the history
…lose #17
  • Loading branch information
charles-liu committed Apr 2, 2022
1 parent ef41f32 commit 2721f9c
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 13 deletions.
5 changes: 3 additions & 2 deletions libevmasm/Assembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void Assembly::appendDebugInfo(string const& _debugInfo)
auto iter = m_debugInfos.find(pos);
auto message = iter == m_debugInfos.end() ? _debugInfo : iter->second + "\n // " + _debugInfo;
m_debugInfos[pos] = message;
if (m_verbose) std::clog << " [Assembly] " << _debugInfo << std::endl;
}

unsigned Assembly::bytesRequired(unsigned subTagSize) const
Expand Down Expand Up @@ -757,10 +758,10 @@ LinkerObject const& Assembly::assemble() const
subId == numeric_limits<size_t>::max() ?
m_tagPositionsInBytecode :
m_subs[subId]->m_tagPositionsInBytecode;
assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag: "+
assertThrow(tagId < tagPositions.size(), AssemblyException, "Reference to non-existing tag: tag_"+
toString(tagId));
size_t pos = tagPositions[tagId];
assertThrow(pos != numeric_limits<size_t>::max(), AssemblyException, "Reference to tag without position: "+
assertThrow(pos != numeric_limits<size_t>::max(), AssemblyException, "Reference to tag without position: tag_"+
toString(tagId));
assertThrow(util::bytesRequired(pos) <= bytesPerTag, AssemblyException, "Tag too large for reserved space.");
bytesRef r(ret.bytecode.data() + i.first, bytesPerTag);
Expand Down
7 changes: 4 additions & 3 deletions libevmasm/Assembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ using AssemblyPointer = std::shared_ptr<Assembly>;
class Assembly
{
public:
AssemblyItem newTag(std::string const& _description = "") { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++, langutil::SourceLocation(), _description); }
AssemblyItem newPushTag(std::string const& _description = "") { assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++, langutil::SourceLocation(), _description); }
AssemblyItem newTag(std::string const& _description = "") { appendDebugInfo("newTag tag_" + std::to_string(m_usedTags+1) + ", desc: " + _description); assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(Tag, m_usedTags++, langutil::SourceLocation(), _description); }
AssemblyItem newPushTag(std::string const& _description = "") { appendDebugInfo("newPushTag tag_" + std::to_string(m_usedTags+1) + ", desc: " + _description); assertThrow(m_usedTags < 0xffffffff, AssemblyException, ""); return AssemblyItem(PushTag, m_usedTags++, langutil::SourceLocation(), _description); }
/// Returns a tag identified by the given name. Creates it if it does not yet exist.
AssemblyItem namedTag(std::string const& _name);
// Solidity++: keccak256 -> blake2b
Expand Down Expand Up @@ -60,7 +60,7 @@ class Assembly
void appendDebugInfo(std::string const& _debugInfo);

AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; }
AssemblyItem appendJumpI(std::string const& _description = "") { auto ret = append(newPushTag(_description)); append(Instruction::JUMPI); return ret; }
AssemblyItem appendJumpI(std::string const& _description = "") { auto ret = append(newPushTag(_description)); append(Instruction::JUMPI); appendDebugInfo("Jump to "+ret.toAssemblyText(*this)); return ret; }
AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; }
AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; }

Expand Down Expand Up @@ -188,6 +188,7 @@ class Assembly

public:
size_t m_currentModifierDepth = 0;
bool m_verbose = false;
};

inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a)
Expand Down
4 changes: 3 additions & 1 deletion libsolidity/codegen/CompilerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ void CompilerContext::appendMissingLowLevelFunctions()
m_lowLevelFunctionGenerationQueue.pop();

setStackOffset(static_cast<int>(inArgs) + 1);
*this << m_lowLevelFunctions.at(name).tag();
auto tag = m_lowLevelFunctions.at(name).tag();
*this << tag;
debug("CompilerContext::appendMissingLowLevelFunctions: " + name + "->" + tag.toAssemblyText(*m_asm));
generator(*this);
CompilerUtils(*this).moveToStackTop(outArgs);
appendJump(evmasm::AssemblyItem::JumpType::OutOfFunction);
Expand Down
9 changes: 5 additions & 4 deletions libsolidity/codegen/CompilerContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class CompilerContext
{
if (m_runtimeContext)
m_runtimeSub = size_t(m_asm->newSub(m_runtimeContext->m_asm).data());
m_asm->m_verbose = _verbose;
}

langutil::EVMVersion const& evmVersion() const { return m_evmVersion; }
Expand Down Expand Up @@ -175,11 +176,11 @@ class CompilerContext
std::pair<u256, unsigned> storageLocationOfVariable(Declaration const& _declaration) const;

/// Appends a JUMPI instruction to a new tag and @returns the tag
evmasm::AssemblyItem appendConditionalJump(std::string const& _description = "") { return m_asm->appendJumpI(_description).tag(); }
evmasm::AssemblyItem appendConditionalJump(std::string const& _description = "") { debug("appendConditionalJump "); return m_asm->appendJumpI(_description).tag(); }
/// Appends a JUMPI instruction to @a _tag
CompilerContext& appendConditionalJumpTo(evmasm::AssemblyItem const& _tag) { m_asm->appendJumpI(_tag); return *this; }
CompilerContext& appendConditionalJumpTo(evmasm::AssemblyItem const& _tag) { debug("appendConditionalJumpTo "+_tag.toAssemblyText(*m_asm)); m_asm->appendJumpI(_tag); return *this; }
/// Appends a JUMP to a new tag and @returns the tag
evmasm::AssemblyItem appendJumpToNew() { return m_asm->appendJump().tag(); }
evmasm::AssemblyItem appendJumpToNew() { debug("appendJumpToNew "); return m_asm->appendJump().tag(); }
/// Appends a JUMP to a tag already on the stack
CompilerContext& appendJump(evmasm::AssemblyItem::JumpType _jumpType = evmasm::AssemblyItem::JumpType::Ordinary);
/// Appends code to revert with a Panic(uint256) error.
Expand All @@ -200,7 +201,7 @@ class CompilerContext
CompilerContext& appendJumpTo(
evmasm::AssemblyItem const& _tag,
evmasm::AssemblyItem::JumpType _jumpType = evmasm::AssemblyItem::JumpType::Ordinary
) { *m_asm << _tag.pushTag(); return appendJump(_jumpType); }
) { debug("appendJumpTo "+_tag.toAssemblyText(*m_asm)); *m_asm << _tag.pushTag(); return appendJump(_jumpType); }
/// Appends pushing of a new tag and @returns the new tag.
evmasm::AssemblyItem pushNewTag(std::string const& _description = "") { return m_asm->append(m_asm->newPushTag(_description)).tag(); }
/// @returns a new tag without pushing any opcodes or data
Expand Down
12 changes: 9 additions & 3 deletions libsolidity/codegen/ContractCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont

m_runtimeCompiler->appendMissingFunctions();
m_runtimeCompiler->appendFunctionSelector(_contract);
// Solidity++: Do it again to compile the missing functions which are called in the receive/fallback functions
m_runtimeCompiler->appendMissingFunctions();

// Solidity++: Moved from appendMissingFunctions()
m_runtimeCompiler->m_context.appendYulUtilityFunctions(m_optimiserSettings);
Expand Down Expand Up @@ -235,10 +237,12 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract)
solAssert(_contract.isLibrary(), "Tried to deploy contract as library.");

appendMissingFunctions();
m_runtimeCompiler->appendMissingFunctions();

// Solidity++: Moved from compileContract()
m_runtimeCompiler->appendMissingFunctions();
m_runtimeCompiler->appendFunctionSelector(_contract);
// Solidity++: Do it again to compile the missing functions which are called in the receive/fallback functions
m_runtimeCompiler->appendMissingFunctions();

// Solidity++: Moved from appendMissingFunctions()
m_runtimeCompiler->m_context.appendYulUtilityFunctions(m_optimiserSettings);
Expand Down Expand Up @@ -1467,7 +1471,7 @@ void ContractCompiler::appendMissingFunctions()
void ContractCompiler::appendModifierOrFunctionCode()
{
solAssert(m_currentFunction, "");
auto debugInfo = "ContractCompiler::appendModifierOrFunctionCode() for " + m_currentFunction->name();
auto debugInfo = "ContractCompiler::appendModifierOrFunctionCode() for " + m_currentFunction->location().text();
debug(debugInfo);
m_context.appendDebugInfo(debugInfo);
unsigned stackSurplus = 0;
Expand Down Expand Up @@ -1542,8 +1546,10 @@ void ContractCompiler::appendModifierOrFunctionCode()

solAssert(!m_returnTags.empty(), "");
m_context.appendDebugInfo("start processing return data");
m_context << m_returnTags.back().first;
auto returnTag = m_returnTags.back().first;
m_context << returnTag;
m_returnTags.pop_back();
debug("Return tag: " + returnTag.toAssemblyText(m_context.assembly()));

CompilerUtils(m_context).popStackSlots(stackSurplus);
for (auto var: addedVariables)
Expand Down

0 comments on commit 2721f9c

Please sign in to comment.