summaryrefslogtreecommitdiffstats
path: root/base/android
diff options
context:
space:
mode:
authorhusky@chromium.org <husky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-30 13:40:38 +0000
committerhusky@chromium.org <husky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-30 13:40:38 +0000
commitd31afe7d7857c68d4ea8d9bccb2a70688a4f2edd (patch)
tree429d6235f45f48cfb486970b2d0c917a0829e75b /base/android
parentcd1177991859a25f39dc70502ad68dae82e9ec8e (diff)
downloadchromium_src-d31afe7d7857c68d4ea8d9bccb2a70688a4f2edd.zip
chromium_src-d31afe7d7857c68d4ea8d9bccb2a70688a4f2edd.tar.gz
chromium_src-d31afe7d7857c68d4ea8d9bccb2a70688a4f2edd.tar.bz2
Fix segfault in JNIEnv function hooks for test
On newer JB builds, the JNINativeInterface struct appears to be held in read-only memory so attempting to repoint individual function pointers in it causes segfault. So instead we repoint the top-level struct pointer to refer to our own copy held in read/write memory. BUG=137348 TEST=JNIAndroidTest Review URL: https://chromiumcodereview.appspot.com/10828050 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148943 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/android')
-rw-r--r--base/android/jni_android_unittest.cc26
-rw-r--r--base/android/scoped_java_ref_unittest.cc29
2 files changed, 33 insertions, 22 deletions
diff --git a/base/android/jni_android_unittest.cc b/base/android/jni_android_unittest.cc
index 5f5165a..abecad7 100644
--- a/base/android/jni_android_unittest.cc
+++ b/base/android/jni_android_unittest.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/jni_android.h"
+#include "base/at_exit.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
@@ -21,14 +22,14 @@ const char* g_last_method;
const char* g_last_jni_signature;
jmethodID g_last_method_id;
-JNINativeInterface g_previous_functions = {0};
+const JNINativeInterface* g_previous_functions;
jmethodID GetMethodIDWrapper(JNIEnv* env, jclass clazz, const char* method,
const char* jni_signature) {
g_last_method = method;
g_last_jni_signature = jni_signature;
- g_last_method_id = g_previous_functions.GetMethodID(env, clazz, method,
- jni_signature);
+ g_last_method_id = g_previous_functions->GetMethodID(env, clazz, method,
+ jni_signature);
return g_last_method_id;
}
@@ -38,15 +39,16 @@ class JNIAndroidTest : public testing::Test {
protected:
virtual void SetUp() {
JNIEnv* env = AttachCurrentThread();
- g_previous_functions = *env->functions;
- JNINativeInterface* native_interface =
- const_cast<JNINativeInterface*>(env->functions);
- native_interface->GetMethodID = &GetMethodIDWrapper;
+ g_previous_functions = env->functions;
+ hooked_functions = *g_previous_functions;
+ env->functions = &hooked_functions;
+ hooked_functions.GetMethodID = &GetMethodIDWrapper;
}
virtual void TearDown() {
JNIEnv* env = AttachCurrentThread();
- *(const_cast<JNINativeInterface*>(env->functions)) = g_previous_functions;
+ env->functions = g_previous_functions;
+ Reset();
}
void Reset() {
@@ -54,6 +56,12 @@ class JNIAndroidTest : public testing::Test {
g_last_jni_signature = 0;
g_last_method_id = NULL;
}
+ // Needed to cleanup the cached method map in the implementation between
+ // runs (e.g. if using --gtest_repeat)
+ base::ShadowingAtExitManager exit_manager;
+ // From JellyBean release, the instance of this struct provided in JNIEnv is
+ // read-only, so we deep copy it to allow individual functions to be hooked.
+ JNINativeInterface hooked_functions;
};
TEST_F(JNIAndroidTest, GetMethodIDFromClassNameCaching) {
diff --git a/base/android/scoped_java_ref_unittest.cc b/base/android/scoped_java_ref_unittest.cc
index f8bc675..36f253c 100644
--- a/base/android/scoped_java_ref_unittest.cc
+++ b/base/android/scoped_java_ref_unittest.cc
@@ -15,26 +15,26 @@ namespace {
int g_local_refs = 0;
int g_global_refs = 0;
-JNINativeInterface g_previous_functions = {0};
+const JNINativeInterface* g_previous_functions;
jobject NewGlobalRef(JNIEnv* env, jobject obj) {
++g_global_refs;
- return g_previous_functions.NewGlobalRef(env, obj);
+ return g_previous_functions->NewGlobalRef(env, obj);
}
void DeleteGlobalRef(JNIEnv* env, jobject obj) {
--g_global_refs;
- return g_previous_functions.DeleteGlobalRef(env, obj);
+ return g_previous_functions->DeleteGlobalRef(env, obj);
}
jobject NewLocalRef(JNIEnv* env, jobject obj) {
++g_local_refs;
- return g_previous_functions.NewLocalRef(env, obj);
+ return g_previous_functions->NewLocalRef(env, obj);
}
void DeleteLocalRef(JNIEnv* env, jobject obj) {
--g_local_refs;
- return g_previous_functions.DeleteLocalRef(env, obj);
+ return g_previous_functions->DeleteLocalRef(env, obj);
}
} // namespace
@@ -44,21 +44,24 @@ class ScopedJavaRefTest : public testing::Test {
g_local_refs = 0;
g_global_refs = 0;
JNIEnv* env = AttachCurrentThread();
- g_previous_functions = *env->functions;
+ g_previous_functions = env->functions;
+ hooked_functions = *g_previous_functions;
+ env->functions = &hooked_functions;
// We inject our own functions in JNINativeInterface so we can keep track
// of the reference counting ourselves.
- JNINativeInterface* native_interface =
- const_cast<JNINativeInterface*>(env->functions);
- native_interface->NewGlobalRef = &NewGlobalRef;
- native_interface->DeleteGlobalRef = &DeleteGlobalRef;
- native_interface->NewLocalRef = &NewLocalRef;
- native_interface->DeleteLocalRef = &DeleteLocalRef;
+ hooked_functions.NewGlobalRef = &NewGlobalRef;
+ hooked_functions.DeleteGlobalRef = &DeleteGlobalRef;
+ hooked_functions.NewLocalRef = &NewLocalRef;
+ hooked_functions.DeleteLocalRef = &DeleteLocalRef;
}
virtual void TearDown() {
JNIEnv* env = AttachCurrentThread();
- *(const_cast<JNINativeInterface*>(env->functions)) = g_previous_functions;
+ env->functions = g_previous_functions;
}
+ // From JellyBean release, the instance of this struct provided in JNIEnv is
+ // read-only, so we deep copy it to allow individual functions to be hooked.
+ JNINativeInterface hooked_functions;
};
// The main purpose of this is testing the various conversions compile.