Merge "Binder interface tokens: remove extra mallocs"
This commit is contained in:
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user