Skip to content

Commit

Permalink
Fix Yul stack output using standard json in the presence of warnings.
Browse files Browse the repository at this point in the history
  • Loading branch information
ekpyron authored and nikola-matic committed Sep 3, 2024
1 parent bf54bdf commit 3f6f2d3
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 14 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Bugfixes:
* SMTChecker: Fix formatting of unary minus expressions in invariants.
* SMTChecker: Fix internal compiler error when reporting proved targets for BMC engine.
* SMTChecker: Fix SMT logic error when assigning to an array of contracts or functions.
* Standard JSON Interface: For Yul input, properly produce output artifacts in case of warnings.
* TypeChecker: Fix segfault when assigning nested tuple to tuple.
* Yul IR Code Generation: Deterministic order of Yul subobjects.
* Yul Optimizer: Fix Yul source locations always referring to unoptimized source, even in optimized outputs.
Expand Down
26 changes: 12 additions & 14 deletions libsolidity/interface/StandardCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1620,7 +1620,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
std::string const& sourceContents = _inputsAndSettings.sources.begin()->second;

// Inconsistent state - stop here to receive error reports from users
if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty())
if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors())
{
output["errors"].emplace_back(formatError(
Error::Type::InternalCompilerError,
Expand All @@ -1630,22 +1630,20 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
return output;
}

if (!stack.errors().empty())
for (auto const& error: stack.errors())
{
for (auto const& error: stack.errors())
{
auto err = std::dynamic_pointer_cast<Error const>(error);
auto err = std::dynamic_pointer_cast<Error const>(error);

output["errors"].emplace_back(formatErrorWithException(
stack,
*error,
err->type(),
"general",
""
));
}
return output;
output["errors"].emplace_back(formatErrorWithException(
stack,
*error,
err->type(),
"general",
""
));
}
if (stack.hasErrors())
return output;

std::string contractName = stack.parserResult()->name;

Expand Down
1 change: 1 addition & 0 deletions libyul/YulStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class YulStack: public langutil::CharStreamProvider

/// @returns the errors generated during parsing, analysis (and potentially assembly).
langutil::ErrorList const& errors() const { return m_errors; }
bool hasErrors() const { return m_errorReporter.hasErrors(); }

/// Pretty-print the input after having parsed it.
std::string print(
Expand Down
20 changes: 20 additions & 0 deletions test/cmdlineTests/standard_yul_output_warning/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"language": "Yul",
"sources":
{
"C":
{
"content": "{ let x := tload(0) tstore(add(x, 1), 0) }"
}
},
"settings":
{
"outputSelection":
{
"*": {
"*": ["evm.bytecode", "evm.assembly", "irOptimized"],
"": [ "*" ]
}
}
}
}
61 changes: 61 additions & 0 deletions test/cmdlineTests/standard_yul_output_warning/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"contracts": {
"C": {
"object": {
"evm": {
"assembly": " /* \"C\":99:100 */
0x00
/* \"C\":95:96 */
0x01
/* \"C\":60:68 */
dup2
tload
/* \"C\":88:97 */
add
/* \"C\":81:101 */
tstore
/* \"C\":27:117 */
stop
",
"bytecode": {
"functionDebugData": {},
"generatedSources": [],
"linkReferences": {},
"object": "<BYTECODE REMOVED>",
"opcodes":"<OPCODES REMOVED>",
"sourceMap":"<SOURCEMAP REMOVED>"
}
},
"irOptimized": "object \"object\" {
code {
{
let x := tload(0)
tstore(add(x, 1), 0)
}
}
}
"
}
}
},
"errors": [
{
"component": "general",
"formattedMessage": "Warning: Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe.
--> C:1:21:
|
1 | { let x := tload(0) tstore(add(x, 1), 0) }
| ^^^^^^

",
"message": "Transient storage as defined by EIP-1153 can break the composability of smart contracts: Since transient storage is cleared only at the end of the transaction and not at the end of the outermost call frame to the contract within a transaction, your contract may unintentionally misbehave when invoked multiple times in a complex transaction. To avoid this, be sure to clear all transient storage at the end of any call to your contract. The use of transient storage for reentrancy guards that are cleared at the end of the call is safe.",
"severity": "warning",
"sourceLocation": {
"end": 26,
"file": "C",
"start": 20
},
"type": "Warning"
}
]
}

0 comments on commit 3f6f2d3

Please sign in to comment.