@@ -638,50 +638,77 @@ static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
638638 return ret;
639639}
640640
641+ // String tries to allocate itself on the stack, within a known size, but will
642+ // make a heap allocation if not.
643+ template <size_t StackReserve>
644+ class StackString {
645+ public:
646+ StackString (JNIEnv* env, jstring str) : mEnv (env), mJStr (str) {
647+ LOG_ALWAYS_FATAL_IF (str == nullptr );
648+ mSize = env->GetStringLength (str);
649+ if (mSize > StackReserve) {
650+ mStr = new jchar[mSize ];
651+ } else {
652+ mStr = &mBuffer [0 ];
653+ }
654+ mEnv ->GetStringRegion (str, 0 , mSize , mStr );
655+ }
656+ ~StackString () {
657+ if (mStr != &mBuffer [0 ]) {
658+ delete[] mStr ;
659+ }
660+ }
661+ const jchar* str () { return mStr ; }
662+ jsize size () { return mSize ; }
663+
664+ private:
665+ JNIEnv* mEnv ;
666+ jstring mJStr ;
667+
668+ jchar mBuffer [StackReserve];
669+ // pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
670+ jchar* mStr ;
671+ jsize mSize ;
672+ };
673+
674+ // This size is chosen to be longer than most interface descriptors.
675+ // Ones longer than this will be allocated on the heap.
676+ typedef StackString<64 > InterfaceDescriptorString;
677+
641678static void android_os_Parcel_writeInterfaceToken (JNIEnv* env, jclass clazz, jlong nativePtr,
642679 jstring name)
643680{
644681 Parcel* parcel = reinterpret_cast <Parcel*>(nativePtr);
645- if (parcel != NULL ) {
646- // In the current implementation, the token is just the serialized interface name that
647- // the caller expects to be invoking
648- const jchar* str = env->GetStringCritical (name, 0 );
649- if (str != NULL ) {
650- parcel->writeInterfaceToken (String16 (
651- reinterpret_cast <const char16_t *>(str),
652- env->GetStringLength (name)));
653- env->ReleaseStringCritical (name, str);
654- }
682+ if (parcel != nullptr ) {
683+ InterfaceDescriptorString descriptor (env, name);
684+ parcel->writeInterfaceToken (reinterpret_cast <const char16_t *>(descriptor.str ()),
685+ descriptor.size ());
655686 }
656687}
657688
658689static void android_os_Parcel_enforceInterface (JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
659690{
660691 Parcel* parcel = reinterpret_cast <Parcel*>(nativePtr);
661- if (parcel != NULL ) {
662- const jchar* str = env->GetStringCritical (name, 0 );
663- if (str) {
664- IPCThreadState* threadState = IPCThreadState::self ();
665- const int32_t oldPolicy = threadState->getStrictModePolicy ();
666- const bool isValid = parcel->enforceInterface (
667- reinterpret_cast <const char16_t *>(str),
668- env->GetStringLength (name),
669- threadState);
670- env->ReleaseStringCritical (name, str);
671- if (isValid) {
672- const int32_t newPolicy = threadState->getStrictModePolicy ();
673- if (oldPolicy != newPolicy) {
674- // Need to keep the Java-level thread-local strict
675- // mode policy in sync for the libcore
676- // enforcements, which involves an upcall back
677- // into Java. (We can't modify the
678- // Parcel.enforceInterface signature, as it's
679- // pseudo-public, and used via AIDL
680- // auto-generation...)
681- set_dalvik_blockguard_policy (env, newPolicy);
682- }
683- return ; // everything was correct -> return silently
692+ if (parcel != nullptr ) {
693+ InterfaceDescriptorString descriptor (env, name);
694+ IPCThreadState* threadState = IPCThreadState::self ();
695+ const int32_t oldPolicy = threadState->getStrictModePolicy ();
696+ const bool isValid =
697+ parcel->enforceInterface (reinterpret_cast <const char16_t *>(descriptor.str ()),
698+ descriptor.size (), threadState);
699+ if (isValid) {
700+ const int32_t newPolicy = threadState->getStrictModePolicy ();
701+ if (oldPolicy != newPolicy) {
702+ // Need to keep the Java-level thread-local strict
703+ // mode policy in sync for the libcore
704+ // enforcements, which involves an upcall back
705+ // into Java. (We can't modify the
706+ // Parcel.enforceInterface signature, as it's
707+ // pseudo-public, and used via AIDL
708+ // auto-generation...)
709+ set_dalvik_blockguard_policy (env, newPolicy);
684710 }
711+ return ; // everything was correct -> return silently
685712 }
686713 }
687714
0 commit comments