mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
added error jump instead of STOP instraction in case of exception
This commit is contained in:
parent
7f55e26eb8
commit
25205cb05b
28
Assembly.cpp
28
Assembly.cpp
@ -127,7 +127,10 @@ ostream& Assembly::streamAsm(ostream& _out, string const& _prefix, StringMap con
|
|||||||
_out << " PUSH \"" << m_strings.at((h256)i.data()) << "\"";
|
_out << " PUSH \"" << m_strings.at((h256)i.data()) << "\"";
|
||||||
break;
|
break;
|
||||||
case PushTag:
|
case PushTag:
|
||||||
_out << " PUSH [tag" << dec << i.data() << "]";
|
if (i.data() == 0)
|
||||||
|
_out << " PUSH [ErrorTag]";
|
||||||
|
else
|
||||||
|
_out << " PUSH [tag" << dec << i.data() << "]";
|
||||||
break;
|
break;
|
||||||
case PushSub:
|
case PushSub:
|
||||||
_out << " PUSH [$" << h256(i.data()).abridged() << "]";
|
_out << " PUSH [$" << h256(i.data()).abridged() << "]";
|
||||||
@ -207,6 +210,10 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
|
|||||||
createJsonValue("PUSH tag", i.getLocation().start, i.getLocation().end, m_strings.at((h256)i.data())));
|
createJsonValue("PUSH tag", i.getLocation().start, i.getLocation().end, m_strings.at((h256)i.data())));
|
||||||
break;
|
break;
|
||||||
case PushTag:
|
case PushTag:
|
||||||
|
if (i.data() == 0)
|
||||||
|
collection.append(
|
||||||
|
createJsonValue("PUSH [ErrorTag]", i.getLocation().start, i.getLocation().end, ""));
|
||||||
|
|
||||||
collection.append(
|
collection.append(
|
||||||
createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data())));
|
createJsonValue("PUSH [tag]", i.getLocation().start, i.getLocation().end, string(i.data())));
|
||||||
break;
|
break;
|
||||||
@ -226,7 +233,7 @@ Json::Value Assembly::streamAsmJson(ostream& _out, StringMap const& _sourceCodes
|
|||||||
collection.append(
|
collection.append(
|
||||||
createJsonValue("tag", i.getLocation().start, i.getLocation().end, string(i.data())));
|
createJsonValue("tag", i.getLocation().start, i.getLocation().end, string(i.data())));
|
||||||
collection.append(
|
collection.append(
|
||||||
createJsonValue("JUMDEST", i.getLocation().start, i.getLocation().end));
|
createJsonValue("JUMPDEST", i.getLocation().start, i.getLocation().end));
|
||||||
break;
|
break;
|
||||||
case PushData:
|
case PushData:
|
||||||
collection.append(createJsonValue("PUSH data", i.getLocation().start, i.getLocation().end, toStringInHex(i.data())));
|
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
|
// m_data must not change from here on
|
||||||
|
|
||||||
for (AssemblyItem const& i: m_items)
|
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())
|
switch (i.type())
|
||||||
{
|
{
|
||||||
case Operation:
|
case Operation:
|
||||||
@ -448,17 +460,23 @@ bytes Assembly::assemble() const
|
|||||||
}
|
}
|
||||||
case Tag:
|
case Tag:
|
||||||
tagPos[(unsigned)i.data()] = ret.size();
|
tagPos[(unsigned)i.data()] = ret.size();
|
||||||
|
assertThrow(i.data() != 0, AssemblyException, "");
|
||||||
ret.push_back((byte)Instruction::JUMPDEST);
|
ret.push_back((byte)Instruction::JUMPDEST);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BOOST_THROW_EXCEPTION(InvalidOpcode());
|
BOOST_THROW_EXCEPTION(InvalidOpcode());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (auto const& i: tagRef)
|
for (auto const& i: tagRef)
|
||||||
{
|
{
|
||||||
bytesRef r(ret.data() + i.first, bytesPerTag);
|
bytesRef r(ret.data() + i.first, bytesPerTag);
|
||||||
//@todo in the failure case, we could use the position of the invalid jumpdest
|
auto tag = i.second;
|
||||||
toBigEndian(i.second < tagPos.size() ? tagPos[i.second] : (1 << (8 * bytesPerTag)) - 1, r);
|
if (tag >= tagPos.size())
|
||||||
|
tag = 0;
|
||||||
|
if (tag == 0)
|
||||||
|
assertThrow(tagPos[tag] != 0, AssemblyException, "");
|
||||||
|
|
||||||
|
toBigEndian(tagPos[tag], r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_data.empty())
|
if (!m_data.empty())
|
||||||
|
@ -67,6 +67,8 @@ public:
|
|||||||
AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; }
|
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 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 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; }
|
template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
|
||||||
AssemblyItems const& getItems() const { return m_items; }
|
AssemblyItems const& getItems() const { return m_items; }
|
||||||
AssemblyItem const& back() const { return m_items.back(); }
|
AssemblyItem const& back() const { return m_items.back(); }
|
||||||
@ -97,7 +99,6 @@ public:
|
|||||||
const StringMap &_sourceCodes = StringMap(),
|
const StringMap &_sourceCodes = StringMap(),
|
||||||
bool _inJsonFormat = false
|
bool _inJsonFormat = false
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string getLocationFromSources(StringMap const& _sourceCodes, SourceLocation const& _location) const;
|
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()); }
|
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;
|
Json::Value createJsonValue(std::string _name, int _begin, int _end, std::string _value = std::string(), std::string _jumpType = std::string()) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned m_usedTags = 0;
|
// 0 is reserved for exception
|
||||||
|
unsigned m_usedTags = 1;
|
||||||
AssemblyItems m_items;
|
AssemblyItems m_items;
|
||||||
mutable std::map<h256, bytes> m_data;
|
mutable std::map<h256, bytes> m_data;
|
||||||
std::vector<Assembly> m_subs;
|
std::vector<Assembly> m_subs;
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
/// @returns the instruction of this item (only valid if type() == Operation)
|
/// @returns the instruction of this item (only valid if type() == Operation)
|
||||||
Instruction instruction() const { return Instruction(byte(m_data)); }
|
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 m_type == _other.m_type && m_data == _other.m_data; }
|
||||||
bool operator!=(AssemblyItem const& _other) const { return !operator==(_other); }
|
bool operator!=(AssemblyItem const& _other) const { return !operator==(_other); }
|
||||||
/// Less-than operator compatible with operator==.
|
/// Less-than operator compatible with operator==.
|
||||||
|
@ -226,7 +226,10 @@ void ControlFlowGraph::gatherKnowledge()
|
|||||||
//@todo we might have to do something like incrementing the sequence number for each JUMPDEST
|
//@todo we might have to do something like incrementing the sequence number for each JUMPDEST
|
||||||
assertThrow(!!workQueue.back().first, OptimizerException, "");
|
assertThrow(!!workQueue.back().first, OptimizerException, "");
|
||||||
if (!m_blocks.count(workQueue.back().first))
|
if (!m_blocks.count(workQueue.back().first))
|
||||||
|
{
|
||||||
|
workQueue.pop_back();
|
||||||
continue; // too bad, we do not know the tag, probably an invalid jump
|
continue; // too bad, we do not know the tag, probably an invalid jump
|
||||||
|
}
|
||||||
BasicBlock& block = m_blocks.at(workQueue.back().first);
|
BasicBlock& block = m_blocks.at(workQueue.back().first);
|
||||||
KnownStatePointer state = workQueue.back().second;
|
KnownStatePointer state = workQueue.back().second;
|
||||||
workQueue.pop_back();
|
workQueue.pop_back();
|
||||||
@ -257,10 +260,7 @@ void ControlFlowGraph::gatherKnowledge()
|
|||||||
);
|
);
|
||||||
state->feedItem(m_items.at(pc++));
|
state->feedItem(m_items.at(pc++));
|
||||||
|
|
||||||
if (tags.empty() || std::any_of(tags.begin(), tags.end(), [&](u256 const& _tag)
|
if (tags.empty())
|
||||||
{
|
|
||||||
return !m_blocks.count(BlockId(_tag));
|
|
||||||
}))
|
|
||||||
{
|
{
|
||||||
if (!unknownJumpEncountered)
|
if (!unknownJumpEncountered)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user