@ -464,6 +464,7 @@ void Parcel::setDataPosition(size_t pos) const
mDataPos = pos ;
mNextObjectHint = 0 ;
mObjectsSorted = false ;
}
status_t Parcel : : setDataCapacity ( size_t size )
@ -1133,6 +1134,59 @@ void Parcel::remove(size_t /*start*/, size_t /*amt*/)
LOG_ALWAYS_FATAL ( " Parcel::remove() not yet implemented! " ) ;
}
status_t Parcel : : validateReadData ( size_t upperBound ) const
{
// Don't allow non-object reads on object data
if ( mObjectsSorted | | mObjectsSize < = 1 ) {
data_sorted :
// Expect to check only against the next object
if ( mNextObjectHint < mObjectsSize & & upperBound > mObjects [ mNextObjectHint ] ) {
// For some reason the current read position is greater than the next object
// hint. Iterate until we find the right object
size_t nextObject = mNextObjectHint ;
do {
if ( mDataPos < mObjects [ nextObject ] + sizeof ( flat_binder_object ) ) {
// Requested info overlaps with an object
ALOGE ( " Attempt to read from protected data in Parcel %p " , this ) ;
return PERMISSION_DENIED ;
}
nextObject + + ;
} while ( nextObject < mObjectsSize & & upperBound > mObjects [ nextObject ] ) ;
mNextObjectHint = nextObject ;
}
return NO_ERROR ;
}
// Quickly determine if mObjects is sorted.
binder_size_t * currObj = mObjects + mObjectsSize - 1 ;
binder_size_t * prevObj = currObj ;
while ( currObj > mObjects ) {
prevObj - - ;
if ( * prevObj > * currObj ) {
goto data_unsorted ;
}
currObj - - ;
}
mObjectsSorted = true ;
goto data_sorted ;
data_unsorted :
// Insertion Sort mObjects
// Great for mostly sorted lists. If randomly sorted or reverse ordered mObjects become common,
// switch to std::sort(mObjects, mObjects + mObjectsSize);
for ( binder_size_t * iter0 = mObjects + 1 ; iter0 < mObjects + mObjectsSize ; iter0 + + ) {
binder_size_t temp = * iter0 ;
binder_size_t * iter1 = iter0 - 1 ;
while ( iter1 > = mObjects & & * iter1 > temp ) {
* ( iter1 + 1 ) = * iter1 ;
iter1 - - ;
}
* ( iter1 + 1 ) = temp ;
}
mNextObjectHint = 0 ;
mObjectsSorted = true ;
goto data_sorted ;
}
status_t Parcel : : read ( void * outData , size_t len ) const
{
if ( len > INT32_MAX ) {
@ -1143,6 +1197,10 @@ status_t Parcel::read(void* outData, size_t len) const
if ( ( mDataPos + pad_size ( len ) ) > = mDataPos & & ( mDataPos + pad_size ( len ) ) < = mDataSize
& & len < = pad_size ( len ) ) {
if ( mObjectsSize > 0 ) {
status_t err = validateReadData ( mDataPos + pad_size ( len ) ) ;
if ( err ! = NO_ERROR ) return err ;
}
memcpy ( outData , mData + mDataPos , len ) ;
mDataPos + = pad_size ( len ) ;
ALOGV ( " read Setting data pos of %p to %zu " , this , mDataPos ) ;
@ -1161,6 +1219,11 @@ const void* Parcel::readInplace(size_t len) const
if ( ( mDataPos + pad_size ( len ) ) > = mDataPos & & ( mDataPos + pad_size ( len ) ) < = mDataSize
& & len < = pad_size ( len ) ) {
if ( mObjectsSize > 0 ) {
status_t err = validateReadData ( mDataPos + pad_size ( len ) ) ;
if ( err ! = NO_ERROR ) return NULL ;
}
const void * data = mData + mDataPos ;
mDataPos + = pad_size ( len ) ;
ALOGV ( " readInplace Setting data pos of %p to %zu " , this , mDataPos ) ;
@ -1174,6 +1237,11 @@ status_t Parcel::readAligned(T *pArg) const {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE ( PAD_SIZE_UNSAFE ( sizeof ( T ) ) = = sizeof ( T ) ) ;
if ( ( mDataPos + sizeof ( T ) ) < = mDataSize ) {
if ( mObjectsSize > 0 ) {
status_t err = validateReadData ( mDataPos + sizeof ( T ) ) ;
if ( err ! = NO_ERROR ) return err ;
}
const void * data = mData + mDataPos ;
mDataPos + = sizeof ( T ) ;
* pArg = * reinterpret_cast < const T * > ( data ) ;
@ -1638,6 +1706,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,
mObjects = const_cast < binder_size_t * > ( objects ) ;
mObjectsSize = mObjectsCapacity = objectsCount ;
mNextObjectHint = 0 ;
mObjectsSorted = false ;
mOwner = relFunc ;
mOwnerCookie = relCookie ;
for ( size_t i = 0 ; i < mObjectsSize ; i + + ) {
@ -1795,6 +1864,7 @@ status_t Parcel::restartWrite(size_t desired)
mObjects = NULL ;
mObjectsSize = mObjectsCapacity = 0 ;
mNextObjectHint = 0 ;
mObjectsSorted = false ;
mHasFds = false ;
mFdsKnown = true ;
mAllowFds = true ;
@ -1881,6 +1951,7 @@ status_t Parcel::continueWrite(size_t desired)
mDataCapacity = desired ;
mObjectsSize = mObjectsCapacity = objectsSize ;
mNextObjectHint = 0 ;
mObjectsSorted = false ;
} else if ( mData ) {
if ( objectsSize < mObjectsSize ) {
@ -1906,6 +1977,7 @@ status_t Parcel::continueWrite(size_t desired)
}
mObjectsSize = objectsSize ;
mNextObjectHint = 0 ;
mObjectsSorted = false ;
}
// We own the data, so we can just do a realloc().
@ -1978,6 +2050,7 @@ void Parcel::initState()
mObjectsSize = 0 ;
mObjectsCapacity = 0 ;
mNextObjectHint = 0 ;
mObjectsSorted = false ;
mHasFds = false ;
mFdsKnown = true ;
mAllowFds = true ;