Skip to content

Commit

Permalink
Merge pull request #2068 from MarcMil/fix-dex-annotations
Browse files Browse the repository at this point in the history
Fix handling of Annotations in Dex code & UnconditionalBranchFolder
  • Loading branch information
StevenArzt authored Apr 16, 2024
2 parents 7f43e77 + 29ef343 commit 62926b9
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 8 deletions.
36 changes: 34 additions & 2 deletions src/main/java/soot/dexpler/DexAnnotation.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
Expand Down Expand Up @@ -113,6 +115,18 @@ public class DexAnnotation {
private final SootClass clazz;
private final Dependencies deps;

protected static Set<String> isHandled = new HashSet<>();

static {
isHandled.add(SootToDexUtils.getDexClassName(DALVIK_ANNOTATION_DEFAULT));
isHandled.add(SootToDexUtils.getDexClassName(DALVIK_ANNOTATION_SIGNATURE));
isHandled.add(SootToDexUtils.getDexClassName(DALVIK_ANNOTATION_MEMBERCLASSES));
isHandled.add(SootToDexUtils.getDexClassName(DALVIK_ANNOTATION_INNERCLASS));
isHandled.add(SootToDexUtils.getDexClassName(DALVIK_ANNOTATION_ENCLOSINGMETHOD));
isHandled.add(SootToDexUtils.getDexClassName(DALVIK_ANNOTATION_ENCLOSINGCLASS));
isHandled.add(SootToDexUtils.getDexClassName(JAVA_DEPRECATED));
}

public DexAnnotation(SootClass clazz, Dependencies deps) {
this.clazz = clazz;
this.deps = deps;
Expand Down Expand Up @@ -161,8 +175,11 @@ public void handleClassAnnotation(ClassDef classDef) {
// to methods through the creation of new
// AnnotationDefaultTag.
VisibilityAnnotationTag vt = (VisibilityAnnotationTag) t;
for (AnnotationTag a : vt.getAnnotations()) {
Iterator<AnnotationTag> it = vt.getAnnotations().iterator();
while (it.hasNext()) {
AnnotationTag a = it.next();
if (a.getType().equals("Ldalvik/annotation/AnnotationDefault;")) {
it.remove();
for (AnnotationElem ae : a.getElems()) {
if (ae instanceof AnnotationAnnotationElem) {
AnnotationAnnotationElem aae = (AnnotationAnnotationElem) ae;
Expand Down Expand Up @@ -228,8 +245,19 @@ public void handleClassAnnotation(ClassDef classDef) {
}
}
}
if (!(vt.getVisibility() == AnnotationConstants.RUNTIME_INVISIBLE)) {
if (vt.getVisibility() == AnnotationConstants.RUNTIME_INVISIBLE) {
clazz.addTag(vt);
} else {
// filter out the tags we handle explicitly
VisibilityAnnotationTag vbCopy = new VisibilityAnnotationTag(vt.getVisibility());
for (AnnotationTag tf : vt.getAnnotations()) {
if (!isHandled(tf)) {
vbCopy.addAnnotation(tf);
}
}
if (vbCopy.getAnnotations() != null && !vbCopy.getAnnotations().isEmpty()) {
clazz.addTag(vbCopy);
}
}
} else {
clazz.addTag(t);
Expand All @@ -238,6 +266,10 @@ public void handleClassAnnotation(ClassDef classDef) {
}
}

private boolean isHandled(AnnotationTag tf) {
return isHandled.contains(tf.getType());
}

private Type getSootType(AnnotationElem e) {
Type annotationType;
switch (e.getKind()) {
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/soot/jimple/BranchableStmt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package soot.jimple;

/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 1999 Raja Vallee-Rai
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/

import soot.Unit;
import soot.UnitBox;

public interface BranchableStmt extends Stmt {
public Unit getTarget();

public void setTarget(Unit target);

public UnitBox getTargetBox();
}
2 changes: 1 addition & 1 deletion src/main/java/soot/jimple/GotoStmt.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import soot.Unit;
import soot.UnitBox;

public interface GotoStmt extends Stmt {
public interface GotoStmt extends BranchableStmt {
public Unit getTarget();

public void setTarget(Unit target);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/soot/jimple/internal/JIfStmt.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import soot.baf.Baf;
import soot.jimple.AbstractJimpleValueSwitch;
import soot.jimple.BinopExpr;
import soot.jimple.BranchableStmt;
import soot.jimple.ConvertToBaf;
import soot.jimple.EqExpr;
import soot.jimple.GeExpr;
Expand All @@ -50,7 +51,7 @@
import soot.jimple.StmtSwitch;
import soot.util.Switch;

public class JIfStmt extends AbstractStmt implements IfStmt {
public class JIfStmt extends AbstractStmt implements IfStmt, BranchableStmt {

protected final ValueBox conditionBox;
protected final UnitBox targetBox;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import soot.Unit;
import soot.UnitBox;
import soot.Value;
import soot.jimple.BranchableStmt;
import soot.jimple.ConditionExpr;
import soot.jimple.GotoStmt;
import soot.jimple.IfStmt;
Expand Down Expand Up @@ -213,6 +214,37 @@ public Result transform() {
succAsGoto.setTarget(ifTarget);
stmtAsIfStmt.setTarget(gotoTarget);
ifTarget = gotoTarget;
// We need to check whether anyone has a goto to the "goto X", because this no has to also go
// to Y

// If we wouldn't do that, we would e.g. go from
// if $i0 == 6 goto label04;
// label03:
// goto label21;
// ...
// goto label3;

// to
// if $i0 != 6 goto label21;
// label03:
// goto label04;
// label04:
// ...
// goto label03;
// this would alter the semantics, since the previous go-tos now go to the other branch!
if (!succAsGoto.getBoxesPointingToThis().isEmpty()) {
// we cannot simply use getBoxesPointingToThis, because we do not want to update
// trap references
for (Unit i : units) {
if (i instanceof BranchableStmt) {
BranchableStmt b = (BranchableStmt) i;
if (b.getTarget() == succAsGoto) {
b.setTarget(gotoTarget);
}
}
}
}

// NOTE: No need to remove the goto [successor] because it
// is processed by the next iteration of the main loop.
// NOTE: Nothing is removed here, it is a simple refactoring.
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/soot/toDex/DexPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,9 @@ private EncodedValue buildEncodedValueForAnnotation(AnnotationElem elem) {
Collection<AnnotationElem> elems = e.getValue().getElems();
if (!elems.isEmpty()) {
elements = new ArrayList<AnnotationElement>();
Set<String> alreadyWritten = new HashSet<String>();
Set<AnnotationElem> alreadyWritten = new HashSet<AnnotationElem>();
for (AnnotationElem ae : elems) {
if (!alreadyWritten.add(ae.getName())) {
if (!alreadyWritten.add(ae)) {
throw new DexPrinterException("Duplicate annotation attribute: " + ae.getName());
}
elements.add(new ImmutableAnnotationElement(ae.getName(), buildEncodedValueForAnnotation(ae)));
Expand Down Expand Up @@ -670,7 +670,7 @@ protected void addClassDefinition(ClassDef classDef) {
}
}

private Set<Annotation> buildClassAnnotations(SootClass c) {
protected Set<Annotation> buildClassAnnotations(SootClass c) {
Set<String> skipList = new HashSet<String>();
Set<Annotation> annotations = buildCommonAnnotations(c, skipList);

Expand Down Expand Up @@ -855,7 +855,7 @@ private Set<Annotation> buildCommonAnnotations(AbstractHost host, Set<String> sk
return annotations;
}

private List<ImmutableAnnotation> buildVisibilityAnnotationTag(VisibilityAnnotationTag t, Set<String> skipList) {
protected List<ImmutableAnnotation> buildVisibilityAnnotationTag(VisibilityAnnotationTag t, Set<String> skipList) {
if (t.getAnnotations() == null) {
return Collections.emptyList();
}
Expand Down

0 comments on commit 62926b9

Please sign in to comment.