joern
joern copied to clipboard
reachableByFlows for Java code doesn't return multiple paths if we have several if conditions
reachableByFlows
doesn't return multiple paths if we have several if conditions.
Suppose, we have a small dummy example:
val cpg = code(
"""package a;
|import java.io.File;
|public class MainClass {
| public File getISmtokenPos(String str, int savedPos) {
| int num = 1;
| int i = savedPos - 1;
| if (i >= 2 && isDSeparator(str.charAt(i - 2))) {
| num = i - 2;
| } else {
| num = i;
| }
| File file = new File("/Users/pankaj/source.txt" + Integer.toString(num));
| int temp = Desktop.getDesktop().open(file);
| return file;
| }
| private boolean isDSeparator(char c) {
| return true;
| }
|}""".stripMargin).moreCode(
"""package a;
|import java.io.File;
|public class Desktop {
| public int open(File file) { return 6; }
| private static int isDesktopSupported() { return 0; }
| public static Desktop getDesktop() { return new Desktop(); }
|}
|""".stripMargin).moreCode(
"""package a;
|import java.io.File;
|public class Main {
| public static void main(String[] args) { new Main().f(5); }
| public File f(int a) {
| int b = a + 1;
| return new MainClass().getISmtokenPos(String.valueOf(a), b);
| }
|}""".stripMargin)
The source is a list of identifiers of line 7 return new MainClass().getISmtokenPos(String.valueOf(a), b)
:
List(String, a, b)
The sink is a list of identifiers in the call Desktop.getDesktop().open(file)
(I've chosen only 1):
List(file)
Only 1 path is returned:
List(_______________________________________________________________________________________________
| nodeType | tracked | lineNumber| method | file |
|==============================================================================================|
| Identifier | new MainClass().getISmtoken... | 7 | f | Test2.java |
| MethodParameterIn | getISmtokenPos(this, String... | 4 | getISmtokenPos | Test0.java |
| Identifier | savedPos - 1 | 6 | getISmtokenPos | Test0.java |
| Call | savedPos - 1 | 6 | getISmtokenPos | Test0.java |
| Identifier | int i = savedPos - 1 | 6 | getISmtokenPos | Test0.java |
| Identifier | i >= 2 | 7 | getISmtokenPos | Test0.java |
| Identifier | i - 2 | 7 | getISmtokenPos | Test0.java |
| Identifier | i - 2 | 8 | getISmtokenPos | Test0.java |
| Call | i - 2 | 8 | getISmtokenPos | Test0.java |
| Identifier | num = i - 2 | 8 | getISmtokenPos | Test0.java |
| Identifier | Integer.toString(num) | 12 | getISmtokenPos | Test0.java |
| Call | "/Users/pankaj/source.txt" ... | 12 | getISmtokenPos | Test0.java |
| Identifier | new File("/Users/pankaj/sou... | 12 | getISmtokenPos | Test0.java |
| Identifier | Desktop.getDesktop().open(f... | 13 | getISmtokenPos | Test0.java |
Steps to reproduce the behavior:
- Use javasrc2cpg to construct code for those files and run joern cli with
joern project.bin
(also you can use latest version of joern and compile scala project) - Find the mentioned identifiers
- Run reachableByFlows
- See only 1 path with condition:
if (i >= 2 && isDSeparator(str.charAt(i - 2))) {
num = i - 2;
}
Expected behavior 2 paths are shown: The 1st contains
if (i >= 2 && isDSeparator(str.charAt(i - 2))) {
num = i - 2;
}
The 2nd contains
else {
num = i;
}
Desktop:
- checked on both Windows 10 Pro build 19045.3324 / Ubuntu 20.04.4 LTS
- Joern Version: 2.0.74 or joern libraries:
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.9" % "test",
libraryDependencies += "io.joern" %% "javasrc2cpg" % "2.0.105",
libraryDependencies += "io.joern" %% "joern-cli" % "2.0.105",
libraryDependencies += "io.joern" %% "x2cpg" % "2.0.105",
libraryDependencies += "io.joern" %% "dataflowengineoss" % "2.0.105",
libraryDependencies += "io.joern" %% "semanticcpg" % "2.0.105",
libraryDependencies += "io.shiftleft" %% "semanticcpg" % "1.3.522",
libraryDependencies += "io.shiftleft" %% "codepropertygraph" % "1.4.23",
- Java version: openjdk 17.0.8.1 2023-08-24 (Ubuntu), java 17.0.1 2021-10-19 LTS (Windows)
Additional context
The issue that even if I replace else
with else if
or multiple else if
, the paths which should contain code inside those cycles are absent also. Seems joern doesn't include such paths
The problem is that even when I replace else
with else if
or multiple else if
, the paths that should contain code inside those blocks are also missing. It seems that joern
does not include such paths.