summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/jni/android_os_Parcel.cpp93
1 files changed, 60 insertions, 33 deletions
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 9ae3d160be98..9c7ee0c641a6 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -638,50 +638,77 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
return ret;
}
+// String tries to allocate itself on the stack, within a known size, but will
+// make a heap allocation if not.
+template <size_t StackReserve>
+class StackString {
+public:
+ StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
+ LOG_ALWAYS_FATAL_IF(str == nullptr);
+ mSize = env->GetStringLength(str);
+ if (mSize > StackReserve) {
+ mStr = new jchar[mSize];
+ } else {
+ mStr = &mBuffer[0];
+ }
+ mEnv->GetStringRegion(str, 0, mSize, mStr);
+ }
+ ~StackString() {
+ if (mStr != &mBuffer[0]) {
+ delete[] mStr;
+ }
+ }
+ const jchar* str() { return mStr; }
+ jsize size() { return mSize; }
+
+private:
+ JNIEnv* mEnv;
+ jstring mJStr;
+
+ jchar mBuffer[StackReserve];
+ // pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
+ jchar* mStr;
+ jsize mSize;
+};
+
+// This size is chosen to be longer than most interface descriptors.
+// Ones longer than this will be allocated on the heap.
+typedef StackString<64> InterfaceDescriptorString;
+
static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
jstring name)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- // In the current implementation, the token is just the serialized interface name that
- // the caller expects to be invoking
- const jchar* str = env->GetStringCritical(name, 0);
- if (str != NULL) {
- parcel->writeInterfaceToken(String16(
- reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(name)));
- env->ReleaseStringCritical(name, str);
- }
+ if (parcel != nullptr) {
+ InterfaceDescriptorString descriptor(env, name);
+ parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
+ descriptor.size());
}
}
static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- const jchar* str = env->GetStringCritical(name, 0);
- if (str) {
- IPCThreadState* threadState = IPCThreadState::self();
- const int32_t oldPolicy = threadState->getStrictModePolicy();
- const bool isValid = parcel->enforceInterface(
- reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(name),
- threadState);
- env->ReleaseStringCritical(name, str);
- if (isValid) {
- const int32_t newPolicy = threadState->getStrictModePolicy();
- if (oldPolicy != newPolicy) {
- // Need to keep the Java-level thread-local strict
- // mode policy in sync for the libcore
- // enforcements, which involves an upcall back
- // into Java. (We can't modify the
- // Parcel.enforceInterface signature, as it's
- // pseudo-public, and used via AIDL
- // auto-generation...)
- set_dalvik_blockguard_policy(env, newPolicy);
- }
- return; // everything was correct -> return silently
+ if (parcel != nullptr) {
+ InterfaceDescriptorString descriptor(env, name);
+ IPCThreadState* threadState = IPCThreadState::self();
+ const int32_t oldPolicy = threadState->getStrictModePolicy();
+ const bool isValid =
+ parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
+ descriptor.size(), threadState);
+ if (isValid) {
+ const int32_t newPolicy = threadState->getStrictModePolicy();
+ if (oldPolicy != newPolicy) {
+ // Need to keep the Java-level thread-local strict
+ // mode policy in sync for the libcore
+ // enforcements, which involves an upcall back
+ // into Java. (We can't modify the
+ // Parcel.enforceInterface signature, as it's
+ // pseudo-public, and used via AIDL
+ // auto-generation...)
+ set_dalvik_blockguard_policy(env, newPolicy);
}
+ return; // everything was correct -> return silently
}
}