Attackathon _ Fuel Network 32536 - [Smart Contract - Insight] The control flow graph is incorrectly
Submitted on Tue Jun 25 2024 18:34:32 GMT-0400 (Atlantic Standard Time) by @Schnilch for Attackathon | Fuel Network
Report ID: #32536
Report type: Smart Contract
Report severity: Insight
Target: https://github.com/FuelLabs/sway/tree/7b56ec734d4a4fda550313d448f7f20dba818b59
Impacts:
Contract fails to deliver promised returns, but doesn't lose value
Compiler fails to deliver promised returns
Description
Brief/Intro
When the control flow graph is constructed for return path analysis, the mistake is made that only the "first level" of the code is examined. This means that, for example, if an if statement occurs in the code, the if statement is included in the graph, but the code within the if statement is not further analyzed. As a result, the return path analysis that uses this graph cannot function correctly since it is possible that there is a return in the if statement. However, this currently has no real impact as everything is caught by the type check.
Vulnerability Details
After the code has been type-checked, some further analyses are performed, including the return path analysis which checks whether all possible paths in the code provide a return value (See 1. reference). For this, a control flow graph is built (See 2. reference). In doing so, the function connect_node is used, which incorrectly handles expressions (See 3. reference). connect_node handles all expressions except for return expressions as follows:
In this process, we see that regardless of the type of expression (except for return expressions), it is simply added to the graph and connected to the leaves. However, there are expressions such as if statements that contain code. This code, as seen in the above code snippet, is not added to the graph. The issue with this approach is that the code may contain return statements that are not accounted for. Something similar can happen when the last expression in a function, which is supposed to return something, also contains code:
In this case, the expression could again be, for example, an if statement that contains code. Here again, this code would not be added to the graph. Only the if statement itself would be added to the graph as a return expression, without checking whether something is actually returned within the if statement.
Impact Details
Although due to this bug the return path analysis did not work correctly, currently it has no real consequences because if a return value were missing, it would be detected by the type check. If no value is returned from a path in the function that should return something, it is simply recognized as returning a value with the wrong type. However, this bug could have consequences if, for example, the compiler is further developed and the type check no longer catches this error, relying instead on the return path analysis. Additionally, at the moment, the return path analysis does not return errors as it should.
References
https://github.com/FuelLabs/sway/blob/7b56ec734d4a4fda550313d448f7f20dba818b59/sway-core/src/lib.rs#L1055-L1059
https://github.com/FuelLabs/sway/blob/7b56ec734d4a4fda550313d448f7f20dba818b59/sway-core/src/lib.rs#L1069
https://github.com/FuelLabs/sway/blob/7b56ec734d4a4fda550313d448f7f20dba818b59/sway-core/src/control_flow_analysis/analyze_return_paths.rs#L140-L189
Proof of concept
Proof of Concept
To show that the control flow graph is incorrectly constructed, it is best to visualize it, as this allows you to see most clearly that a part of the code is missing in the graph. To do this, the graph must first be output to a file after it has been visualized. For this, the following line must be inserted into sway-core/src/lib.rs:
Now the following POC can be inserted into the file sway-core/src/lib.rs and started with this command: cargo test -p sway-core poc -- --nocapture
Now you should see the errors that were caught during the type check but no errors from the return path analysis in the terminal. Additionally, there should now be a file sway-core/return_graph where the graph is located. This graph can now be copied and visualized, for example, on this website: https://dreampuf.github.io/GraphvizOnline/ The code for the graph should look like this:
Based on the graph, it is clear that while the if statement appears as an implicit return, the code within the if statement that would actually perform the return is not included. Since the return path analysis iterates over this graph later, it will not check whether the if statement actually returns anything.
Last updated