Skip to content

Tai-e seems unable to handle the taint-flow through the collection-class correctly. #146

@Spr1n9T1me

Description

@Spr1n9T1me

📝 Overall Description

Description

I tried to test the taint-analysis Module of Tai-e with one example below:

package collection;

import util.SourceSinks;
import java.util.ArrayList;

public class CollectionExample {
    public static void main(String[] args) throws Exception{
        ArrayList<String> list = new ArrayList<>();
        list.add(SourceSinks.getTaintedInput()); // source point
        list.add(SourceSinks.getSafeInput());
        String element = list.get(0);
        Runtime.getRuntime().exec(element); // sink point
    }
}

which converts to tir format is:

public class collection.CollectionExample extends java.lang.Object {

   public void <init>() {
       [0@L8] invokespecial %this.<java.lang.Object: void <init>()>();
       [1@L8] return;
   }

   public static void main(java.lang.String[] r6) {
       java.util.ArrayList $r0;
       java.lang.String $r1, $r2, r4;
       java.lang.Object $r3;
       int %intconst0;
       java.lang.Runtime $r5;
       [0@L11] $r0 = new java.util.ArrayList;
       [1@L11] invokespecial $r0.<java.util.ArrayList: void <init>()>();
       [2@L12] $r1 = invokestatic <util.SourceSinks: java.lang.String getTaintedInput()>();
       [3@L12] invokevirtual $r0.<java.util.ArrayList: boolean add(java.lang.Object)>($r1);
       [4@L13] $r2 = invokestatic <util.SourceSinks: java.lang.String getSafeInput()>();
       [5@L13] invokevirtual $r0.<java.util.ArrayList: boolean add(java.lang.Object)>($r2);
       [6@L14] %intconst0 = 0;
       [7@L14] $r3 = invokevirtual $r0.<java.util.ArrayList: java.lang.Object get(int)>(%intconst0);
       [8@L14] r4 = (java.lang.String) $r3;
       [9@L15] $r5 = invokestatic <java.lang.Runtime: java.lang.Runtime getRuntime()>();
       [10@L15] invokevirtual $r5.<java.lang.Runtime: java.lang.Process exec(java.lang.String)>(r4);
       [11@L26] return;
   }

}

When pointer analysis is executed to [7@L14] $r3 = invokevirtual $r0.<java.util.ArrayList: java.lang.Object get(int)>(%intconst0); , the system will try to get pts(%intconst0), but during initialization, %intconst0 = 0; is not considered a statement that creates ConstantObj. The reason is that DefaultSolver can only create ConstantObj for statements whose Rvalue is ReferenceLiteral(refer to link ).NumberLiteral is not a sub-type of ReferenceLiteral. As a result, the passed parameter pointer set of list.get(0) is null, and pointer analysis is interrupted here. Ultimately, the taint-flow cannot be detected.
So my question is, how to detect the taint-flow In this case.

taint-flow-graph output

I have dumped the outputed taint-flow-graph.dot,content below:

digraph G {
  node [];
  edge [];
  "VarNode{<collection.CollectionExample: void main(java.lang.String[])>/$r1}" [fillcolor=floralwhite,shape=box,style=filled];
  "VarNode{<java.util.ArrayList: boolean add(java.lang.Object)>/r2}" [fillcolor=floralwhite,shape=box,style=filled];
  "ArrayIndexNode{NewObj{<java.util.ArrayList: void <init>(int)>[3@L153] newarray java.lang.Object[i0]}}" [fillcolor=khaki1,style=filled];
  "VarNode{<collection.CollectionExample: void main(java.lang.String[])>/$r1}" -> "VarNode{<java.util.ArrayList: boolean add(java.lang.Object)>/r2}" [color=blue];
  "VarNode{<java.util.ArrayList: boolean add(java.lang.Object)>/r2}" -> "ArrayIndexNode{NewObj{<java.util.ArrayList: void <init>(int)>[3@L153] newarray java.lang.Object[i0]}}" [color=red];
  "{ kind: \"call\", method: \"<util.SourceSinks: java.lang.String getTaintedInput()>\", index: \"result\", type: \"java.lang.String\" }\n<collection.CollectionExample: void main(java.lang.String[])>[2@L12] $r1 = invokestatic util.SourceSinks.getTaintedInput()/result" [fillcolor=gold,shape=doubleoctagon,style=filled];
  "{ kind: \"call\", method: \"<util.SourceSinks: java.lang.String getTaintedInput()>\", index: \"result\", type: \"java.lang.String\" }\n<collection.CollectionExample: void main(java.lang.String[])>[2@L12] $r1 = invokestatic util.SourceSinks.getTaintedInput()/result" -> "VarNode{<collection.CollectionExample: void main(java.lang.String[])>/$r1}";
}

🎯 Expected Behavior

Detect the taint-flow correctly through collection-class.

🐛 Current Behavior

Pointer analysis interrupted encountering collection-class.

🔄 Reproducible Example

given above.

⚙️ Tai-e Arguments

🔍 Click here to see Tai-e Options
optionsFile: null
printHelp: false
classPath: []
appClassPath:
- tai-e-tir-test/target/classes
mainClass: collection.CollectionExample
inputClasses: []
javaVersion: 8
prependJVM: false
allowPhantom: true
worldBuilderClass: pascal.taie.frontend.soot.SootWorldBuilder
outputDir: output
preBuildIR: false
worldCacheMode: false
scope: REACHABLE
nativeModel: true
planFile: null
analyses:
ir-dumper: ""
pta: cs:ci;distinguish-string-constants:app;taint-config:src\main\resources\taint-config.yml;only-app:false;dump-ci:true
onlyGenPlan: false
keepResult:
- $KEEP-ALL

📜 Tai-e Log

🔍 Click here to see Tai-e Log
{{The content of 'output/tai-e.log' file}}

ℹ️ Additional Information

none

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions