Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FieldRef validator changes #791

Merged
merged 11 commits into from
Jan 5, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997-2020 Raja Vallée-Rai, Christian Brüggemann, Markus Schmidt and others
* Copyright (C) 1997-2020 Raja Vallée-Rai, Christian Brüggemann, Markus Schmidt, Akshita Dubey and others
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
Expand All @@ -24,7 +24,13 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import sootup.core.jimple.common.ref.JFieldRef;
import sootup.core.jimple.common.ref.JInstanceFieldRef;
import sootup.core.jimple.common.ref.JStaticFieldRef;
import sootup.core.jimple.common.stmt.Stmt;
import sootup.core.model.Body;
import sootup.core.model.SootField;
import sootup.core.views.View;

public class FieldRefValidator implements BodyValidator {
Expand All @@ -35,31 +41,47 @@

List<ValidationException> validationException = new ArrayList<>();

// TODO: check copied code from old soot
/*
* SootMethod methodRef = body.getMethod(); if (methodRef.isAbstract()) { return; }
*
* Chain<Unit> units = body.getUnits().getNonPatchingChain();
*
* for (Unit unit : units) { Stmt s = (Stmt) unit; if (!s.containsFieldRef()) { continue; } JFieldRef fr =
* s.getFieldRef();
*
* if (fr instanceof JStaticFieldRef) { JStaticFieldRef v = (JStaticFieldRef) fr; try { SootField field = v.getField();
* if (field == null) { exceptions.add(new UnitValidationException(unit, body, "Resolved field is null: " +
* fr.toString())); } else if (!field.isStatic() && !field.isPhantom()) { exceptions .add(new
* UnitValidationException(unit, body, "Trying to get a static field which is non-static: " + v)); } } catch
* (ResolutionFailedException e) { exceptions.add(new UnitValidationException(unit, body,
* "Trying to get a static field which is non-static: " + v)); } } else if (fr instanceof InstanceFieldRef) {
* InstanceFieldRef v = (InstanceFieldRef) fr;
*
* try { SootField field = v.getField(); if (field == null) { exceptions.add(new UnitValidationException(unit, body,
* "Resolved field is null: " + fr.toString())); } else if (field.isStatic() && !field.isPhantom()) { exceptions.add(new
* UnitValidationException(unit, body, "Trying to get an instance field which is static: " + v)); } } catch
* (ResolutionFailedException e) { exceptions.add(new UnitValidationException(unit, body,
* "Trying to get an instance field which is static: " + v)); } } else { throw new RuntimeException("unknown field ref");
* } }
*/
List<Stmt> stmts = body.getStmts();

for (Stmt stmt : stmts) {
if (!stmt.containsFieldRef()) {
continue;
}
JFieldRef fr = stmt.getFieldRef();

if (fr instanceof JStaticFieldRef) {
JStaticFieldRef v = (JStaticFieldRef) fr;

Optional<? extends SootField> fieldOpt = view.getField(v.getFieldSignature());
if (!fieldOpt.isPresent()) {
validationException.add(new ValidationException(v, "Resolved field is empty: "));

Check warning on line 57 in sootup.core/src/main/java/sootup/core/validation/FieldRefValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/FieldRefValidator.java#L57

Added line #L57 was not covered by tests
Comment on lines +56 to +57
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can occur when not a complete program is given in the input - lets just ignore those cases.

} else {
SootField field = fieldOpt.get();
if (!field.isStatic()) {
validationException.add(
new ValidationException(
fr, "Trying to get a static field which is non-static: " + v));
}
}
} else if (fr instanceof JInstanceFieldRef) {
JInstanceFieldRef v = (JInstanceFieldRef) fr;

Optional<? extends SootField> fieldOpt = view.getField(v.getFieldSignature());
if (!fieldOpt.isPresent()) {
validationException.add(
new ValidationException(fr, "Resolved field is null: " + fr.toString()));

Check warning on line 72 in sootup.core/src/main/java/sootup/core/validation/FieldRefValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/FieldRefValidator.java#L71-L72

Added lines #L71 - L72 were not covered by tests
Comment on lines +71 to +72
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can occur when not a complete program is given in the input - lets just ignore those cases.

} else {
SootField field = fieldOpt.get();
if (field.isStatic()) {
validationException.add(
new ValidationException(
fr, "Trying to get an instance field which is static: " + v));
}
}
} else {
throw new RuntimeException("unknown field ref");

Check warning on line 82 in sootup.core/src/main/java/sootup/core/validation/FieldRefValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/FieldRefValidator.java#L82

Added line #L82 was not covered by tests
}
}
return validationException;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package sootup.tests.validator;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import categories.Java8Test;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import sootup.core.model.SootClass;
import sootup.core.model.SourceType;
import sootup.core.signatures.PackageName;
import sootup.core.types.ClassType;
import sootup.core.validation.FieldRefValidator;
import sootup.core.validation.ValidationException;
import sootup.jimple.parser.JimpleAnalysisInputLocation;
import sootup.jimple.parser.JimpleView;

@Category(Java8Test.class)
public class FieldRefValidatorTest {

FieldRefValidator fieldRefValidator;
JimpleView jimpleView;
Collection<SootClass<?>> classes;

@Before
public void Setup() {

fieldRefValidator = new FieldRefValidator();

ClassType classTypeFieldRefValidator =
new ClassType() {
@Override
public boolean isBuiltInClass() {
return false;
}

@Override
public String getFullyQualifiedName() {
return "jimple.FieldRefValidator";
}

@Override
public String getClassName() {
return "FieldRefValidator";
}

@Override
public PackageName getPackageName() {
return new PackageName("jimple");
}
};

String classPath = "src/test/resources/validator/jimple";
JimpleAnalysisInputLocation jimpleInputLocation =
new JimpleAnalysisInputLocation(Paths.get(classPath), SourceType.Application);

jimpleView = new JimpleView(jimpleInputLocation);
final Optional<SootClass<?>> classSource1 = jimpleView.getClass(classTypeFieldRefValidator);
assertFalse(classSource1.isPresent());

classes = new HashSet<>(); // Set to track the classes to check

for (SootClass<?> aClass : jimpleView.getClasses()) {
if (!aClass.isLibraryClass()) {
classes.add(aClass);
}
}
}

@Test
public void testFieldRefValidatorSuccess() {
List<ValidationException> validationExceptions_success;

validationExceptions_success =
fieldRefValidator.validate(
classes.stream()
.filter(c -> c.getType().getClassName().equals("FieldRefValidator"))
.findFirst()
.get()
.getMethods()
.stream()
.filter(m -> m.getName().equals("testFieldRefValidator_pass"))
.map(m -> m.getBody())
.findFirst()
.get(),
jimpleView);

assertEquals(0, validationExceptions_success.size());
}

@Test
public void testFieldRefValidatorFailure() {
List<ValidationException> validationExceptions_fail;

validationExceptions_fail =
fieldRefValidator.validate(
classes.stream()
.filter(c -> c.getType().getClassName().equals("FieldRefValidator"))
.findFirst()
.get()
.getMethods()
.stream()
.filter(m -> m.getName().equals("testFieldRefValidator_fail"))
.map(m -> m.getBody())
.findFirst()
.get(),
jimpleView);

assertEquals(2, validationExceptions_fail.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import categories.Java8Test;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import sootup.core.model.SootClass;
import sootup.core.model.SourceType;
import sootup.core.signatures.PackageName;
Expand All @@ -19,6 +21,7 @@
import sootup.jimple.parser.JimpleAnalysisInputLocation;
import sootup.jimple.parser.JimpleView;

@Category(Java8Test.class)
public class NewValidatorTest {

NewValidator validator;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
public super class FieldRefValidator extends java.lang.Object
{
private int x;

private static int y;

public void <init>()
{
FieldRefValidator $l0;


$l0 := @this: FieldRefValidator;
specialinvoke $l0.<java.lang.Object: void <init>()>();

return;
}

static void <clinit>()
{

<FieldRefValidator: int y> = 5;

return;
}

public void testFieldRefValidator_pass()
{
FieldRefValidator $l0;
unknown $stack1, $stack2;

$l0 := @this: FieldRefValidator;
$stack1 = $l0.<FieldRefValidator: int x>;
$stack2 = <FieldRefValidator: int y>;

return;
}

public void testFieldRefValidator_fail()
{
FieldRefValidator $l0;
unknown $stack1, $stack2;

$l0 := @this: FieldRefValidator;
$stack1 = <FieldRefValidator: int x>;
$stack2 = $l0.<FieldRefValidator: int y>;

return;
}

}