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

InvokeArgumentValidator changes #865

Draft
wants to merge 13 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@
|| supertypeName.equals("java.io.Serializable")
|| supertypeName.equals("java.lang.Cloneable");
} else {
throw new AssertionError("potentialSubtype has unexpected type");
throw new IllegalStateException("potentialSubtype has unexpected type");

Check warning on line 165 in sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java#L165

Added line #L165 was not covered by tests
}
} else {
throw new AssertionError("supertype has unexpected type");
throw new IllegalStateException("supertype has unexpected type");

Check warning on line 168 in sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/typehierarchy/TypeHierarchy.java#L168

Added line #L168 was not covered by tests
}
}

Expand Down Expand Up @@ -200,6 +200,6 @@
Set<ClassType> directlyExtendedInterfacesOf(@Nonnull ClassType type);

// checks if a Type is contained int the TypeHierarchy - should return the equivalent to
// View.getClass(...).isPresent()
// View.getClass(...).isPresent() - the opposite is not true!
boolean contains(ClassType type);
}
94 changes: 94 additions & 0 deletions sootup.core/src/main/java/sootup/core/types/PrimitiveType.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
* #L%
*/

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import sootup.core.jimple.visitor.TypeVisitor;

Expand Down Expand Up @@ -50,12 +54,54 @@
return name;
}

@Nonnull
public abstract String getBoxedName();

@Override
@Nonnull
public String toString() {
return name;
}

private static final Map<Class<? extends PrimitiveType>, Set<Class<? extends PrimitiveType>>>
implicitConversionMap =
ImmutableMap
.<Class<? extends PrimitiveType>, Set<Class<? extends PrimitiveType>>>builder()
.put(
ByteType.class,
ImmutableSet.of(
ShortType.class,
IntType.class,
LongType.class,
FloatType.class,
DoubleType.class))
.put(
ShortType.class,
ImmutableSet.of(IntType.class, LongType.class, FloatType.class, DoubleType.class))
.put(
CharType.class,
ImmutableSet.of(IntType.class, LongType.class, FloatType.class, DoubleType.class))
.put(
IntType.class, ImmutableSet.of(LongType.class, FloatType.class, DoubleType.class))
.put(LongType.class, ImmutableSet.of(FloatType.class, DoubleType.class))
.put(FloatType.class, ImmutableSet.of(DoubleType.class))
.build();

/**
* @param fromType e.g. the method argument
* @param toType e.g. the method parameter
* @return true if type conversion is possible
*/
public static boolean isImplicitlyConvertibleTo(
@Nonnull PrimitiveType fromType, @Nonnull PrimitiveType toType) {
Class<? extends PrimitiveType> fromTypeClass = fromType.getClass();
Class<? extends PrimitiveType> toTypeClass = toType.getClass();

Check warning on line 98 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L97-L98

Added lines #L97 - L98 were not covered by tests
return implicitConversionMap.containsKey(fromTypeClass)
&& implicitConversionMap.get(fromTypeClass).contains(toTypeClass)
|| IntType.class.isAssignableFrom(fromTypeClass)
&& implicitConversionMap.get(IntType.class).contains(toTypeClass);
}

@Nonnull
public static ByteType getByte() {
return ByteType.getInstance();
Expand Down Expand Up @@ -107,6 +153,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Byte";

Check warning on line 159 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L159

Added line #L159 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseByteType();
Expand All @@ -124,6 +176,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Short";

Check warning on line 182 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L182

Added line #L182 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseShortType();
Expand All @@ -145,6 +203,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Integer";

Check warning on line 209 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L209

Added line #L209 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseIntType();
Expand All @@ -162,6 +226,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Double";

Check warning on line 232 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L232

Added line #L232 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseDoubleType();
Expand All @@ -179,6 +249,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Long";

Check warning on line 255 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L255

Added line #L255 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseLongType();
Expand All @@ -196,6 +272,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Float";

Check warning on line 278 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L278

Added line #L278 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseFloatType();
Expand All @@ -213,6 +295,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Character";

Check warning on line 301 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L301

Added line #L301 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseCharType();
Expand All @@ -234,6 +322,12 @@
return INSTANCE;
}

@Nonnull
@Override
public String getBoxedName() {
return "Boolean";

Check warning on line 328 in sootup.core/src/main/java/sootup/core/types/PrimitiveType.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/types/PrimitiveType.java#L328

Added line #L328 was not covered by tests
}

@Override
public void accept(@Nonnull TypeVisitor v) {
v.caseBooleanType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,17 @@
* #L%
*/

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import sootup.core.IdentifierFactory;
import sootup.core.jimple.basic.Immediate;
import sootup.core.jimple.common.expr.AbstractInvokeExpr;
import sootup.core.jimple.common.stmt.Stmt;
import sootup.core.model.Body;
import sootup.core.signatures.MethodSignature;
import sootup.core.typehierarchy.TypeHierarchy;
import sootup.core.types.*;
import sootup.core.views.View;

/**
Expand All @@ -33,15 +42,99 @@
* @author Steven Arzt
*/
public class InvokeArgumentValidator implements BodyValidator {

@Override
public List<ValidationException> validate(Body body, View view) {
// TODO: check copied code from old soot
/*
* for (Unit u : body.getUnits()) { Stmt s = (Stmt) u; if (s.containsInvokeExpr()) { InvokeExpr iinvExpr =
* s.getInvokeExpr(); SootMethod callee = iinvExpr.getMethod(); if (callee != null && iinvExpr.getArgCount() !=
* callee.getParameterCount()) { exceptions.add(new ValidationException(s, "Invalid number of arguments")); } } }
*/
return null;
List<ValidationException> validationException = new ArrayList<>();

Check warning on line 47 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L47

Added line #L47 was not covered by tests

TypeHierarchy typeHierarchy = view.getTypeHierarchy();
IdentifierFactory identifierFactory = view.getIdentifierFactory();

Check warning on line 50 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L49-L50

Added lines #L49 - L50 were not covered by tests

for (Stmt stmt : body.getStmts()) {
if (!stmt.containsInvokeExpr()) {
continue;

Check warning on line 54 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L54

Added line #L54 was not covered by tests
}

AbstractInvokeExpr invExpr = stmt.getInvokeExpr();
MethodSignature callee = invExpr.getMethodSignature();
List<Immediate> args = invExpr.getArgs();
List<Type> parameterTypes = callee.getParameterTypes();

Check warning on line 60 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L57-L60

Added lines #L57 - L60 were not covered by tests

if (invExpr.getArgCount() != parameterTypes.size()) {
validationException.add(

Check warning on line 63 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L63

Added line #L63 was not covered by tests
new ValidationException(
stmt,
"Argument count '"
+ invExpr.getArgCount()

Check warning on line 67 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L67

Added line #L67 was not covered by tests
+ "' does not match the number of expected parameters '"
+ parameterTypes.size()

Check warning on line 69 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L69

Added line #L69 was not covered by tests
+ "'."));
continue;

Check warning on line 71 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L71

Added line #L71 was not covered by tests
}

// check argument type
ReferenceType argClassType;
Iterator<Type> iterParameters = parameterTypes.iterator();

Check warning on line 76 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L76

Added line #L76 was not covered by tests
for (Immediate arg : args) {
Type argType = arg.getType();
Type parameterType = iterParameters.next();

Check warning on line 79 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L78-L79

Added lines #L78 - L79 were not covered by tests

// handle implicit conversion cases. e.g., `int` is used as an argument of a `double`
// parameter
if (argType instanceof PrimitiveType) {
if (parameterType instanceof PrimitiveType) {

if (argType == parameterType) {
continue;

Check warning on line 87 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L87

Added line #L87 was not covered by tests
}
Momo-Not-Emo marked this conversation as resolved.
Show resolved Hide resolved

if (!PrimitiveType.isImplicitlyConvertibleTo(
(PrimitiveType) argType, (PrimitiveType) parameterType)) {
validationException.add(

Check warning on line 92 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L92

Added line #L92 was not covered by tests
new ValidationException(
stmt,
String.format(

Check warning on line 95 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L95

Added line #L95 was not covered by tests
"Invalid argument type - type conversion is not applicable to '%s' and the provided '%s'.",
parameterType, argType)));
}
continue;
}

// prepare autoboxing test
argClassType = identifierFactory.getBoxedType(((PrimitiveType) argType));

Check warning on line 103 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L103

Added line #L103 was not covered by tests

} else {
argClassType = (ReferenceType) argType;

Check warning on line 106 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L106

Added line #L106 was not covered by tests
}

// non-primitive type cases, primitive+autoboxing
if (argClassType == parameterType) {
continue;

Check warning on line 111 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L111

Added line #L111 was not covered by tests
}

// check if the (base-) type is contained in the typehierarchy - else it throws exceptions
// TODO: incorporate into api after #874 is done
if (parameterType instanceof ClassType
&& !typeHierarchy.contains((ClassType) parameterType)) {
continue;

Check warning on line 118 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L118

Added line #L118 was not covered by tests
}

if (parameterType instanceof ArrayType) {
Type baseType = ((ArrayType) parameterType).getBaseType();

Check warning on line 122 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L122

Added line #L122 was not covered by tests
if (baseType instanceof ClassType && !typeHierarchy.contains((ClassType) baseType)) {
continue;

Check warning on line 124 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L124

Added line #L124 was not covered by tests
}
}

if (!typeHierarchy.isSubtype(parameterType, argClassType)) {
validationException.add(

Check warning on line 129 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L129

Added line #L129 was not covered by tests
new ValidationException(
stmt,
String.format(

Check warning on line 132 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L132

Added line #L132 was not covered by tests
"Invalid argument type. Required '%s' but provided was '%s'.",
parameterType, argType)));
}
}
}
return validationException;

Check warning on line 138 in sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java

View check run for this annotation

Codecov / codecov/patch

sootup.core/src/main/java/sootup/core/validation/InvokeArgumentValidator.java#L136-L138

Added lines #L136 - L138 were not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,14 @@
try {
FileSystem fs = fileSystemCache.get(path);
final Path archiveRoot = fs.getPath("/");
return getClassSourceInternal(
(JavaClassType) type, archiveRoot, new AsmJavaClassProvider(view));
JavaClassType javaClassType = null;

// FIXME: This is a temporary workaround to prevent a casting exception when passing an
// anonymous
// ClassType object e.g. from a JimpleAnalysisInputLocation
if (type instanceof JavaClassType) javaClassType = (JavaClassType) type;
else javaClassType = new JavaClassType(type.getClassName(), type.getPackageName());

Check warning on line 108 in sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/ArchiveBasedAnalysisInputLocation.java

View check run for this annotation

Codecov / codecov/patch

sootup.java.bytecode/src/main/java/sootup/java/bytecode/inputlocation/ArchiveBasedAnalysisInputLocation.java#L108

Added line #L108 was not covered by tests
return getClassSourceInternal(javaClassType, archiveRoot, new AsmJavaClassProvider(view));
} catch (ExecutionException e) {
throw new RuntimeException("Failed to retrieve file system from cache for " + path, e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,7 @@
@Override
@Nonnull
public JavaClassType getBoxedType(@Nonnull PrimitiveType primitiveType) {
String name = primitiveType.getName();
StringBuilder boxedname = new StringBuilder(name);
boxedname.setCharAt(0, Character.toUpperCase(boxedname.charAt(0)));
return getClassType(boxedname.toString(), "java.lang");
return getClassType(primitiveType.getBoxedName(), "java.lang");

Check warning on line 239 in sootup.java.core/src/main/java/sootup/java/core/JavaIdentifierFactory.java

View check run for this annotation

Codecov / codecov/patch

sootup.java.core/src/main/java/sootup/java/core/JavaIdentifierFactory.java#L239

Added line #L239 was not covered by tests
}

@Override
Expand Down
Loading
Loading