Loading core/jni/android_os_Parcel.cpp +60 −33 Original line number Original line Diff line number Diff line Loading @@ -638,36 +638,64 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr) return ret; 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, static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name) jstring name) { { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { if (parcel != nullptr) { // In the current implementation, the token is just the serialized interface name that InterfaceDescriptorString descriptor(env, name); // the caller expects to be invoking parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()), const jchar* str = env->GetStringCritical(name, 0); descriptor.size()); if (str != NULL) { parcel->writeInterfaceToken(String16( reinterpret_cast<const char16_t*>(str), env->GetStringLength(name))); env->ReleaseStringCritical(name, str); } } } } } static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name) static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name) { { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { if (parcel != nullptr) { const jchar* str = env->GetStringCritical(name, 0); InterfaceDescriptorString descriptor(env, name); if (str) { IPCThreadState* threadState = IPCThreadState::self(); IPCThreadState* threadState = IPCThreadState::self(); const int32_t oldPolicy = threadState->getStrictModePolicy(); const int32_t oldPolicy = threadState->getStrictModePolicy(); const bool isValid = parcel->enforceInterface( const bool isValid = reinterpret_cast<const char16_t*>(str), parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()), env->GetStringLength(name), descriptor.size(), threadState); threadState); env->ReleaseStringCritical(name, str); if (isValid) { if (isValid) { const int32_t newPolicy = threadState->getStrictModePolicy(); const int32_t newPolicy = threadState->getStrictModePolicy(); if (oldPolicy != newPolicy) { 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 return; // everything was correct -> return silently } } } } } // all error conditions wind up here // all error conditions wind up here jniThrowException(env, "java/lang/SecurityException", jniThrowException(env, "java/lang/SecurityException", Loading Loading
core/jni/android_os_Parcel.cpp +60 −33 Original line number Original line Diff line number Diff line Loading @@ -638,36 +638,64 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr) return ret; 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, static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name) jstring name) { { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { if (parcel != nullptr) { // In the current implementation, the token is just the serialized interface name that InterfaceDescriptorString descriptor(env, name); // the caller expects to be invoking parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()), const jchar* str = env->GetStringCritical(name, 0); descriptor.size()); if (str != NULL) { parcel->writeInterfaceToken(String16( reinterpret_cast<const char16_t*>(str), env->GetStringLength(name))); env->ReleaseStringCritical(name, str); } } } } } static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name) static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name) { { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { if (parcel != nullptr) { const jchar* str = env->GetStringCritical(name, 0); InterfaceDescriptorString descriptor(env, name); if (str) { IPCThreadState* threadState = IPCThreadState::self(); IPCThreadState* threadState = IPCThreadState::self(); const int32_t oldPolicy = threadState->getStrictModePolicy(); const int32_t oldPolicy = threadState->getStrictModePolicy(); const bool isValid = parcel->enforceInterface( const bool isValid = reinterpret_cast<const char16_t*>(str), parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()), env->GetStringLength(name), descriptor.size(), threadState); threadState); env->ReleaseStringCritical(name, str); if (isValid) { if (isValid) { const int32_t newPolicy = threadState->getStrictModePolicy(); const int32_t newPolicy = threadState->getStrictModePolicy(); if (oldPolicy != newPolicy) { 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 return; // everything was correct -> return silently } } } } } // all error conditions wind up here // all error conditions wind up here jniThrowException(env, "java/lang/SecurityException", jniThrowException(env, "java/lang/SecurityException", Loading