pamunb / jimpleframework Goto Github PK
View Code? Open in Web Editor NEWA Rascal implementation of the Jimple framework.
A Rascal implementation of the Jimple framework.
Hi, the decompile method in Decompiler class is generating an error when processing classes with java stream mechanism.
Below the code to reproduce the error:
package samples;
import java.util.Arrays;
import java.util.List;
public class StreamSupportSample {
public static void main(String[] args) {
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList.stream().filter(s -> s.startsWith("c")).map(String::toUpperCase).sorted().forEach(System.out::println);
}
}
Error message:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running lang.jimple.internal.TestDecompiler
java.util.EmptyStackException
at java.util.Stack.peek(Stack.java:102)
at java.util.Stack.pop(Stack.java:84)
at lang.jimple.internal.Decompiler$InstructionSetVisitor.invokeMethodIns(Decompiler.java:669)
at lang.jimple.internal.Decompiler$InstructionSetVisitor.visitMethodInsn(Decompiler.java:529)
at org.objectweb.asm.tree.MethodInsnNode.accept(Unknown Source)
at org.objectweb.asm.tree.InsnList.accept(Unknown Source)
at lang.jimple.internal.Decompiler$GenerateJimpleClassVisitor.visitMethod(Decompiler.java:203)
at lang.jimple.internal.Decompiler$GenerateJimpleClassVisitor.visitEnd(Decompiler.java:154)
Code to test the class:
@Test
public void decompileStreamSupport() {
try {
File classFile = new File("./target/test-classes/samples/StreamSupportSample.class");
assertNotNull(classFile);
IValueFactory vf = ValueFactory.getInstance();
Decompiler decompiler = new Decompiler(vf);
IConstructor c = decompiler.decompile(new FileInputStream(classFile), null);
assertNotNull(c);
}
catch(Exception e) {
e.printStackTrace();
fail(e.getLocalizedMessage());
}
}
Sample code to reproduce the error:
public class TestClass {
public void D() {
List<String> list = List.of("a","b","c","d");
for(int i=0; i < list.size(); i++) {
log("Executing D: "+list.get(i));
}
}
static void log(String message) {
System.out.println(message);
}
}
Error message:
java.lang.StackOverflowError
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:107)
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:127)
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:127)
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:127)
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:127)
It will help to track the statements (as unique ones)
Currently, our organization in terms of packages is as follows:
io (IO utility functions for traversing the file system)
lang.jimple (AST + Decompiler)
lang.jimple.analysis (ControlFlowGraph)
lang.jimple.analysis.dataflow (DataFlow framework + DataFlow algorithms)
lang.jimple.analysis.ssa (conversion to the SSA format)
lang.jimple.core (execution context of the program analysis)
lang.jimple.internal (internal utility module for generating Java code from Jimple syntax)
lang.jimple.toolkit (CallGraph, SensitiveAnalysis, Global PP)
lang.jimple.toolkit.jimplify (Transformations for jimple code refinement)
lang.jimple.util (data type converterds (e.g.: signature to string) + Local PP)
We do think that the following is better:
lang.jimple.core: AST + ExecutionContext
lang.jimple.toolkit: SSA, CallGraph, ControlFlowGraph
lang.jimple.analysys.dataflow: DataflowFramework + DataFlow algorithms
lang.jimple.analysys.security: SensitiveAnalysis
lang.jimple.decompiler: Decompiler, jimple transformations
lang.jimple.util: io, converters, ....
Hi, the Decompiler class has a problem when decompiling (bytecode to jimple) a class file that is originated from a source code (.java) which have a nested interface. Maybe the whole problem is related to the generation of multiples class files originated from java files. Below is the code that gives the error:
package samples;
interface MyInterfaceA{
void display();
}
class NestedInterface
implements MyInterfaceA{
public void display(){
System.out.println("Nested interface method");
}
public static void main(String args[]){
MyInterfaceA obj=
new NestedInterface();
obj.display();
}
}
I created a test case for this:
@Test
public void decompileNestedInterface() {
try {
File classFile = new File("./target/test-classes/samples/NestedInterface.class");
assertNotNull(classFile);
IValueFactory vf = ValueFactory.getInstance();
Decompiler decompiler = new Decompiler(vf);
IConstructor c = decompiler.decompile(new FileInputStream(classFile), null);
assertNotNull(c);
}
catch(Exception e) {
e.printStackTrace();
fail(e.getLocalizedMessage());
}
}
And here the error:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running lang.jimple.internal.TestDecompiler
Tests run: 5, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.226 sec <<< FAILURE!
decompileNestedInterface(lang.jimple.internal.TestDecompiler) Time elapsed: 0.023 sec <<< ERROR!
java.lang.StackOverflowError
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:107)
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:127)
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:127)
at lang.jimple.internal.JimpleObjectFactory.type(JimpleObjectFactory.java:127)
I came up with this error trying to process this simple file:
The decompiler is assigning the Unknown
type when decompiling the new
statement.
When we try to decompile this code:
public class Vanilla {
public static void main(String[] args) {
List<Student> students = Collections.emptyList();
students.add(new Student("Pedro", 30));
students.add(new Student("João", 25));
Predicate<Student> p = s -> s.name == "Pedro";
Vanilla v = new Vanilla();
}
public List<Student> vanilla(List<Student> students, Predicate<Student> p, Function<Student, Student> f) {
List<Student> result = Collections.emptyList();
boolean over = false;
while(!over) {
List<Student> sub = auxState.subList(0, auxState.size());
if(p.test(auxState.get(0))) {
result.add(f.apply(auxState.get(0)));
}
auxState = sub;
}
return result;
}
public List<Student> withFStream(List<Student> students, Predicate<Student> p, Function<Student, Student> f) {
return Collections.emptyList();
}
An exception occurs:
java.util.EmptyStackException
at java.base/java.util.Stack.peek(Stack.java:102)
at java.base/java.util.Stack.pop(Stack.java:84)
at lang.jimple.internal.Decompiler$InstructionSetVisitor.returnIns(Decompiler.java:1269)
We use the local-variable-table to configure the set of local variables of a method (including the corresponding type). Nonetheless, this table is only available when the source code of a system has been compiled using the -g
(which sets debugging information).
Tasks:
Java bytecode has newarray, anewarray, or multinewarray for dealing with arrays. We are missing in our abstract syntax (and probably in Decompiler) the multinewarray, which is called newmultiarray in Soot. We can see a code sample that uses this in Java (samples/arrays/Arrays.java).
There is a bug in the Decompiler module that is creating duplicated variables names in some method bodies.
Sample Code:
package samples;
public class LongValueSample {
public static void addLongValues() throws Exception {
long x = 10L;
long y = 20L;
System.out.println(x + y);
}
}
The Decompiler generates the code bellow:
public static void addLongValues() throws java.lang.Exception
{
long $i2;
long $i1;
java.io.PrintStream $i2;
long $i3;
$i1 = 10L;
$i2 = 20L;
$i2 = <java.lang.System: java.io.PrintStream out>;
$i3 = $i1 + $i2;
virtualinvoke $i2.<java.io.PrintStream: void println(long)>($i3);
return;
}
You can see the repeated usage of variable name $i2 (for a long and for java.io.PrintStream) .
A pretty printer to export Jimple code from the AST.
An exception is thrown whenever we generate a control flow graph processing a code like:
public void equals() {
int a = 5;
int b = 5;
boolean result = (a == b);
System.out.println(result);
}
The problem actually is with the decompiler.
A new call graph analysis that starts from the entry points.
When running this java code:
// Source: https://www.w3resource.com/java-exercises/math/java-math-exercise-20.php
public class GeneratePrimes {
public static int [] generatePrimes(int num) {
boolean[] temp = new boolean[num + 1];
for (int i = 2; i * i <= num; i++) {
if (!temp [i]) {
for (int j = i; i * j <= num; j++) {
temp [i*j] = true;
}
}
}
int prime_nums = 0;
for (int i = 2; i <= num; i++) {
if (!temp [i]) prime_nums++;
}
int [] all_primes = new int [prime_nums];
int index = 0;
for (int i = 2; i <= num; i++) {
if (!temp [i]) all_primes [index++] = i;
}
return all_primes;
}
}
This error was raised:
The Compiler is generating random label targets when dealing with switch statements.
Example code:
public void tableSwitch() {
int a = 1;
switch (a) {
case 1:
System.out.println(a);
case 2:
System.out.println(a);
default:
System.out.println(a);
}
}
The above code should generate the Jimple output bellow:
lookupswitch(1)
{
case 1: goto label1;
case 2: goto label2;
default: goto label3;
};
But it is generating this:
lookupswitch($i1)
{
case 1: goto L2002984510;
case 2: goto L300974586;
default: goto L1929121194;
}
The abstract representation from this input is:
lookupSwitch(
local("$i1"),
[
caseOption(1,"L189513712"),
caseOption(2,"L717799000"),
defaultOption("L1955752771")
]),
A new analysis to mine calls to sensitive APIs. Some tasks:
There is a JUnit Tes tRunner class that runs rascal test cases, we can integrate this runner in our code.
The link bellow could be used as an example to how to do it.
We need to implement a solution to cover all cases including: longValue, floatValue and doubleValue describes in a Jimple Syntax of Rascal of this project.
The identity statement of jimple is getting an incorrect value for local name.
Sample code:
class O {
public O f;
}
public class FooBar {
public static void main(String[] args) {
O p = new O();
O q = p;
O r = new O();
p.f = r;
O t = bar(q);
}
static O bar(O s) {
return s.f;
}
}
Output from the decompiler module (only for the bar method):
static samples.pointsto.ex2.O bar(samples.pointsto.ex2.O)
{
samples.pointsto.ex2.O r1;
samples.pointsto.ex2.O $r1;
i1 := @parameter0: samples.pointsto.ex2.O;
$r1 = r1.<samples.pointsto.ex2.O: samples.pointsto.ex2.O f>;
return $r1;
}
As you can see, there is no i1 variable in this scope.
Hi, the decompile method in Decompiler class is generating an error when processing classes with java reflection mechanism.
Below is the code to reproduce the error:
public class Reflection {
public static void staticInvokeReflection() throws NoSuchMethodException {
// Invoking static method using reflection
Method method = A.class.getMethod("staticFoo");
try {
method.invoke(null);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
The A.java file:
public class A {
public static void staticFoo() {
System.out.println("foo");
}
}
Error message:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running lang.jimple.internal.TestDecompiler
java.lang.ClassCastException: lang.jimple.internal.generated.Immediate$c_iValue cannot be cast to lang.jimple.internal.generated.Immediate$c_local
at lang.jimple.internal.Decompiler$InstructionSetVisitor.invokeMethodIns(Decompiler.java:698)
at lang.jimple.internal.Decompiler$InstructionSetVisitor.visitMethodInsn(Decompiler.java:555)
at org.objectweb.asm.tree.MethodInsnNode.accept(Unknown Source)
at org.objectweb.asm.tree.InsnList.accept(Unknown Source)
at lang.jimple.internal.Decompiler$GenerateJimpleClassVisitor.visitMethod(Decompiler.java:210)
at lang.jimple.internal.Decompiler$GenerateJimpleClassVisitor.visitEnd(Decompiler.java:162)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
this transformation will be able to delete some class' modifiers (synchronized, .....) before to generate the jimple code
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.