diff options
| -rw-r--r-- | runtime/openjdkjvmti/ti_redefine.cc | 9 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/transform.cc | 7 | ||||
| -rw-r--r-- | test/921-hello-failure/expected.txt | 3 | ||||
| -rw-r--r-- | test/921-hello-failure/src/Main.java | 1 | ||||
| -rw-r--r-- | test/921-hello-failure/src/Unmodifiable.java | 52 |
5 files changed, 71 insertions, 1 deletions
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc index 7a69078391..a173a4abdd 100644 --- a/runtime/openjdkjvmti/ti_redefine.cc +++ b/runtime/openjdkjvmti/ti_redefine.cc @@ -325,12 +325,19 @@ jvmtiError Redefiner::RedefineClasses(ArtJvmTiEnv* env, std::vector<ArtClassDefinition> def_vector; def_vector.reserve(class_count); for (jint i = 0; i < class_count; i++) { + jboolean is_modifiable = JNI_FALSE; + jvmtiError res = env->IsModifiableClass(definitions[i].klass, &is_modifiable); + if (res != OK) { + return res; + } else if (!is_modifiable) { + return ERR(UNMODIFIABLE_CLASS); + } // We make a copy of the class_bytes to pass into the retransformation. // This makes cleanup easier (since we unambiguously own the bytes) and also is useful since we // will need to keep the original bytes around unaltered for subsequent RetransformClasses calls // to get the passed in bytes. unsigned char* class_bytes_copy = nullptr; - jvmtiError res = env->Allocate(definitions[i].class_byte_count, &class_bytes_copy); + res = env->Allocate(definitions[i].class_byte_count, &class_bytes_copy); if (res != OK) { return res; } diff --git a/runtime/openjdkjvmti/transform.cc b/runtime/openjdkjvmti/transform.cc index 36421b9137..bd52cbb7f9 100644 --- a/runtime/openjdkjvmti/transform.cc +++ b/runtime/openjdkjvmti/transform.cc @@ -109,6 +109,13 @@ jvmtiError Transformer::RetransformClasses(ArtJvmTiEnv* env, std::vector<ArtClassDefinition> definitions; jvmtiError res = OK; for (jint i = 0; i < class_count; i++) { + jboolean is_modifiable = JNI_FALSE; + res = env->IsModifiableClass(classes[i], &is_modifiable); + if (res != OK) { + return res; + } else if (!is_modifiable) { + return ERR(UNMODIFIABLE_CLASS); + } ArtClassDefinition def; res = FillInTransformationData(env, classes[i], &def); if (res != OK) { diff --git a/test/921-hello-failure/expected.txt b/test/921-hello-failure/expected.txt index a5dc10d59c..fdbfbe2191 100644 --- a/test/921-hello-failure/expected.txt +++ b/test/921-hello-failure/expected.txt @@ -50,3 +50,6 @@ hello there - MissingField hello there again - FieldChange Transformation error : java.lang.Exception(Failed to redefine class <LTransform4;> due to JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED) hello there again - FieldChange +hello - Unmodifiable +Transformation error : java.lang.Exception(Failed to redefine class <[LTransform;> due to JVMTI_ERROR_UNMODIFIABLE_CLASS) +hello - Unmodifiable diff --git a/test/921-hello-failure/src/Main.java b/test/921-hello-failure/src/Main.java index 5bbe2b5479..6779ed862a 100644 --- a/test/921-hello-failure/src/Main.java +++ b/test/921-hello-failure/src/Main.java @@ -32,6 +32,7 @@ public class Main { NewField.doTest(new Transform()); MissingField.doTest(new Transform4("there")); FieldChange.doTest(new Transform4("there again")); + Unmodifiable.doTest(new Transform[] { new Transform(), }); } // Transforms the class. This throws an exception if something goes wrong. diff --git a/test/921-hello-failure/src/Unmodifiable.java b/test/921-hello-failure/src/Unmodifiable.java new file mode 100644 index 0000000000..ad05f51f9f --- /dev/null +++ b/test/921-hello-failure/src/Unmodifiable.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 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. + */ + +import java.util.Base64; + +class Unmodifiable { + // The following is a base64 encoding of a valid class file. + private static final byte[] CLASS_BYTES = Base64.getDecoder().decode( + "yv66vgAAADQAFQoABgAPBwAQCAARCgACABIHABMHABQBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAP" + + "TGluZU51bWJlclRhYmxlAQAFc2F5SGkBABUoTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3VyY2VG" + + "aWxlAQAOVHJhbnNmb3JtLmphdmEMAAcACAEAD2phdmEvbGFuZy9FcnJvcgEAFVNob3VsZCBub3Qg" + + "YmUgY2FsbGVkIQwABwAMAQAJVHJhbnNmb3JtAQAQamF2YS9sYW5nL09iamVjdAAgAAUABgAAAAAA" + + "AgAAAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAIAAAALAAwAAQAJAAAA" + + "IgADAAIAAAAKuwACWRIDtwAEvwAAAAEACgAAAAYAAQAAAAQAAQANAAAAAgAO"); + private static final byte[] DEX_BYTES = Base64.getDecoder().decode( + "ZGV4CjAzNQCrV81cy4Q+YKMMMqc0bZEO5Y1X5u7irPeQAgAAcAAAAHhWNBIAAAAAAAAAAPwBAAAL" + + "AAAAcAAAAAUAAACcAAAAAgAAALAAAAAAAAAAAAAAAAQAAADIAAAAAQAAAOgAAACIAQAACAEAAEoB" + + "AABSAQAAXwEAAHIBAACGAQAAmgEAALEBAADBAQAAxAEAAMgBAADcAQAAAQAAAAIAAAADAAAABAAA" + + "AAcAAAAHAAAABAAAAAAAAAAIAAAABAAAAEQBAAAAAAAAAAAAAAAAAQAKAAAAAQABAAAAAAACAAAA" + + "AAAAAAAAAAAAAAAAAgAAAAAAAAAGAAAAAAAAAO4BAAAAAAAAAQABAAEAAADjAQAABAAAAHAQAwAA" + + "AA4ABAACAAIAAADoAQAACQAAACIAAQAbAQUAAABwIAIAEAAnAAAAAQAAAAMABjxpbml0PgALTFRy" + + "YW5zZm9ybTsAEUxqYXZhL2xhbmcvRXJyb3I7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xh" + + "bmcvU3RyaW5nOwAVU2hvdWxkIG5vdCBiZSBjYWxsZWQhAA5UcmFuc2Zvcm0uamF2YQABVgACVkwA" + + "EmVtaXR0ZXI6IGphY2stNC4yNAAFc2F5SGkAAgAHDgAEAQAHDgAAAAEBAICABIgCAQCgAgwAAAAA" + + "AAAAAQAAAAAAAAABAAAACwAAAHAAAAACAAAABQAAAJwAAAADAAAAAgAAALAAAAAFAAAABAAAAMgA" + + "AAAGAAAAAQAAAOgAAAABIAAAAgAAAAgBAAABEAAAAQAAAEQBAAACIAAACwAAAEoBAAADIAAAAgAA" + + "AOMBAAAAIAAAAQAAAO4BAAAAEAAAAQAAAPwBAAA="); + + public static void doTest(Transform[] ts) { + ts[0].sayHi("Unmodifiable"); + try { + Main.doCommonClassRedefinition(Transform[].class, CLASS_BYTES, DEX_BYTES); + } catch (Exception e) { + System.out.println( + "Transformation error : " + e.getClass().getName() + "(" + e.getMessage() + ")"); + } + ts[0].sayHi("Unmodifiable"); + } +} |