Skip to content

Commit

Permalink
fix: additional checks for class signature
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Mar 22, 2020
1 parent dbd00d5 commit e09e933
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 4 deletions.
19 changes: 18 additions & 1 deletion jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -194,6 +195,10 @@ private void loadStaticValues(ClassDef cls, List<FieldNode> staticFields) throws
root().getConstValues().processConstFields(this, staticFields);
}

/**
* Class signature format:
* https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.9.1
*/
private void parseClassSignature() {
SignatureParser sp = SignatureParser.fromNode(this);
if (sp == null) {
Expand All @@ -203,7 +208,7 @@ private void parseClassSignature() {
// parse class generic map
generics = sp.consumeGenericTypeParameters();
// parse super class signature
superClass = sp.consumeType();
superClass = validateSuperCls(sp.consumeType(), superClass);
// parse interfaces signatures
for (int i = 0; i < interfaces.size(); i++) {
ArgType type = sp.consumeType();
Expand All @@ -218,6 +223,18 @@ private void parseClassSignature() {
}
}

private ArgType validateSuperCls(ArgType candidateType, ArgType currentType) {
if (!candidateType.isObject()) {
this.addComment("Incorrect class signature, super class is not object: " + SignatureParser.getSignature(this));
return currentType;
}
if (Objects.equals(candidateType.getObject(), this.getClassInfo().getType().getObject())) {
this.addComment("Incorrect class signature, super class is equals to this class: " + SignatureParser.getSignature(this));
return currentType;
}
return candidateType;
}

private void setFieldsTypesFromSignature() {
for (FieldNode field : fields) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,23 @@ public SignatureParser(String signature) {
mark = 0;
}

@SuppressWarnings("unchecked")
@Nullable
public static SignatureParser fromNode(IAttributeNode node) {
String signature = getSignature(node);
if (signature == null) {
return null;
}
return new SignatureParser(signature);
}

@SuppressWarnings("unchecked")
@Nullable
public static String getSignature(IAttributeNode node) {
Annotation a = node.getAnnotation(Consts.DALVIK_SIGNATURE);
if (a == null) {
return null;
}
String signature = mergeSignature((List<String>) a.getDefaultValue());
return new SignatureParser(signature);
return mergeSignature((List<String>) a.getDefaultValue());
}

private char next() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package jadx.tests.integration.generics;

import org.junit.jupiter.api.Test;

import jadx.tests.api.SmaliTest;

import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;

public class TestClassSignature extends SmaliTest {
// @formatter:off
/*
Incorrect class signature, super class is equals to this class: <T:Ljava/lang/Object;>Lgenerics/TestClassSignature<TT;>;
*/
// @formatter:on

@Test
public void test() {
assertThat(getClassNodeFromSmali())
.code()
.containsOne("Incorrect class signature")
.doesNotContain("StackOverflowError");
}
}
115 changes: 115 additions & 0 deletions jadx-core/src/test/smali/generics/TestClassSignature.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
.class public abstract Lgenerics/TestClassSignature;
.super Ljava/lang/Object;
.source "SourceFile"

# interfaces
.implements Ljava/util/Iterator;


# annotations
.annotation system Ldalvik/annotation/Signature;
value = {
"<T:",
"Ljava/lang/Object;",
">",
"Lgenerics/TestClassSignature<",
"TT;>;"
}
.end annotation


# instance fields
.field public f:Ljava/lang/Object;
.annotation system Ldalvik/annotation/Signature;
value = {
"TT;"
}
.end annotation
.end field


# direct methods
.method public constructor <init>(Ljava/lang/Object;)V
.registers 2
.annotation system Ldalvik/annotation/Signature;
value = {
"(TT;)V"
}
.end annotation

invoke-direct {p0}, Ljava/lang/Object;-><init>()V
iput-object p1, p0, Lgenerics/TestClassSignature;->f:Ljava/lang/Object;
return-void
.end method


# virtual methods
.method public abstract a(Ljava/lang/Object;)Ljava/lang/Object;
.annotation system Ldalvik/annotation/Signature;
value = {
"(TT;)TT;"
}
.end annotation
.end method

.method public final hasNext()Z
.registers 2

.line 1
iget-object v0, p0, Lgenerics/TestClassSignature;->f:Ljava/lang/Object;
if-eqz v0, :cond_6
const/4 v0, 0x1
goto :goto_7

:cond_6
const/4 v0, 0x0

:goto_7
return v0
.end method

.method public final next()Ljava/lang/Object;
.registers 3
.annotation system Ldalvik/annotation/Signature;
value = {
"()TT;"
}
.end annotation

invoke-virtual {p0}, Lgenerics/TestClassSignature;->hasNext()Z
move-result v0
if-eqz v0, :cond_1b

:try_start_6
iget-object v0, p0, Lgenerics/TestClassSignature;->f:Ljava/lang/Object;
:try_end_8
.catchall {:try_start_6 .. :try_end_8} :catchall_11

iget-object v1, p0, Lgenerics/TestClassSignature;->f:Ljava/lang/Object;
invoke-virtual {p0, v1}, Lgenerics/TestClassSignature;->a(Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v1
iput-object v1, p0, Lgenerics/TestClassSignature;->f:Ljava/lang/Object;
return-object v0

:catchall_11
move-exception v0

iget-object v1, p0, Lgenerics/TestClassSignature;->f:Ljava/lang/Object;
invoke-virtual {p0, v1}, Lgenerics/TestClassSignature;->a(Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v1
iput-object v1, p0, Lgenerics/TestClassSignature;->f:Ljava/lang/Object;
throw v0

:cond_1b
new-instance v0, Ljava/util/NoSuchElementException;
invoke-direct {v0}, Ljava/util/NoSuchElementException;-><init>()V
throw v0
.end method

.method public final remove()V
.registers 2

new-instance v0, Ljava/lang/UnsupportedOperationException;
invoke-direct {v0}, Ljava/lang/UnsupportedOperationException;-><init>()V
throw v0
.end method

0 comments on commit e09e933

Please sign in to comment.