commit 973529d127fbfbb49fc7fdb2895feaaa758a698f
parent 32d5e28eaadb7959e00008ef31e35ba35330033f
Author: Lee Salzman <lsalzman@mozilla.com>
Date: Thu, 2 Oct 2025 14:01:56 +0000
Bug 1991899 - Use RecordedEventArray for variable-sized recording data. r=aosmond
Differential Revision: https://phabricator.services.mozilla.com/D267087
Diffstat:
2 files changed, 160 insertions(+), 93 deletions(-)
diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h
@@ -541,6 +541,85 @@ class RecordedStrokeOptionsMixin {
UniquePtr<Float[]> mDashPatternStorage;
};
+template <typename T>
+class RecordedEventArray {
+ public:
+ T* data() { return mData.get(); }
+ const T* data() const { return mData.get(); }
+ size_t size() const { return mSize; }
+ bool empty() const { return !mSize; }
+
+ void Assign(const T* aData, size_t aSize) {
+ mSize = aSize;
+ mData = MakeUnique<T[]>(aSize);
+ PodCopy(mData.get(), aData, aSize);
+ }
+
+ bool TryAlloc(size_t aSize) {
+ if (mSize > 0) {
+ MOZ_ASSERT_UNREACHABLE();
+ return false;
+ }
+ mData = MakeUniqueFallible<T[]>(aSize);
+ if (!mData) {
+ return false;
+ }
+ mSize = aSize;
+ return true;
+ }
+
+ template <typename S>
+ void Write(S& aStream) const {
+ if (mSize) {
+ aStream.write(reinterpret_cast<const char*>(mData.get()),
+ sizeof(T) * mSize);
+ }
+ }
+
+ template <typename S>
+ bool Read(S& aStream, size_t aSize) {
+ if (!aStream.good() || !TryAlloc(aSize)) {
+ return false;
+ }
+ aStream.read(reinterpret_cast<char*>(mData.get()), sizeof(T) * mSize);
+ if (!aStream.good()) {
+ Clear();
+ return false;
+ }
+ return true;
+ }
+
+ void Clear() {
+ mSize = 0;
+ mData.reset();
+ }
+
+ protected:
+ size_t mSize = 0;
+ UniquePtr<T[]> mData;
+};
+
+class RecordedEventCString : public RecordedEventArray<char> {
+ public:
+ explicit RecordedEventCString(const char* aStr = nullptr) {
+ if (aStr) {
+ if (size_t len = strlen(aStr)) {
+ Assign(aStr, len + 1);
+ }
+ }
+ }
+
+ template <typename S>
+ bool Read(S& aStream, size_t aSize) {
+ if (!RecordedEventArray<char>::Read(aStream, aSize) ||
+ (size() > 0 && !memchr(data(), '\0', size()))) {
+ Clear();
+ return false;
+ }
+ return true;
+ }
+};
+
template <class Derived>
class RecordedEventDerived : public RecordedEvent {
using RecordedEvent::RecordedEvent;
diff --git a/gfx/2d/RecordedEventImpl.h b/gfx/2d/RecordedEventImpl.h
@@ -1566,7 +1566,7 @@ class RecordedFontDescriptor
bool mHasDesc;
FontType mType;
- std::vector<uint8_t> mData;
+ RecordedEventArray<uint8_t> mData;
uint32_t mIndex;
ReferencePtr mRefPtr;
@@ -1609,7 +1609,7 @@ class RecordedUnscaledFontCreation
ReferencePtr mRefPtr;
uint64_t mFontDataKey;
uint32_t mIndex;
- std::vector<uint8_t> mInstanceData;
+ RecordedEventArray<uint8_t> mInstanceData;
template <class S>
MOZ_IMPLICIT RecordedUnscaledFontCreation(S& aStream);
@@ -1676,8 +1676,8 @@ class RecordedScaledFontCreation
ReferencePtr mRefPtr;
ReferencePtr mUnscaledFont;
Float mGlyphSize;
- std::vector<uint8_t> mInstanceData;
- std::vector<FontVariation> mVariations;
+ RecordedEventArray<uint8_t> mInstanceData;
+ RecordedEventArray<FontVariation> mVariations;
template <class S>
MOZ_IMPLICIT RecordedScaledFontCreation(S& aStream);
@@ -1765,8 +1765,7 @@ class RecordedFilterNodeSetAttribute
mNode(aNode),
mIndex(aIndex),
mArgType(aArgType) {
- mPayload.resize(sizeof(T));
- memcpy(&mPayload.front(), &aArgument, sizeof(T));
+ mPayload.Assign(reinterpret_cast<const uint8_t*>(&aArgument), sizeof(T));
}
RecordedFilterNodeSetAttribute(FilterNode* aNode, uint32_t aIndex,
@@ -1775,8 +1774,8 @@ class RecordedFilterNodeSetAttribute
mNode(aNode),
mIndex(aIndex),
mArgType(ARGTYPE_FLOAT_ARRAY) {
- mPayload.resize(sizeof(Float) * aSize);
- memcpy(&mPayload.front(), aFloat, sizeof(Float) * aSize);
+ mPayload.Assign(reinterpret_cast<const uint8_t*>(aFloat),
+ sizeof(Float) * aSize);
}
bool PlayEvent(Translator* aTranslator) const override;
@@ -1793,7 +1792,7 @@ class RecordedFilterNodeSetAttribute
uint32_t mIndex;
ArgType mArgType;
- std::vector<uint8_t> mPayload;
+ RecordedEventArray<uint8_t> mPayload;
template <class S>
MOZ_IMPLICIT RecordedFilterNodeSetAttribute(S& aStream);
@@ -1855,8 +1854,8 @@ class RecordedLink : public RecordedEventDerived<RecordedLink> {
private:
friend class RecordedEvent;
- std::string mLocalDest;
- std::string mURI;
+ RecordedEventCString mLocalDest;
+ RecordedEventCString mURI;
Rect mRect;
template <class S>
@@ -1880,7 +1879,7 @@ class RecordedDestination : public RecordedEventDerived<RecordedDestination> {
private:
friend class RecordedEvent;
- std::string mDestination;
+ RecordedEventCString mDestination;
Point mPoint;
template <class S>
@@ -4221,10 +4220,8 @@ void RecordedFontDescriptor::Record(S& aStream) const {
WriteElement(aStream, mType);
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mIndex);
- WriteElement(aStream, (size_t)mData.size());
- if (mData.size()) {
- aStream.write((char*)mData.data(), mData.size());
- }
+ WriteElement(aStream, mData.size());
+ mData.Write(aStream);
}
inline void RecordedFontDescriptor::OutputSimpleEventInfo(
@@ -4235,7 +4232,7 @@ inline void RecordedFontDescriptor::OutputSimpleEventInfo(
inline void RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData,
uint32_t aSize,
uint32_t aIndex) {
- mData.assign(aData, aData + aSize);
+ mData.Assign(aData, aSize);
mIndex = aIndex;
}
@@ -4246,14 +4243,14 @@ RecordedFontDescriptor::RecordedFontDescriptor(S& aStream)
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mIndex);
- size_t size;
+ size_t size = 0;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
- if (size) {
- mData.resize(size);
- aStream.read((char*)mData.data(), size);
+ if (size && !mData.Read(aStream, size)) {
+ aStream.SetIsBad();
+ return;
}
}
@@ -4279,10 +4276,8 @@ void RecordedUnscaledFontCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mFontDataKey);
WriteElement(aStream, mIndex);
- WriteElement(aStream, (size_t)mInstanceData.size());
- if (mInstanceData.size()) {
- aStream.write((char*)mInstanceData.data(), mInstanceData.size());
- }
+ WriteElement(aStream, mInstanceData.size());
+ mInstanceData.Write(aStream);
}
inline void RecordedUnscaledFontCreation::OutputSimpleEventInfo(
@@ -4293,7 +4288,7 @@ inline void RecordedUnscaledFontCreation::OutputSimpleEventInfo(
inline void RecordedUnscaledFontCreation::SetFontInstanceData(
const uint8_t* aData, uint32_t aSize) {
if (aSize) {
- mInstanceData.assign(aData, aData + aSize);
+ mInstanceData.Assign(aData, aSize);
}
}
@@ -4304,14 +4299,14 @@ RecordedUnscaledFontCreation::RecordedUnscaledFontCreation(S& aStream)
ReadElement(aStream, mFontDataKey);
ReadElement(aStream, mIndex);
- size_t size;
+ size_t size = 0;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
- if (size) {
- mInstanceData.resize(size);
- aStream.read((char*)mInstanceData.data(), size);
+ if (size && !mInstanceData.Read(aStream, size)) {
+ aStream.SetIsBad();
+ return;
}
}
@@ -4360,15 +4355,10 @@ void RecordedScaledFontCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mUnscaledFont);
WriteElement(aStream, mGlyphSize);
- WriteElement(aStream, (size_t)mInstanceData.size());
- if (mInstanceData.size()) {
- aStream.write((char*)mInstanceData.data(), mInstanceData.size());
- }
- WriteElement(aStream, (size_t)mVariations.size());
- if (mVariations.size()) {
- aStream.write((char*)mVariations.data(),
- sizeof(FontVariation) * mVariations.size());
- }
+ WriteElement(aStream, mInstanceData.size());
+ mInstanceData.Write(aStream);
+ WriteElement(aStream, mVariations.size());
+ mVariations.Write(aStream);
}
inline void RecordedScaledFontCreation::OutputSimpleEventInfo(
@@ -4380,10 +4370,10 @@ inline void RecordedScaledFontCreation::SetFontInstanceData(
const uint8_t* aData, uint32_t aSize, const FontVariation* aVariations,
uint32_t aNumVariations) {
if (aSize) {
- mInstanceData.assign(aData, aData + aSize);
+ mInstanceData.Assign(aData, aSize);
}
if (aNumVariations) {
- mVariations.assign(aVariations, aVariations + aNumVariations);
+ mVariations.Assign(aVariations, aNumVariations);
}
}
@@ -4394,25 +4384,24 @@ RecordedScaledFontCreation::RecordedScaledFontCreation(S& aStream)
ReadElement(aStream, mUnscaledFont);
ReadElement(aStream, mGlyphSize);
- size_t size;
+ size_t size = 0;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
- if (size) {
- mInstanceData.resize(size);
- aStream.read((char*)mInstanceData.data(), size);
+ if (size && !mInstanceData.Read(aStream, size)) {
+ aStream.SetIsBad();
+ return;
}
- size_t numVariations;
+ size_t numVariations = 0;
ReadElement(aStream, numVariations);
if (!aStream.good()) {
return;
}
- if (numVariations) {
- mVariations.resize(numVariations);
- aStream.read((char*)mVariations.data(),
- sizeof(FontVariation) * numVariations);
+ if (numVariations && !mVariations.Read(aStream, numVariations)) {
+ aStream.SetIsBad();
+ return;
}
}
@@ -4490,9 +4479,12 @@ inline bool RecordedFilterNodeSetAttribute::PlayEvent(
return false;
}
-#define REPLAY_SET_ATTRIBUTE(type, argtype) \
- case ARGTYPE_##argtype: \
- ReplaySetAttribute(node, mIndex, *(type*)&mPayload.front()); \
+#define REPLAY_SET_ATTRIBUTE(type, argtype) \
+ case ARGTYPE_##argtype: \
+ if (mPayload.size() < sizeof(type)) { \
+ return false; \
+ } \
+ ReplaySetAttribute(node, mIndex, *(type*)mPayload.data()); \
break
switch (mArgType) {
@@ -4511,7 +4503,7 @@ inline bool RecordedFilterNodeSetAttribute::PlayEvent(
REPLAY_SET_ATTRIBUTE(DeviceColor, COLOR);
case ARGTYPE_FLOAT_ARRAY:
node->SetAttribute(mIndex,
- reinterpret_cast<const Float*>(&mPayload.front()),
+ reinterpret_cast<const Float*>(mPayload.data()),
mPayload.size() / sizeof(Float));
break;
}
@@ -4524,8 +4516,8 @@ void RecordedFilterNodeSetAttribute::Record(S& aStream) const {
WriteElement(aStream, mNode);
WriteElement(aStream, mIndex);
WriteElement(aStream, mArgType);
- WriteElement(aStream, uint64_t(mPayload.size()));
- aStream.write((const char*)&mPayload.front(), mPayload.size());
+ WriteElement(aStream, mPayload.size());
+ mPayload.Write(aStream);
}
template <class S>
@@ -4535,14 +4527,16 @@ RecordedFilterNodeSetAttribute::RecordedFilterNodeSetAttribute(S& aStream)
ReadElement(aStream, mIndex);
ReadElementConstrained(aStream, mArgType, ArgType::ARGTYPE_UINT32,
ArgType::ARGTYPE_FLOAT_ARRAY);
- uint64_t size;
+ size_t size = 0;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
- mPayload.resize(size_t(size));
- aStream.read((char*)&mPayload.front(), size);
+ if (size && !mPayload.Read(aStream, size)) {
+ aStream.SetIsBad();
+ return;
+ }
}
inline void RecordedFilterNodeSetAttribute::OutputSimpleEventInfo(
@@ -4601,48 +4595,44 @@ inline bool RecordedLink::PlayEvent(Translator* aTranslator) const {
if (!dt) {
return false;
}
- dt->Link(mLocalDest.c_str(), mURI.c_str(), mRect);
+ dt->Link(mLocalDest.data(), mURI.data(), mRect);
return true;
}
template <class S>
void RecordedLink::Record(S& aStream) const {
WriteElement(aStream, mRect);
- uint32_t len = mLocalDest.length();
- WriteElement(aStream, len);
- if (len) {
- aStream.write(mLocalDest.data(), len);
- }
- len = mURI.length();
- WriteElement(aStream, len);
- if (len) {
- aStream.write(mURI.data(), len);
- }
+ WriteElement(aStream, mLocalDest.size());
+ mLocalDest.Write(aStream);
+ WriteElement(aStream, mURI.size());
+ mURI.Write(aStream);
}
template <class S>
RecordedLink::RecordedLink(S& aStream) : RecordedEventDerived(LINK) {
ReadElement(aStream, mRect);
- uint32_t len;
- ReadElement(aStream, len);
- mLocalDest.resize(size_t(len));
- if (len && aStream.good()) {
- aStream.read(&mLocalDest.front(), len);
+ size_t localDestLen = 0;
+ ReadElement(aStream, localDestLen);
+ if (!aStream.good() ||
+ (localDestLen && !mLocalDest.Read(aStream, localDestLen))) {
+ aStream.SetIsBad();
+ return;
}
- ReadElement(aStream, len);
- mURI.resize(size_t(len));
- if (len && aStream.good()) {
- aStream.read(&mURI.front(), len);
+ size_t uriLen = 0;
+ ReadElement(aStream, uriLen);
+ if (!aStream.good() || (uriLen && !mURI.Read(aStream, uriLen))) {
+ aStream.SetIsBad();
+ return;
}
}
inline void RecordedLink::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
if (mLocalDest.empty()) {
- aStringStream << "Link [" << mURI << " @ " << mRect << "]";
+ aStringStream << "Link [" << mURI.data() << " @ " << mRect << "]";
} else {
- aStringStream << "Link [" << mLocalDest << " / " << mURI << " @ " << mRect
- << "]";
+ aStringStream << "Link [" << mLocalDest.data() << " / " << mURI.data()
+ << " @ " << mRect << "]";
}
}
@@ -4651,35 +4641,33 @@ inline bool RecordedDestination::PlayEvent(Translator* aTranslator) const {
if (!dt) {
return false;
}
- dt->Destination(mDestination.c_str(), mPoint);
+ dt->Destination(mDestination.data(), mPoint);
return true;
}
template <class S>
void RecordedDestination::Record(S& aStream) const {
WriteElement(aStream, mPoint);
- uint32_t len = mDestination.length();
- WriteElement(aStream, len);
- if (len) {
- aStream.write(mDestination.data(), len);
- }
+ WriteElement(aStream, mDestination.size());
+ mDestination.Write(aStream);
}
template <class S>
RecordedDestination::RecordedDestination(S& aStream)
: RecordedEventDerived(DESTINATION) {
ReadElement(aStream, mPoint);
- uint32_t len;
+ size_t len = 0;
ReadElement(aStream, len);
- mDestination.resize(size_t(len));
- if (len && aStream.good()) {
- aStream.read(&mDestination.front(), len);
+ if (!aStream.good() || (len && !mDestination.Read(aStream, len))) {
+ aStream.SetIsBad();
+ return;
}
}
inline void RecordedDestination::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
- aStringStream << "Destination [" << mDestination << " @ " << mPoint << "]";
+ aStringStream << "Destination [" << mDestination.data() << " @ " << mPoint
+ << "]";
}
#define FOR_EACH_EVENT(f) \