Merge "Binder interface tokens: remove extra mallocs"

This commit is contained in:
Steven Moreland
2020-10-05 18:55:58 +00:00
committed by Gerrit Code Review

View File

@@ -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) {
@@ -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",