diff options
| author | 2015-07-21 16:32:22 +0000 | |
|---|---|---|
| committer | 2015-07-21 16:32:22 +0000 | |
| commit | b203b332be18c7bf1e4b3be3e0ddd345174e0517 (patch) | |
| tree | 8d3773c26d9ccd57849aa4ae8a95caed6a27137c | |
| parent | 364fa537a78ef67825a3f7aa6b4bf8ff32c39266 (diff) | |
| parent | 891dfaa94eda54ab620d203200191c4be46afb70 (diff) | |
Merge "ART: Fix UninitializedReference handling"
| -rw-r--r-- | runtime/verifier/reg_type.cc | 10 | ||||
| -rw-r--r-- | test/800-smali/expected.txt | 5 | ||||
| -rw-r--r-- | test/800-smali/smali/b_22411633_1.smali | 35 | ||||
| -rw-r--r-- | test/800-smali/smali/b_22411633_2.smali | 45 | ||||
| -rw-r--r-- | test/800-smali/smali/b_22411633_3.smali | 31 | ||||
| -rw-r--r-- | test/800-smali/smali/b_22411633_4.smali | 25 | ||||
| -rw-r--r-- | test/800-smali/smali/b_22411633_5.smali | 28 | ||||
| -rw-r--r-- | test/800-smali/src/Main.java | 10 |
8 files changed, 184 insertions, 5 deletions
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 9c528190b2..6e23234182 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -690,6 +690,11 @@ const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_ty } else if (IsReferenceTypes() && incoming_type.IsReferenceTypes()) { if (IsZero() || incoming_type.IsZero()) { return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref + } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) { + // Something that is uninitialized hasn't had its constructor called. Unitialized types are + // special. They may only ever be merged with themselves (must be taken care of by the + // caller of Merge(), see the DCHECK on entry). So mark any other merge as conflicting here. + return conflict; } else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) { return reg_types->JavaLangObject(false); // Object MERGE ref => Object } else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) { @@ -698,11 +703,6 @@ const RegType& RegType::Merge(const RegType& incoming_type, RegTypeCache* reg_ty // type that reflects our lack of knowledge and that allows the rest of the unresolved // mechanics to continue. return reg_types->FromUnresolvedMerge(*this, incoming_type); - } else if (IsUninitializedTypes() || incoming_type.IsUninitializedTypes()) { - // Something that is uninitialized hasn't had its constructor called. Mark any merge - // of this type with something that is initialized as conflicting. The cases of a merge - // with itself, 0 or Object are handled above. - return conflict; } else { // Two reference types, compute Join mirror::Class* c1 = GetClass(); mirror::Class* c2 = incoming_type.GetClass(); diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt index 4c17240455..fd9fcafbff 100644 --- a/test/800-smali/expected.txt +++ b/test/800-smali/expected.txt @@ -31,4 +31,9 @@ b/22244733 b/22331663 b/22331663 (pass) b/22331663 (fail) +b/22411633 (1) +b/22411633 (2) +b/22411633 (3) +b/22411633 (4) +b/22411633 (5) Done! diff --git a/test/800-smali/smali/b_22411633_1.smali b/test/800-smali/smali/b_22411633_1.smali new file mode 100644 index 0000000000..ffc82a86ae --- /dev/null +++ b/test/800-smali/smali/b_22411633_1.smali @@ -0,0 +1,35 @@ +.class public LB22411633_1; +.super Ljava/lang/Object; + + +.method public static run(Z)V +.registers 6 + # Make v3 & v4 defined, just use null. + const v3, 0 + const v4, 0 + + # Allocate a java.lang.Object (do not initialize). + new-instance v4, Ljava/lang/Object; + + # Branch forward. + if-eqz v5, :LabelMerge + + # Just some random work. + add-int/lit16 v3, v3, 1 + + # Another branch forward. + if-nez v5, :LabelMerge + + # Some more random work, technically dead, but reachable. + add-int/lit16 v3, v3, 1 + +:LabelMerge + # v4 is still an uninitialized reference here. Initialize it. + invoke-direct {v4}, Ljava/lang/Object;-><init>()V + + # And test whether it's initialized by calling hashCode. + invoke-virtual {v4}, Ljava/lang/Object;->hashCode()I + + return-void + +.end method diff --git a/test/800-smali/smali/b_22411633_2.smali b/test/800-smali/smali/b_22411633_2.smali new file mode 100644 index 0000000000..9f27c4cb12 --- /dev/null +++ b/test/800-smali/smali/b_22411633_2.smali @@ -0,0 +1,45 @@ +.class public LB22411633_2; +.super Ljava/lang/Object; + + +.method public static run(Z)V +.registers 6 + # Make v3 & v4 defined, just use null. + const v3, 0 + const v4, 0 + + # Allocate a java.lang.Object (do not initialize). + new-instance v4, Ljava/lang/Object; + + # Branch forward. + if-eqz v5, :LabelMerge + + # Create a non-precise object reference. We can do this by merging to objects together + # that only have Object as a common ancestor. + + # Allocate a java.lang.Object and initialize it. + new-instance v4, Ljava/lang/Object; + invoke-direct {v4}, Ljava/lang/Object;-><init>()V + + if-nez v5, :LabelMergeObject + + new-instance v4, Ljava/lang/Integer; + invoke-direct {v4}, Ljava/lang/Integer;-><init>()V + +:LabelMergeObject + + # Dummy work to separate blocks. At this point, v4 is of type Reference<Object>. + add-int/lit16 v3, v3, 1 + +:LabelMerge + # Merge the uninitialized Object from line 12 with the reference to Object from 31. Older + # rules set any reference merged with Object to Object. This is wrong in the case of the + # other reference being an uninitialized reference, as we'd suddenly allow calling on it. + + # Test whether it's some initialized reference by calling hashCode. This should fail, as we + # merged initialized and uninitialized. + invoke-virtual {v4}, Ljava/lang/Object;->hashCode()I + + return-void + +.end method diff --git a/test/800-smali/smali/b_22411633_3.smali b/test/800-smali/smali/b_22411633_3.smali new file mode 100644 index 0000000000..d1212f13dd --- /dev/null +++ b/test/800-smali/smali/b_22411633_3.smali @@ -0,0 +1,31 @@ +.class public LB22411633_3; +.super Ljava/lang/Object; + + +.method public static run(Z)V +.registers 6 + # Make v3 & v4 defined, just use null. + const v3, 0 + const v4, 0 + + # Allocate a java.lang.Object (do not initialize). + new-instance v4, Ljava/lang/Object; + + # Branch forward. + if-eqz v5, :LabelMerge + + # Create an initialized Object. + new-instance v4, Ljava/lang/Object; + invoke-direct {v4}, Ljava/lang/Object;-><init>()V + + # Just some random work. + add-int/lit16 v3, v3, 1 + +:LabelMerge + # At this point, an initialized and an uninitialized reference are merged. However, the + # merge is only from forward branches. If the conflict isn't used (as here), this should + # pass the verifier. + + return-void + +.end method diff --git a/test/800-smali/smali/b_22411633_4.smali b/test/800-smali/smali/b_22411633_4.smali new file mode 100644 index 0000000000..503ca99569 --- /dev/null +++ b/test/800-smali/smali/b_22411633_4.smali @@ -0,0 +1,25 @@ +.class public LB22411633_4; +.super Ljava/lang/Object; + + +.method public static run(Z)V +.registers 6 + # Do not merge into the backward branch target. + goto :LabelEntry + +:LabelBwd + # At this point v4 is an uninitialized reference. This should fail to verify. + # Note: we make sure that it is an uninitialized reference and not a conflict in sister + # file b_22411633_bwdok.smali. + invoke-virtual {v4}, Ljava/lang/Object;->hashCode()I + +:LabelEntry + # Allocate a java.lang.Object (do not initialize). + new-instance v4, Ljava/lang/Object; + + # Branch backward. + if-eqz v5, :LabelBwd + + return-void + +.end method diff --git a/test/800-smali/smali/b_22411633_5.smali b/test/800-smali/smali/b_22411633_5.smali new file mode 100644 index 0000000000..b7964f64a5 --- /dev/null +++ b/test/800-smali/smali/b_22411633_5.smali @@ -0,0 +1,28 @@ +.class public LB22411633_5; +.super Ljava/lang/Object; + + +.method public static run(Z)V +.registers 6 + # Do not merge into the backward branch target. + goto :LabelEntry + +:LabelBwd + # At this point v4 is an uninitialized reference. We should be able to initialize here + # and call a method afterwards. + invoke-direct {v4}, Ljava/lang/Object;-><init>()V + invoke-virtual {v4}, Ljava/lang/Object;->hashCode()I + + # Make sure this is not an infinite loop. + const v5, 1 + +:LabelEntry + # Allocate a java.lang.Object (do not initialize). + new-instance v4, Ljava/lang/Object; + + # Branch backward. + if-eqz v5, :LabelBwd + + return-void + +.end method diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java index 8be6418d77..8da2af4e84 100644 --- a/test/800-smali/src/Main.java +++ b/test/800-smali/src/Main.java @@ -109,6 +109,16 @@ public class Main { new Object[] { false }, null, null)); testCases.add(new TestCase("b/22331663 (fail)", "B22331663Fail", "run", new Object[] { false }, new VerifyError(), null)); + testCases.add(new TestCase("b/22411633 (1)", "B22411633_1", "run", new Object[] { false }, + null, null)); + testCases.add(new TestCase("b/22411633 (2)", "B22411633_2", "run", new Object[] { false }, + new VerifyError(), null)); + testCases.add(new TestCase("b/22411633 (3)", "B22411633_3", "run", new Object[] { false }, + null, null)); + testCases.add(new TestCase("b/22411633 (4)", "B22411633_4", "run", new Object[] { false }, + new VerifyError(), null)); + testCases.add(new TestCase("b/22411633 (5)", "B22411633_5", "run", new Object[] { false }, + null, null)); } public void runTests() { |