Loading media/libstagefright/foundation/AMessage.cpp +81 −69 Original line number Diff line number Diff line Loading @@ -54,13 +54,11 @@ status_t AReplyToken::setReply(const sp<AMessage> &reply) { AMessage::AMessage(void) : mWhat(0), mTarget(0), mNumItems(0) { mTarget(0) { } AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler) : mWhat(what), mNumItems(0) { : mWhat(what) { setTarget(handler); } Loading Loading @@ -89,13 +87,13 @@ void AMessage::setTarget(const sp<const AHandler> &handler) { } void AMessage::clear() { for (size_t i = 0; i < mNumItems; ++i) { Item *item = &mItems[i]; delete[] item->mName; item->mName = NULL; freeItemValue(item); // Item needs to be handled delicately for (Item &item : mItems) { delete[] item.mName; item.mName = NULL; freeItemValue(&item); } mNumItems = 0; mItems.clear(); } void AMessage::freeItemValue(Item *item) { Loading Loading @@ -157,7 +155,7 @@ inline size_t AMessage::findItemIndex(const char *name, size_t len) const { size_t memchecks = 0; #endif size_t i = 0; for (; i < mNumItems; i++) { for (; i < mItems.size(); i++) { if (len != mItems[i].mNameLength) { continue; } Loading @@ -172,7 +170,7 @@ inline size_t AMessage::findItemIndex(const char *name, size_t len) const { { Mutex::Autolock _l(gLock); ++gFindItemCalls; gAverageNumItems += mNumItems; gAverageNumItems += mItems.size(); gAverageNumMemChecks += memchecks; gAverageNumChecks += i; reportStats(); Loading @@ -188,20 +186,26 @@ void AMessage::Item::setName(const char *name, size_t len) { memcpy((void*)mName, name, len + 1); } AMessage::Item::Item(const char *name, size_t len) : mType(kTypeInt32) { // mName and mNameLength are initialized by setName setName(name, len); } AMessage::Item *AMessage::allocateItem(const char *name) { size_t len = strlen(name); size_t i = findItemIndex(name, len); Item *item; if (i < mNumItems) { if (i < mItems.size()) { item = &mItems[i]; freeItemValue(item); } else { CHECK(mNumItems < kMaxNumItems); i = mNumItems++; CHECK(mItems.size() < kMaxNumItems); i = mItems.size(); // place a 'blank' item at the end - this is of type kTypeInt32 mItems.emplace_back(name, len); item = &mItems[i]; item->mType = kTypeInt32; item->setName(name, len); } return item; Loading @@ -210,7 +214,7 @@ AMessage::Item *AMessage::allocateItem(const char *name) { const AMessage::Item *AMessage::findItem( const char *name, Type type) const { size_t i = findItemIndex(name, strlen(name)); if (i < mNumItems) { if (i < mItems.size()) { const Item *item = &mItems[i]; return item->mType == type ? item : NULL; Loading @@ -220,7 +224,7 @@ const AMessage::Item *AMessage::findItem( bool AMessage::findAsFloat(const char *name, float *value) const { size_t i = findItemIndex(name, strlen(name)); if (i < mNumItems) { if (i < mItems.size()) { const Item *item = &mItems[i]; switch (item->mType) { case kTypeFloat: Loading @@ -247,7 +251,7 @@ bool AMessage::findAsFloat(const char *name, float *value) const { bool AMessage::findAsInt64(const char *name, int64_t *value) const { size_t i = findItemIndex(name, strlen(name)); if (i < mNumItems) { if (i < mItems.size()) { const Item *item = &mItems[i]; switch (item->mType) { case kTypeInt64: Loading @@ -265,15 +269,16 @@ bool AMessage::findAsInt64(const char *name, int64_t *value) const { bool AMessage::contains(const char *name) const { size_t i = findItemIndex(name, strlen(name)); return i < mNumItems; return i < mItems.size(); } #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ void AMessage::set##NAME(const char *name, TYPENAME value) { \ Item *item = allocateItem(name); \ \ if (item) { \ item->mType = kType##NAME; \ item->u.FIELDNAME = value; \ } \ } \ \ /* NOLINT added to avoid incorrect warning/fix from clang.tidy */ \ Loading @@ -298,9 +303,11 @@ BASIC_TYPE(Pointer,ptrValue,void *) void AMessage::setString( const char *name, const char *s, ssize_t len) { Item *item = allocateItem(name); if (item) { item->mType = kTypeString; item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); } } void AMessage::setString( const char *name, const AString &s) { Loading @@ -310,11 +317,13 @@ void AMessage::setString( void AMessage::setObjectInternal( const char *name, const sp<RefBase> &obj, Type type) { Item *item = allocateItem(name); if (item) { item->mType = type; if (obj != NULL) { obj->incStrong(this); } item->u.refValue = obj.get(); } } void AMessage::setObject(const char *name, const sp<RefBase> &obj) { setObjectInternal(name, obj, kTypeObject); Loading @@ -326,16 +335,19 @@ void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) { void AMessage::setMessage(const char *name, const sp<AMessage> &obj) { Item *item = allocateItem(name); if (item) { item->mType = kTypeMessage; if (obj != NULL) { obj->incStrong(this); } item->u.refValue = obj.get(); } } void AMessage::setRect( const char *name, int32_t left, int32_t top, int32_t right, int32_t bottom) { Item *item = allocateItem(name); if (item) { item->mType = kTypeRect; item->u.rectValue.mLeft = left; Loading @@ -343,6 +355,7 @@ void AMessage::setRect( item->u.rectValue.mRight = right; item->u.rectValue.mBottom = bottom; } } bool AMessage::findString(const char *name, AString *value) const { const Item *item = findItem(name, kTypeString); Loading Loading @@ -466,18 +479,18 @@ bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) { sp<AMessage> AMessage::dup() const { sp<AMessage> msg = new AMessage(mWhat, mHandler.promote()); msg->mNumItems = mNumItems; msg->mItems = mItems; #ifdef DUMP_STATS { Mutex::Autolock _l(gLock); ++gDupCalls; gAverageDupItems += mNumItems; gAverageDupItems += mItems.size(); reportStats(); } #endif for (size_t i = 0; i < mNumItems; ++i) { for (size_t i = 0; i < mItems.size(); ++i) { const Item *from = &mItems[i]; Item *to = &msg->mItems[i]; Loading Loading @@ -560,7 +573,7 @@ AString AMessage::debugString(int32_t indent) const { } s.append(") = {\n"); for (size_t i = 0; i < mNumItems; ++i) { for (size_t i = 0; i < mItems.size(); ++i) { const Item &item = mItems[i]; switch (item.mType) { Loading Loading @@ -653,19 +666,20 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) sp<AMessage> msg = new AMessage(); msg->setWhat(what); msg->mNumItems = static_cast<size_t>(parcel.readInt32()); if (msg->mNumItems > kMaxNumItems) { size_t numItems = static_cast<size_t>(parcel.readInt32()); if (numItems > kMaxNumItems) { ALOGE("Too large number of items clipped."); msg->mNumItems = kMaxNumItems; numItems = kMaxNumItems; } msg->mItems.resize(numItems); for (size_t i = 0; i < msg->mNumItems; ++i) { for (size_t i = 0; i < msg->mItems.size(); ++i) { Item *item = &msg->mItems[i]; const char *name = parcel.readCString(); if (name == NULL) { ALOGE("Failed reading name for an item. Parsing aborted."); msg->mNumItems = i; msg->mItems.resize(i); break; } Loading Loading @@ -709,7 +723,7 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) if (stringValue == NULL) { ALOGE("Failed reading string value from a parcel. " "Parsing aborted."); msg->mNumItems = i; msg->mItems.resize(i); continue; // The loop will terminate subsequently. } else { Loading Loading @@ -754,11 +768,9 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) void AMessage::writeToParcel(Parcel *parcel) const { parcel->writeInt32(static_cast<int32_t>(mWhat)); parcel->writeInt32(static_cast<int32_t>(mNumItems)); for (size_t i = 0; i < mNumItems; ++i) { const Item &item = mItems[i]; parcel->writeInt32(static_cast<int32_t>(mItems.size())); for (const Item &item : mItems) { parcel->writeCString(item.mName); parcel->writeInt32(static_cast<int32_t>(item.mType)); Loading Loading @@ -828,8 +840,7 @@ sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) c diff->setTarget(mHandler.promote()); } for (size_t i = 0; i < mNumItems; ++i) { const Item &item = mItems[i]; for (const Item &item : mItems) { const Item *oitem = other->findItem(item.mName, item.mType); switch (item.mType) { case kTypeInt32: Loading Loading @@ -936,11 +947,11 @@ sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) c } size_t AMessage::countEntries() const { return mNumItems; return mItems.size(); } const char *AMessage::getEntryNameAt(size_t index, Type *type) const { if (index >= mNumItems) { if (index >= mItems.size()) { *type = kTypeInt32; return NULL; Loading @@ -953,7 +964,7 @@ const char *AMessage::getEntryNameAt(size_t index, Type *type) const { AMessage::ItemData AMessage::getEntryAt(size_t index) const { ItemData it; if (index < mNumItems) { if (index < mItems.size()) { switch (mItems[index].mType) { case kTypeInt32: it.set(mItems[index].u.int32Value); break; case kTypeInt64: it.set(mItems[index].u.int64Value); break; Loading Loading @@ -986,7 +997,7 @@ AMessage::ItemData AMessage::getEntryAt(size_t index) const { } status_t AMessage::setEntryNameAt(size_t index, const char *name) { if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } if (name == nullptr) { Loading @@ -996,7 +1007,7 @@ status_t AMessage::setEntryNameAt(size_t index, const char *name) { return OK; // name has not changed } size_t len = strlen(name); if (findItemIndex(name, len) < mNumItems) { if (findItemIndex(name, len) < mItems.size()) { return ALREADY_EXISTS; } delete[] mItems[index].mName; Loading @@ -1011,7 +1022,7 @@ status_t AMessage::setEntryAt(size_t index, const ItemData &item) { sp<AMessage> msgValue; sp<ABuffer> bufValue; if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } if (!item.used()) { Loading Loading @@ -1060,21 +1071,22 @@ status_t AMessage::setEntryAt(size_t index, const ItemData &item) { } status_t AMessage::removeEntryAt(size_t index) { if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } // delete entry data and objects --mNumItems; delete[] mItems[index].mName; mItems[index].mName = nullptr; freeItemValue(&mItems[index]); // swap entry with last entry and clear last entry's data if (index < mNumItems) { mItems[index] = mItems[mNumItems]; mItems[mNumItems].mName = nullptr; mItems[mNumItems].mType = kTypeInt32; size_t lastIndex = mItems.size() - 1; if (index < lastIndex) { mItems[index] = mItems[lastIndex]; mItems[lastIndex].mName = nullptr; mItems[lastIndex].mType = kTypeInt32; } mItems.pop_back(); return OK; } Loading @@ -1083,7 +1095,7 @@ status_t AMessage::removeEntryByName(const char *name) { return BAD_VALUE; } size_t index = findEntryByName(name); if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } return removeEntryAt(index); Loading @@ -1093,7 +1105,7 @@ void AMessage::setItem(const char *name, const ItemData &item) { if (item.used()) { Item *it = allocateItem(name); if (it != nullptr) { setEntryAt(it - mItems, item); setEntryAt(it - &mItems[0], item); } } } Loading @@ -1108,11 +1120,11 @@ void AMessage::extend(const sp<AMessage> &other) { return; } for (size_t ix = 0; ix < other->mNumItems; ++ix) { for (size_t ix = 0; ix < other->mItems.size(); ++ix) { Item *it = allocateItem(other->mItems[ix].mName); if (it != nullptr) { ItemData data = other->getEntryAt(ix); setEntryAt(it - mItems, data); setEntryAt(it - &mItems[0], data); } } } Loading media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h +29 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include <utils/KeyedVector.h> #include <utils/RefBase.h> #include <vector> namespace android { struct ABuffer; Loading Loading @@ -95,6 +97,7 @@ struct AMessage : public RefBase { void setTarget(const sp<const AHandler> &handler); // removes all items void clear(); void setInt32(const char *name, int32_t value); Loading Loading @@ -302,16 +305,39 @@ private: size_t mNameLength; Type mType; void setName(const char *name, size_t len); Item() : mName(nullptr), mNameLength(0), mType(kTypeInt32) { } Item(const char *name, size_t length); }; enum { kMaxNumItems = 64 kMaxNumItems = 256 }; Item mItems[kMaxNumItems]; size_t mNumItems; std::vector<Item> mItems; /** * Allocates an item with the given key |name|. If the key already exists, the corresponding * item value is freed. Otherwise a new item is added. * * This method currently asserts if the number of elements would exceed the max number of * elements allowed (kMaxNumItems). This is a security precaution to avoid arbitrarily large * AMessage structures. * * @todo(b/192153245) Either revisit this security precaution, or change the behavior to * silently ignore keys added after the max number of elements are reached. * * @note All previously returned Item* pointers are deemed invalid after this call. (E.g. from * allocateItem or findItem) * * @param name the key for the requested item. * * @return Item* a pointer to the item. */ Item *allocateItem(const char *name); /** Frees the value for the item. */ void freeItemValue(Item *item); /** Finds an item with given key |name| and |type|. Returns nullptr if item is not found. */ const Item *findItem(const char *name, Type type) const; void setObjectInternal( Loading Loading
media/libstagefright/foundation/AMessage.cpp +81 −69 Original line number Diff line number Diff line Loading @@ -54,13 +54,11 @@ status_t AReplyToken::setReply(const sp<AMessage> &reply) { AMessage::AMessage(void) : mWhat(0), mTarget(0), mNumItems(0) { mTarget(0) { } AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler) : mWhat(what), mNumItems(0) { : mWhat(what) { setTarget(handler); } Loading Loading @@ -89,13 +87,13 @@ void AMessage::setTarget(const sp<const AHandler> &handler) { } void AMessage::clear() { for (size_t i = 0; i < mNumItems; ++i) { Item *item = &mItems[i]; delete[] item->mName; item->mName = NULL; freeItemValue(item); // Item needs to be handled delicately for (Item &item : mItems) { delete[] item.mName; item.mName = NULL; freeItemValue(&item); } mNumItems = 0; mItems.clear(); } void AMessage::freeItemValue(Item *item) { Loading Loading @@ -157,7 +155,7 @@ inline size_t AMessage::findItemIndex(const char *name, size_t len) const { size_t memchecks = 0; #endif size_t i = 0; for (; i < mNumItems; i++) { for (; i < mItems.size(); i++) { if (len != mItems[i].mNameLength) { continue; } Loading @@ -172,7 +170,7 @@ inline size_t AMessage::findItemIndex(const char *name, size_t len) const { { Mutex::Autolock _l(gLock); ++gFindItemCalls; gAverageNumItems += mNumItems; gAverageNumItems += mItems.size(); gAverageNumMemChecks += memchecks; gAverageNumChecks += i; reportStats(); Loading @@ -188,20 +186,26 @@ void AMessage::Item::setName(const char *name, size_t len) { memcpy((void*)mName, name, len + 1); } AMessage::Item::Item(const char *name, size_t len) : mType(kTypeInt32) { // mName and mNameLength are initialized by setName setName(name, len); } AMessage::Item *AMessage::allocateItem(const char *name) { size_t len = strlen(name); size_t i = findItemIndex(name, len); Item *item; if (i < mNumItems) { if (i < mItems.size()) { item = &mItems[i]; freeItemValue(item); } else { CHECK(mNumItems < kMaxNumItems); i = mNumItems++; CHECK(mItems.size() < kMaxNumItems); i = mItems.size(); // place a 'blank' item at the end - this is of type kTypeInt32 mItems.emplace_back(name, len); item = &mItems[i]; item->mType = kTypeInt32; item->setName(name, len); } return item; Loading @@ -210,7 +214,7 @@ AMessage::Item *AMessage::allocateItem(const char *name) { const AMessage::Item *AMessage::findItem( const char *name, Type type) const { size_t i = findItemIndex(name, strlen(name)); if (i < mNumItems) { if (i < mItems.size()) { const Item *item = &mItems[i]; return item->mType == type ? item : NULL; Loading @@ -220,7 +224,7 @@ const AMessage::Item *AMessage::findItem( bool AMessage::findAsFloat(const char *name, float *value) const { size_t i = findItemIndex(name, strlen(name)); if (i < mNumItems) { if (i < mItems.size()) { const Item *item = &mItems[i]; switch (item->mType) { case kTypeFloat: Loading @@ -247,7 +251,7 @@ bool AMessage::findAsFloat(const char *name, float *value) const { bool AMessage::findAsInt64(const char *name, int64_t *value) const { size_t i = findItemIndex(name, strlen(name)); if (i < mNumItems) { if (i < mItems.size()) { const Item *item = &mItems[i]; switch (item->mType) { case kTypeInt64: Loading @@ -265,15 +269,16 @@ bool AMessage::findAsInt64(const char *name, int64_t *value) const { bool AMessage::contains(const char *name) const { size_t i = findItemIndex(name, strlen(name)); return i < mNumItems; return i < mItems.size(); } #define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \ void AMessage::set##NAME(const char *name, TYPENAME value) { \ Item *item = allocateItem(name); \ \ if (item) { \ item->mType = kType##NAME; \ item->u.FIELDNAME = value; \ } \ } \ \ /* NOLINT added to avoid incorrect warning/fix from clang.tidy */ \ Loading @@ -298,9 +303,11 @@ BASIC_TYPE(Pointer,ptrValue,void *) void AMessage::setString( const char *name, const char *s, ssize_t len) { Item *item = allocateItem(name); if (item) { item->mType = kTypeString; item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len); } } void AMessage::setString( const char *name, const AString &s) { Loading @@ -310,11 +317,13 @@ void AMessage::setString( void AMessage::setObjectInternal( const char *name, const sp<RefBase> &obj, Type type) { Item *item = allocateItem(name); if (item) { item->mType = type; if (obj != NULL) { obj->incStrong(this); } item->u.refValue = obj.get(); } } void AMessage::setObject(const char *name, const sp<RefBase> &obj) { setObjectInternal(name, obj, kTypeObject); Loading @@ -326,16 +335,19 @@ void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) { void AMessage::setMessage(const char *name, const sp<AMessage> &obj) { Item *item = allocateItem(name); if (item) { item->mType = kTypeMessage; if (obj != NULL) { obj->incStrong(this); } item->u.refValue = obj.get(); } } void AMessage::setRect( const char *name, int32_t left, int32_t top, int32_t right, int32_t bottom) { Item *item = allocateItem(name); if (item) { item->mType = kTypeRect; item->u.rectValue.mLeft = left; Loading @@ -343,6 +355,7 @@ void AMessage::setRect( item->u.rectValue.mRight = right; item->u.rectValue.mBottom = bottom; } } bool AMessage::findString(const char *name, AString *value) const { const Item *item = findItem(name, kTypeString); Loading Loading @@ -466,18 +479,18 @@ bool AMessage::senderAwaitsResponse(sp<AReplyToken> *replyToken) { sp<AMessage> AMessage::dup() const { sp<AMessage> msg = new AMessage(mWhat, mHandler.promote()); msg->mNumItems = mNumItems; msg->mItems = mItems; #ifdef DUMP_STATS { Mutex::Autolock _l(gLock); ++gDupCalls; gAverageDupItems += mNumItems; gAverageDupItems += mItems.size(); reportStats(); } #endif for (size_t i = 0; i < mNumItems; ++i) { for (size_t i = 0; i < mItems.size(); ++i) { const Item *from = &mItems[i]; Item *to = &msg->mItems[i]; Loading Loading @@ -560,7 +573,7 @@ AString AMessage::debugString(int32_t indent) const { } s.append(") = {\n"); for (size_t i = 0; i < mNumItems; ++i) { for (size_t i = 0; i < mItems.size(); ++i) { const Item &item = mItems[i]; switch (item.mType) { Loading Loading @@ -653,19 +666,20 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) sp<AMessage> msg = new AMessage(); msg->setWhat(what); msg->mNumItems = static_cast<size_t>(parcel.readInt32()); if (msg->mNumItems > kMaxNumItems) { size_t numItems = static_cast<size_t>(parcel.readInt32()); if (numItems > kMaxNumItems) { ALOGE("Too large number of items clipped."); msg->mNumItems = kMaxNumItems; numItems = kMaxNumItems; } msg->mItems.resize(numItems); for (size_t i = 0; i < msg->mNumItems; ++i) { for (size_t i = 0; i < msg->mItems.size(); ++i) { Item *item = &msg->mItems[i]; const char *name = parcel.readCString(); if (name == NULL) { ALOGE("Failed reading name for an item. Parsing aborted."); msg->mNumItems = i; msg->mItems.resize(i); break; } Loading Loading @@ -709,7 +723,7 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) if (stringValue == NULL) { ALOGE("Failed reading string value from a parcel. " "Parsing aborted."); msg->mNumItems = i; msg->mItems.resize(i); continue; // The loop will terminate subsequently. } else { Loading Loading @@ -754,11 +768,9 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel, size_t maxNestingLevel) void AMessage::writeToParcel(Parcel *parcel) const { parcel->writeInt32(static_cast<int32_t>(mWhat)); parcel->writeInt32(static_cast<int32_t>(mNumItems)); for (size_t i = 0; i < mNumItems; ++i) { const Item &item = mItems[i]; parcel->writeInt32(static_cast<int32_t>(mItems.size())); for (const Item &item : mItems) { parcel->writeCString(item.mName); parcel->writeInt32(static_cast<int32_t>(item.mType)); Loading Loading @@ -828,8 +840,7 @@ sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) c diff->setTarget(mHandler.promote()); } for (size_t i = 0; i < mNumItems; ++i) { const Item &item = mItems[i]; for (const Item &item : mItems) { const Item *oitem = other->findItem(item.mName, item.mType); switch (item.mType) { case kTypeInt32: Loading Loading @@ -936,11 +947,11 @@ sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) c } size_t AMessage::countEntries() const { return mNumItems; return mItems.size(); } const char *AMessage::getEntryNameAt(size_t index, Type *type) const { if (index >= mNumItems) { if (index >= mItems.size()) { *type = kTypeInt32; return NULL; Loading @@ -953,7 +964,7 @@ const char *AMessage::getEntryNameAt(size_t index, Type *type) const { AMessage::ItemData AMessage::getEntryAt(size_t index) const { ItemData it; if (index < mNumItems) { if (index < mItems.size()) { switch (mItems[index].mType) { case kTypeInt32: it.set(mItems[index].u.int32Value); break; case kTypeInt64: it.set(mItems[index].u.int64Value); break; Loading Loading @@ -986,7 +997,7 @@ AMessage::ItemData AMessage::getEntryAt(size_t index) const { } status_t AMessage::setEntryNameAt(size_t index, const char *name) { if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } if (name == nullptr) { Loading @@ -996,7 +1007,7 @@ status_t AMessage::setEntryNameAt(size_t index, const char *name) { return OK; // name has not changed } size_t len = strlen(name); if (findItemIndex(name, len) < mNumItems) { if (findItemIndex(name, len) < mItems.size()) { return ALREADY_EXISTS; } delete[] mItems[index].mName; Loading @@ -1011,7 +1022,7 @@ status_t AMessage::setEntryAt(size_t index, const ItemData &item) { sp<AMessage> msgValue; sp<ABuffer> bufValue; if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } if (!item.used()) { Loading Loading @@ -1060,21 +1071,22 @@ status_t AMessage::setEntryAt(size_t index, const ItemData &item) { } status_t AMessage::removeEntryAt(size_t index) { if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } // delete entry data and objects --mNumItems; delete[] mItems[index].mName; mItems[index].mName = nullptr; freeItemValue(&mItems[index]); // swap entry with last entry and clear last entry's data if (index < mNumItems) { mItems[index] = mItems[mNumItems]; mItems[mNumItems].mName = nullptr; mItems[mNumItems].mType = kTypeInt32; size_t lastIndex = mItems.size() - 1; if (index < lastIndex) { mItems[index] = mItems[lastIndex]; mItems[lastIndex].mName = nullptr; mItems[lastIndex].mType = kTypeInt32; } mItems.pop_back(); return OK; } Loading @@ -1083,7 +1095,7 @@ status_t AMessage::removeEntryByName(const char *name) { return BAD_VALUE; } size_t index = findEntryByName(name); if (index >= mNumItems) { if (index >= mItems.size()) { return BAD_INDEX; } return removeEntryAt(index); Loading @@ -1093,7 +1105,7 @@ void AMessage::setItem(const char *name, const ItemData &item) { if (item.used()) { Item *it = allocateItem(name); if (it != nullptr) { setEntryAt(it - mItems, item); setEntryAt(it - &mItems[0], item); } } } Loading @@ -1108,11 +1120,11 @@ void AMessage::extend(const sp<AMessage> &other) { return; } for (size_t ix = 0; ix < other->mNumItems; ++ix) { for (size_t ix = 0; ix < other->mItems.size(); ++ix) { Item *it = allocateItem(other->mItems[ix].mName); if (it != nullptr) { ItemData data = other->getEntryAt(ix); setEntryAt(it - mItems, data); setEntryAt(it - &mItems[0], data); } } } Loading
media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h +29 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include <utils/KeyedVector.h> #include <utils/RefBase.h> #include <vector> namespace android { struct ABuffer; Loading Loading @@ -95,6 +97,7 @@ struct AMessage : public RefBase { void setTarget(const sp<const AHandler> &handler); // removes all items void clear(); void setInt32(const char *name, int32_t value); Loading Loading @@ -302,16 +305,39 @@ private: size_t mNameLength; Type mType; void setName(const char *name, size_t len); Item() : mName(nullptr), mNameLength(0), mType(kTypeInt32) { } Item(const char *name, size_t length); }; enum { kMaxNumItems = 64 kMaxNumItems = 256 }; Item mItems[kMaxNumItems]; size_t mNumItems; std::vector<Item> mItems; /** * Allocates an item with the given key |name|. If the key already exists, the corresponding * item value is freed. Otherwise a new item is added. * * This method currently asserts if the number of elements would exceed the max number of * elements allowed (kMaxNumItems). This is a security precaution to avoid arbitrarily large * AMessage structures. * * @todo(b/192153245) Either revisit this security precaution, or change the behavior to * silently ignore keys added after the max number of elements are reached. * * @note All previously returned Item* pointers are deemed invalid after this call. (E.g. from * allocateItem or findItem) * * @param name the key for the requested item. * * @return Item* a pointer to the item. */ Item *allocateItem(const char *name); /** Frees the value for the item. */ void freeItemValue(Item *item); /** Finds an item with given key |name| and |type|. Returns nullptr if item is not found. */ const Item *findItem(const char *name, Type type) const; void setObjectInternal( Loading