Skip to content

Commit dd95291

Browse files
committed
prepare_report: Handle internal compiler errors in Standard JSON as errors, not missing bytecode
1 parent ce72134 commit dd95291

9 files changed

+176
-2
lines changed

scripts/bytecodecompare/prepare_report.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,25 @@ for (const optimize of [false, true])
2424

2525
const result = JSON.parse(compiler.compile(JSON.stringify(input)))
2626

27+
let internalCompilerError = false
28+
if ('errors' in result)
29+
{
30+
for (const error of result['errors'])
31+
// JSON interface still returns contract metadata in case of an internal compiler error while
32+
// CLI interface does not. To make reports comparable we must force this case to be detected as
33+
// an error in both cases.
34+
if (['UnimplementedFeatureError', 'CompilerError', 'CodeGenerationError'].includes(error['type']))
35+
{
36+
internalCompilerError = true
37+
break
38+
}
39+
}
40+
2741
if (
2842
!('contracts' in result) ||
2943
Object.keys(result['contracts']).length === 0 ||
30-
Object.keys(result['contracts']).every(file => Object.keys(result['contracts'][file]).length === 0)
44+
Object.keys(result['contracts']).every(file => Object.keys(result['contracts'][file]).length === 0) ||
45+
internalCompilerError
3146
)
3247
// NOTE: do not exit here because this may be run on source which cannot be compiled
3348
console.log(filename + ': <ERROR>')

scripts/bytecodecompare/prepare_report.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,19 @@ def load_source(path: Union[Path, str]) -> str:
6666
def parse_standard_json_output(source_file_name: Path, standard_json_output: str) -> FileReport:
6767
decoded_json_output = json.loads(standard_json_output.strip())
6868

69+
# JSON interface still returns contract metadata in case of an internal compiler error while
70+
# CLI interface does not. To make reports comparable we must force this case to be detected as
71+
# an error in both cases.
72+
internal_compiler_error = any(
73+
error['type'] in ['UnimplementedFeatureError', 'CompilerError', 'CodeGenerationError']
74+
for error in decoded_json_output.get('errors', {})
75+
)
76+
6977
if (
7078
'contracts' not in decoded_json_output or
7179
len(decoded_json_output['contracts']) == 0 or
72-
all(len(file_results) == 0 for file_name, file_results in decoded_json_output['contracts'].items())
80+
all(len(file_results) == 0 for file_name, file_results in decoded_json_output['contracts'].items()) or
81+
internal_compiler_error
7382
):
7483
return FileReport(file_name=source_file_name, contract_reports=None)
7584

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
2+
--> test_1c3426238b8296745d8d8bd0ff995ab65a51992b568dc7c5ce73c3f59b107825_no_assignments_sol.sol
3+
4+
Warning: Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.0;"
5+
--> test_1c3426238b8296745d8d8bd0ff995ab65a51992b568dc7c5ce73c3f59b107825_no_assignments_sol.sol
6+
7+
Error: Some immutables were read from but never assigned, possibly because of optimization.
8+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"contracts": {
3+
"syntaxTests/immutable/no_assignments.sol": {
4+
"C": {
5+
"metadata": "{\"compiler\":{\"version\":\"0.8.0+commit.c7dfd78e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"f\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"syntaxTests/immutable/no_assignments.sol\":\"C\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"syntaxTests/immutable/no_assignments.sol\":{\"keccak256\":\"0xbafaec265150d52cd293787144247b1a0a782adf3cb89296fb4f0eb05dc25739\",\"urls\":[\"bzz-raw://7c01dbb8146347c8cf62469d57a0e290f7ef1b871426d86d995315160db665c0\",\"dweb:/ipfs/QmPrYtxVbFCFeXwnhcHoBgbg546EqMzQCT5kK7wLc3rat8\"]}},\"version\":1}"
6+
}
7+
}
8+
},
9+
"errors": [
10+
{
11+
"component": "general",
12+
"errorCode": "1878",
13+
"formattedMessage": "Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.\n--> syntaxTests/immutable/no_assignments.sol\n\n",
14+
"message": "SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing \"SPDX-License-Identifier: <SPDX-License>\" to each source file. Use \"SPDX-License-Identifier: UNLICENSED\" for non-open-source code. Please see https://spdx.org for more information.",
15+
"severity": "warning",
16+
"sourceLocation": {
17+
"end": -1,
18+
"file": "syntaxTests/immutable/no_assignments.sol",
19+
"start": -1
20+
},
21+
"type": "Warning"
22+
},
23+
{
24+
"component": "general",
25+
"errorCode": "3420",
26+
"formattedMessage": "Warning: Source file does not specify required compiler version! Consider adding \"pragma solidity ^0.8.0;\"\n--> syntaxTests/immutable/no_assignments.sol\n\n",
27+
"message": "Source file does not specify required compiler version! Consider adding \"pragma solidity ^0.8.0;\"",
28+
"severity": "warning",
29+
"sourceLocation": {
30+
"end": -1,
31+
"file": "syntaxTests/immutable/no_assignments.sol",
32+
"start": -1
33+
},
34+
"type": "Warning"
35+
},
36+
{
37+
"component": "general",
38+
"errorCode": "1284",
39+
"formattedMessage": "CodeGenerationError: Some immutables were read from but never assigned, possibly because of optimization.\n\n",
40+
"message": "Some immutables were read from but never assigned, possibly because of optimization.",
41+
"severity": "error",
42+
"type": "CodeGenerationError"
43+
}
44+
],
45+
"sources": {
46+
"syntaxTests/immutable/no_assignments.sol": {
47+
"id": 0
48+
}
49+
}
50+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Compiler error: Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.
2+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"contracts": {
3+
"syntaxTests/tupleAssignments/large_component_count.sol": {
4+
"C": {
5+
"metadata": "{\"compiler\":{\"version\":\"0.8.0+commit.c7dfd78e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"f\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"g\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"syntaxTests/tupleAssignments/large_component_count.sol\":\"C\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"syntaxTests/tupleAssignments/large_component_count.sol\":{\"keccak256\":\"0xb5478857c30ab2e7cf6b0fdcad0fdc70f4715129a7dd3f3f1dda5b3892a83846\",\"urls\":[\"bzz-raw://abc14e4a2a61618b712c4ac3ba0cab07d9214d0637af78aa7648e3d2f89eb725\",\"dweb:/ipfs/QmTqrQzwWbZgdAck6ma9xY3sL1mGiw61Nsg36P21mZdxLG\"]}},\"version\":1}"
6+
}
7+
}
8+
},
9+
"errors": [
10+
{
11+
"component": "general",
12+
"formattedMessage": "CompilerError: Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.\n\n",
13+
"message": "Compiler error (/solidity/libyul/backends/evm/AsmCodeGen.cpp:248):Stack too deep when compiling inline assembly: Variable value0 is 1 slot(s) too deep inside the stack.",
14+
"severity": "error",
15+
"type": "CompilerError"
16+
}
17+
],
18+
"sources": {
19+
"syntaxTests/tupleAssignments/large_component_count.sol": {
20+
"id": 0
21+
}
22+
}
23+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Unimplemented feature:
2+
/solidity/libsolidity/codegen/CompilerUtils.cpp(771): Throw in function void solidity::frontend::CompilerUtils::convertType(const solidity::frontend::Type&, const solidity::frontend::Type&, bool, bool, bool)
3+
Dynamic exception type: boost::wrapexcept<solidity::langutil::UnimplementedFeatureError>
4+
std::exception::what: Not yet implemented - FixedPointType.
5+
[solidity::util::tag_comment*] = Not yet implemented - FixedPointType.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"contracts": {
3+
"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol": {
4+
"test": {
5+
"metadata": "{\"compiler\":{\"version\":\"0.8.0+commit.c7dfd78e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"f\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol\":\"test\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol\":{\"keccak256\":\"0x44b85b2db00441b574d40d11a6be684517d4312de0f6ef0550e02aea33e2a05f\",\"urls\":[\"bzz-raw://c7a9416a8634c5bd1451742f09d633acab37a6e0db1441d0bb7ea4e8f4af214b\",\"dweb:/ipfs/QmZNMQcZu9wnD6sFH2c7PymZReYeroBXDyKkJ5YEhWtCjc\"]}},\"version\":1}"
6+
}
7+
}
8+
},
9+
"errors": [
10+
{
11+
"component": "general",
12+
"formattedMessage": "UnimplementedFeatureError: Not yet implemented - FixedPointType.\n\n",
13+
"message": "Unimplemented feature (/solidity/libsolidity/codegen/CompilerUtils.cpp:771):Not yet implemented - FixedPointType.",
14+
"severity": "error",
15+
"type": "UnimplementedFeatureError"
16+
}
17+
],
18+
"sources": {
19+
"syntaxTests/nameAndTypeResolution/317_fixed_type_valid_explicit_conversions.sol": {
20+
"id": 0
21+
}
22+
}
23+
}

test/scripts/test_bytecodecompare_prepare_report.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
UNKNOWN_PRAGMA_SOL_JSON_OUTPUT = load_fixture('unknown_pragma_sol_json_output.json')
3333
UNKNOWN_PRAGMA_SOL_CLI_OUTPUT = load_fixture('unknown_pragma_sol_cli_output.txt')
3434

35+
UNIMPLEMENTED_FEATURE_JSON_OUTPUT = load_fixture('unimplemented_feature_json_output.json')
36+
UNIMPLEMENTED_FEATURE_CLI_OUTPUT = load_fixture('unimplemented_feature_cli_output.txt')
37+
38+
STACK_TOO_DEEP_JSON_OUTPUT = load_fixture('stack_too_deep_json_output.json')
39+
STACK_TOO_DEEP_CLI_OUTPUT = load_fixture('stack_too_deep_cli_output.txt')
40+
41+
CODE_GENERATION_ERROR_JSON_OUTPUT = load_fixture('code_generation_error_json_output.json')
42+
CODE_GENERATION_ERROR_CLI_OUTPUT = load_fixture('code_generation_error_cli_output.txt')
43+
3544

3645
class PrepareReportTestBase(unittest.TestCase):
3746
def setUp(self):
@@ -294,6 +303,21 @@ def test_parse_standard_json_output_should_not_report_error_if_there_is_at_least
294303

295304
self.assertEqual(parse_standard_json_output(Path('contract.sol'), compiler_output), expected_report)
296305

306+
def test_parse_standard_json_output_should_report_error_on_unimplemented_feature_error(self):
307+
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
308+
309+
self.assertEqual(parse_standard_json_output(Path('file.sol'), UNIMPLEMENTED_FEATURE_JSON_OUTPUT), expected_report)
310+
311+
def test_parse_standard_json_output_should_report_error_on_stack_too_deep_error(self):
312+
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
313+
314+
self.assertEqual(parse_standard_json_output(Path('file.sol'), STACK_TOO_DEEP_JSON_OUTPUT), expected_report)
315+
316+
def test_parse_standard_json_output_should_report_error_on_code_generation_error(self):
317+
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
318+
319+
self.assertEqual(parse_standard_json_output(Path('file.sol'), CODE_GENERATION_ERROR_JSON_OUTPUT), expected_report)
320+
297321

298322
class TestParseCLIOutput(PrepareReportTestBase):
299323
def test_parse_cli_output(self):
@@ -378,3 +402,18 @@ def test_parse_cli_output_should_report_missing_bytecode_and_metadata(self):
378402
)
379403

380404
self.assertEqual(parse_cli_output(Path('syntaxTests/scoping/library_inherited2.sol'), compiler_output), expected_report)
405+
406+
def test_parse_cli_output_should_report_error_on_unimplemented_feature_error(self):
407+
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
408+
409+
self.assertEqual(parse_cli_output(Path('file.sol'), UNIMPLEMENTED_FEATURE_CLI_OUTPUT), expected_report)
410+
411+
def test_parse_cli_output_should_report_error_on_stack_too_deep_error(self):
412+
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
413+
414+
self.assertEqual(parse_cli_output(Path('file.sol'), STACK_TOO_DEEP_CLI_OUTPUT), expected_report)
415+
416+
def test_parse_cli_output_should_report_error_on_code_generation_error(self):
417+
expected_report = FileReport(file_name=Path('file.sol'), contract_reports=None)
418+
419+
self.assertEqual(parse_cli_output(Path('file.sol'), CODE_GENERATION_ERROR_CLI_OUTPUT), expected_report)

0 commit comments

Comments
 (0)