The verifier would treat the result of merge(uninitialized, null) as
an uninitialized value, allowing a constructor to be called on null.
This patch conservatively prevents any usage of the merged register
by treating it as conflicting. Note that this could be relaxed with
a new common type for initialized and uninitialized references.
Bug:
26579108
Bug:
22411633
Change-Id: Ic5a1a3909c80287deece92dbb3254f437074e9b6
// float/long/double MERGE float/long/double_constant => float/long/double
return SelectNonConstant(*this, incoming_type);
} 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()) {
+ 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 (IsZero() || incoming_type.IsZero()) {
+ return SelectNonConstant(*this, incoming_type); // 0 MERGE ref => ref
} else if (IsJavaLangObject() || incoming_type.IsJavaLangObject()) {
return reg_types->JavaLangObject(false); // Object MERGE ref => Object
} else if (IsUnresolvedTypes() || incoming_type.IsUnresolvedTypes()) {
return v2
.end method
-
-# Test throwing and catching an exception between String's allocation and initialization.
-
-## CHECK-START: void TestCase.catchNewInstance() register (after)
-## CHECK-DAG: <<Null:l\d+>> NullConstant
-## CHECK-DAG: <<Zero:i\d+>> IntConstant 0
-## CHECK-DAG: <<String:l\d+>> NewInstance
-## CHECK-DAG: <<UTF8:l\d+>> LoadString
-## CHECK-DAG: InvokeStaticOrDirect [<<Null>>,<<UTF8>>] env:[[<<String>>,<<Zero>>,<<UTF8>>]]
-## CHECK-DAG: Phi [<<Null>>,<<Null>>,<<String>>] reg:0 is_catch_phi:true
-
-.method public static catchNewInstance()V
- .registers 3
-
- const v0, 0x0
- :try_start
- new-instance v0, Ljava/lang/String;
-
- # Calling String.<init> on null byte array will throw NullPointerException
- # with v0 = new-instance.
- const v1, 0x0
- const-string v2, "UTF8"
- invoke-direct {v0, v1, v2}, Ljava/lang/String;-><init>([BLjava/lang/String;)V
- :try_end
- .catchall {:try_start .. :try_end} :catch
- return-void
-
- # Catch exception and test v0. Do not throw if it is not null.
- :catch
- move-exception v1
- if-nez v0, :return
- throw v1
-
- :return
- return-void
-
-.end method
}
}
}
-
- {
- c.getMethod("catchNewInstance").invoke(null, (Object[]) null);
- }
}
}
b/25494456
b/21869691
b/26143249
+b/26579108
Done!
--- /dev/null
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LB26579108;
+.super Ljava/lang/Object;
+
+# Ensure that merging uninitialized type and null does not pass verification.
+
+.field public static field:I
+
+.method public static run()Ljava/lang/String;
+ .registers 2
+ new-instance v0, Ljava/lang/String;
+
+ sget v1, LB26579108;->field:I
+ if-eqz v1, :cond_5
+
+ const/4 v0, 0x0
+ :cond_5
+
+ invoke-direct {v0}, Ljava/lang/String;-><init>()V
+ return-object v0
+ .end method
new IncompatibleClassChangeError(), null));
testCases.add(new TestCase("b/26143249", "B26143249", "run", null,
new AbstractMethodError(), null));
+ testCases.add(new TestCase("b/26579108", "B26579108", "run", null, new VerifyError(),
+ null));
}
public void runTests() {
if (tc.expectedException != null) {
errorReturn = new IllegalStateException("Expected an exception in test " +
tc.testName);
- }
- if (tc.expectedReturn == null && retValue != null) {
+ } else if (tc.expectedReturn == null && retValue != null) {
errorReturn = new IllegalStateException("Expected a null result in test " +
tc.testName);
} else if (tc.expectedReturn != null &&