Loading core/jni/android_os_Parcel.cpp +60 −33 Original line number Diff line number Diff line Loading @@ -638,36 +638,64 @@ 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) { 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*>(str), env->GetStringLength(name), threadState); env->ReleaseStringCritical(name, str); 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) { Loading @@ -683,7 +711,6 @@ static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong return; // everything was correct -> return silently } } } // all error conditions wind up here jniThrowException(env, "java/lang/SecurityException", Loading Loading
core/jni/android_os_Parcel.cpp +60 −33 Original line number Diff line number Diff line Loading @@ -638,36 +638,64 @@ 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) { 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*>(str), env->GetStringLength(name), threadState); env->ReleaseStringCritical(name, str); 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) { Loading @@ -683,7 +711,6 @@ static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong return; // everything was correct -> return silently } } } // all error conditions wind up here jniThrowException(env, "java/lang/SecurityException", Loading