joern icon indicating copy to clipboard operation
joern copied to clipboard

reachableByFlows for Java code doesn't return multiple paths if we have several if conditions

Open lyriccoder opened this issue 1 year ago • 0 comments

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:

  1. 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)
  2. Find the mentioned identifiers
  3. Run reachableByFlows
  4. 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.

lyriccoder avatar Oct 19 '23 09:10 lyriccoder