diff options
author | 2021-09-16 14:07:37 +0100 | |
---|---|---|
committer | 2021-09-16 16:57:39 +0000 | |
commit | f740be5efcc31826b29e5a23aa9a46a1d53d824d (patch) | |
tree | aad23d44c68daf27f16d3f2d4127394ebd12912f | |
parent | 7a3ccd0082aae9dad53733549e5d414af1de00d6 (diff) |
Handle the case the enclosing class is missing.
Fix a crash in ART when Class.getEnclosingClass was hitting a missing
class.
Test: 829-unresolved-enclosing
Bug: 195604858
Change-Id: I12cb8fbcc55f8f011303ffd6fe61537dd0b0f7f4
-rw-r--r-- | runtime/dex/dex_file_annotations.cc | 7 | ||||
-rw-r--r-- | runtime/mirror/throwable.cc | 4 | ||||
-rw-r--r-- | runtime/mirror/throwable.h | 1 | ||||
-rw-r--r-- | test/829-unresolved-enclosing/build | 38 | ||||
-rw-r--r-- | test/829-unresolved-enclosing/expected-stderr.txt | 0 | ||||
-rw-r--r-- | test/829-unresolved-enclosing/expected-stdout.txt | 0 | ||||
-rw-r--r-- | test/829-unresolved-enclosing/info.txt | 2 | ||||
-rw-r--r-- | test/829-unresolved-enclosing/src/Main.java | 57 |
8 files changed, 108 insertions, 1 deletions
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc index bae86deda4..a339ccd59c 100644 --- a/runtime/dex/dex_file_annotations.cc +++ b/runtime/dex/dex_file_annotations.cc @@ -1506,12 +1506,17 @@ ObjPtr<mirror::Class> GetDeclaringClass(Handle<mirror::Class> klass) { if (obj == nullptr) { return nullptr; } + if (!obj->IsClass()) { + // TypeNotPresentException, throw the NoClassDefFoundError. + Thread::Current()->SetException(obj->AsThrowable()->GetCause()); + return nullptr; + } return obj->AsClass(); } ObjPtr<mirror::Class> GetEnclosingClass(Handle<mirror::Class> klass) { ObjPtr<mirror::Class> declaring_class = GetDeclaringClass(klass); - if (declaring_class != nullptr) { + if (declaring_class != nullptr || Thread::Current()->IsExceptionPending()) { return declaring_class; } ClassData data(klass); diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc index a03277cc88..b538fa9125 100644 --- a/runtime/mirror/throwable.cc +++ b/runtime/mirror/throwable.cc @@ -171,5 +171,9 @@ ObjPtr<String> Throwable::GetDetailMessage() { return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_)); } +ObjPtr<Throwable> Throwable::GetCause() { + return GetFieldObject<Throwable>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_)); +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h index 50db34c5ba..995b04a6a0 100644 --- a/runtime/mirror/throwable.h +++ b/runtime/mirror/throwable.h @@ -43,6 +43,7 @@ class MANAGED Throwable : public Object { // overridden. Also it asserts rather than throwing exceptions. Currently this is only used // in cases like the verifier where the checks cannot fail and initCause isn't overridden. void SetCause(ObjPtr<Throwable> cause) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<Throwable> GetCause() REQUIRES_SHARED(Locks::mutator_lock_); void SetStackState(ObjPtr<Object> state) REQUIRES_SHARED(Locks::mutator_lock_); bool IsCheckedException() REQUIRES_SHARED(Locks::mutator_lock_); bool IsError() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/test/829-unresolved-enclosing/build b/test/829-unresolved-enclosing/build new file mode 100644 index 0000000000..163f8544ca --- /dev/null +++ b/test/829-unresolved-enclosing/build @@ -0,0 +1,38 @@ +#!/bin/bash +# +# Copyright (C) 2014 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. + +# Stop if something fails. +set -e + +export ORIGINAL_JAVAC="$JAVAC" + +# Wrapper function for javac which invokes the compiler and applies +# additional setup steps for the test. +function javac_wrapper { + set -e # Stop on error - the caller script may not have this set. + + $ORIGINAL_JAVAC "$@" + + # Remove class available at compile time but not at run time. + rm classes/MissingSuperClass.class +} + +export -f javac_wrapper +export JAVAC=javac_wrapper + +###################################################################### + +./default-build "$@" diff --git a/test/829-unresolved-enclosing/expected-stderr.txt b/test/829-unresolved-enclosing/expected-stderr.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/829-unresolved-enclosing/expected-stderr.txt diff --git a/test/829-unresolved-enclosing/expected-stdout.txt b/test/829-unresolved-enclosing/expected-stdout.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/829-unresolved-enclosing/expected-stdout.txt diff --git a/test/829-unresolved-enclosing/info.txt b/test/829-unresolved-enclosing/info.txt new file mode 100644 index 0000000000..714181e21f --- /dev/null +++ b/test/829-unresolved-enclosing/info.txt @@ -0,0 +1,2 @@ +Regression test for Class.enclosingClass when the enclosing class is absent at +runtime. diff --git a/test/829-unresolved-enclosing/src/Main.java b/test/829-unresolved-enclosing/src/Main.java new file mode 100644 index 0000000000..09962afd89 --- /dev/null +++ b/test/829-unresolved-enclosing/src/Main.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 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. + */ + +public class Main { + + public static void main(String[] args) throws ClassNotFoundException { + try { + System.out.println(SubClass.SubEnclosed.class.getEnclosingClass()); + throw new Error("Expected NoClassDefFoundError"); + } catch (NoClassDefFoundError e) { + } + try { + System.out.println(SubClass.SuperEnclosed.class.getEnclosingClass()); + throw new Error("Expected NoClassDefFoundError"); + } catch (NoClassDefFoundError e) { + } + + Class<?> cls = Class.forName("MissingSuperClass$1LocalClass"); + try { + System.out.println(cls.getEnclosingClass()); + throw new Error("Expected NoClassDefFoundError"); + } catch (NoClassDefFoundError e) { + } + try { + System.out.println(cls.getEnclosingMethod()); + throw new Error("Expected NoClassDefFoundError"); + } catch (NoClassDefFoundError e) { + } + } +} + +class MissingSuperClass { + static class SuperEnclosed {} + + static Object returnLocalClass() { + class LocalClass {} + return new LocalClass(); + } +} + +class SubClass extends MissingSuperClass { + static class SubEnclosed {} +} + |