aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-06-01 23:45:55 +0800
committerchriseth <c@ethdev.com>2015-06-01 23:45:55 +0800
commitd309c3c76827606c4cabd5660035df394a16b601 (patch)
tree5868b922ff18bec1cdc4404c810ec5b00bb3bc31
parentbeab869e1443a9ef8c4bbf27affda0265e8d1947 (diff)
parentda4cd45a85c1b3fe7b72ca53ba4263a309d40ed1 (diff)
downloaddexon-solidity-d309c3c76827606c4cabd5660035df394a16b601.tar.gz
dexon-solidity-d309c3c76827606c4cabd5660035df394a16b601.tar.zst
dexon-solidity-d309c3c76827606c4cabd5660035df394a16b601.zip
Merge pull request #1975 from LianaHus/sol_EVMExceptions
"error jump" instead of STOP instraction in case of exception
-rw-r--r--Assembly.cpp32
-rw-r--r--Assembly.h6
-rw-r--r--AssemblyItem.h2
-rw-r--r--ControlFlowGraph.cpp8
4 files changed, 34 insertions, 14 deletions
diff --git a/Assembly.cpp b/Assembly.cpp
index 8c659188..a9ee9619 100644
--- a/Assembly.cpp
+++ b/Assembly.cpp
@@ -127,7 +127,10 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
_out << " PUSH \"" << m_strings.at((h256)i.data()) << "\"";
break;
case PushTag:
- _out << " PUSH [tag" << dec << i.data() << "]";
+ if (i.data() == 0)
+ _out << " PUSH [ErrorTag]";
+ else
+ _out << " PUSH [tag" << dec << i.data() << "]";
break;
case PushSub:
_out << " PUSH [$" << h256(i.data()).abridged() << "]";
@@ -207,8 +210,12 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
createJsonValue("PUSH tag", i.getLocation().start, i.getLocation().end, m_strings.at((h256)i.data())));
break;
case PushTag:
- collection.append(
- createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data())));
+ if (i.data() == 0)
+ collection.append(
+ createJsonValue("PUSH [ErrorTag]", i.getLocation().start, i.getLocation().end, ""));
+ else
+ collection.append(
+ createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data())));
break;
case PushSub:
collection.append(
@@ -226,7 +233,7 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
collection.append(
createJsonValue("tag", i.getLocation().start, i.getLocation().end, string(i.data())));
collection.append(
- createJsonValue("JUMDEST", i.getLocation().start, i.getLocation().end));
+ createJsonValue("JUMPDEST", i.getLocation().start, i.getLocation().end));
break;
case PushData:
collection.append(createJsonValue("PUSH data", i.getLocation().start, i.getLocation().end, toStringInHex(i.data())));
@@ -387,6 +394,11 @@ bytes Assembly::assemble() const
// m_data must not change from here on
for (AssemblyItem const& i: m_items)
+ {
+ // store position of the invalid jump destination
+ if (i.type() != Tag && tagPos[0] == 0)
+ tagPos[0] = ret.size();
+
switch (i.type())
{
case Operation:
@@ -448,17 +460,23 @@ bytes Assembly::assemble() const
}
case Tag:
tagPos[(unsigned)i.data()] = ret.size();
+ assertThrow(i.data() != 0, AssemblyException, "");
ret.push_back((byte)Instruction::JUMPDEST);
break;
default:
BOOST_THROW_EXCEPTION(InvalidOpcode());
}
-
+ }
for (auto const& i: tagRef)
{
bytesRef r(ret.data() + i.first, bytesPerTag);
- //@todo in the failure case, we could use the position of the invalid jumpdest
- toBigEndian(i.second < tagPos.size() ? tagPos[i.second] : (1 << (8 * bytesPerTag)) - 1, r);
+ auto tag = i.second;
+ if (tag >= tagPos.size())
+ tag = 0;
+ if (tag == 0)
+ assertThrow(tagPos[tag] != 0, AssemblyException, "");
+
+ toBigEndian(tagPos[tag], r);
}
if (!m_data.empty())
diff --git a/Assembly.h b/Assembly.h
index b4850f7d..3c82125a 100644
--- a/Assembly.h
+++ b/Assembly.h
@@ -67,6 +67,8 @@ public:
AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); 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; }
+ AssemblyItem errorTag() { return AssemblyItem(PushTag, 0); }
+
template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
AssemblyItems const& getItems() const { return m_items; }
AssemblyItem const& back() const { return m_items.back(); }
@@ -97,7 +99,6 @@ public:
const StringMap &_sourceCodes = StringMap(),
bool _inJsonFormat = false
) const;
-
protected:
std::string getLocationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const;
void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) BOOST_THROW_EXCEPTION(InvalidDeposit()); }
@@ -109,7 +110,8 @@ private:
Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const;
protected:
- unsigned m_usedTags = 0;
+ // 0 is reserved for exception
+ unsigned m_usedTags = 1;
AssemblyItems m_items;
mutable std::map<h256, bytes> m_data;
std::vector<Assembly> m_subs;
diff --git a/AssemblyItem.h b/AssemblyItem.h
index 7d8f3d9a..9eca0a7d 100644
--- a/AssemblyItem.h
+++ b/AssemblyItem.h
@@ -65,7 +65,7 @@ public:
/// @returns the instruction of this item (only valid if type() == Operation)
Instruction instruction() const { return Instruction(byte(m_data)); }
- /// @returns true iff the type and data of the items are equal.
+ /// @returns true if the type and data of the items are equal.
bool operator==(AssemblyItem const& _other) const { return m_type == _other.m_type && m_data == _other.m_data; }
bool operator!=(AssemblyItem const& _other) const { return !operator==(_other); }
/// Less-than operator compatible with operator==.
diff --git a/ControlFlowGraph.cpp b/ControlFlowGraph.cpp
index 3566bdb1..41a53aa8 100644
--- a/ControlFlowGraph.cpp
+++ b/ControlFlowGraph.cpp
@@ -226,7 +226,10 @@ void ControlFlowGraph::gatherKnowledge()
//@todo we might have to do something like incrementing the sequence number for each JUMPDEST
assertThrow(!!workQueue.back().first, OptimizerException, "");
if (!m_blocks.count(workQueue.back().first))
+ {
+ workQueue.pop_back();
continue; // too bad, we do not know the tag, probably an invalid jump
+ }
BasicBlock& block = m_blocks.at(workQueue.back().first);
KnownStatePointer state = workQueue.back().second;
workQueue.pop_back();
@@ -257,10 +260,7 @@ void ControlFlowGraph::gatherKnowledge()
);
state->feedItem(m_items.at(pc++));
- if (tags.empty() || std::any_of(tags.begin(), tags.end(), [&](u256 const& _tag)
- {
- return !m_blocks.count(BlockId(_tag));
- }))
+ if (tags.empty())
{
if (!unknownJumpEncountered)
{