Skip to content

Commit 072f875

Browse files
committed
Fix UAF in FontCache
Fixes a rare crash related to font caching. Upstream issue: https://issues.chromium.org/issues/342778288 Its been only fixed for ASAN builds for some reason. This change backports the fix: https://crrev.com/c/5629253 and extends the ASAN guards with IS_QTWEBENGINE. Change-Id: I0fb7348ef97882fed199d1432b3a2543804e8de5 Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/592190 Reviewed-by: Peter Varga <[email protected]>
1 parent 673272f commit 072f875

File tree

1 file changed

+57
-16
lines changed

1 file changed

+57
-16
lines changed

chromium/third_party/blink/renderer/platform/fonts/font_face_creation_params.h

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
3939
#include "third_party/blink/renderer/platform/wtf/text/string_hasher.h"
4040

41+
#include <optional>
42+
4143
namespace blink {
4244

4345
enum FontFaceCreationType {
@@ -49,19 +51,10 @@ class FontFaceCreationParams {
4951
USING_FAST_MALLOC(FontFaceCreationParams);
5052

5153
public:
52-
FontFaceCreationParams()
53-
: creation_type_(kCreateFontByFamily),
54-
family_(AtomicString()),
55-
filename_(std::string()),
56-
fontconfig_interface_id_(0),
57-
ttc_index_(0) {}
54+
FontFaceCreationParams() : creation_type_(kCreateFontByFamily) {}
5855

5956
explicit FontFaceCreationParams(AtomicString family)
60-
: creation_type_(kCreateFontByFamily),
61-
family_(family),
62-
filename_(std::string()),
63-
fontconfig_interface_id_(0),
64-
ttc_index_(0) {
57+
: creation_type_(kCreateFontByFamily), family_(family) {
6558
#if BUILDFLAG(IS_WIN)
6659
// Leading "@" in the font name enables Windows vertical flow flag for the
6760
// font. Because we do vertical flow by ourselves, we don't want to use the
@@ -88,8 +81,14 @@ class FontFaceCreationParams {
8881
}
8982
const std::string& Filename() const {
9083
DCHECK_EQ(creation_type_, kCreateFontByFciIdAndTtcIndex);
84+
#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_QTWEBENGINE)
85+
DCHECK(filename_.has_value());
86+
return *filename_;
87+
#else
9188
return filename_;
89+
#endif
9290
}
91+
9392
int FontconfigInterfaceId() const {
9493
DCHECK_EQ(creation_type_, kCreateFontByFciIdAndTtcIndex);
9594
return fontconfig_interface_id_;
@@ -106,8 +105,11 @@ class FontFaceCreationParams {
106105
// encoding and endianness. However, since the hash is not transferred
107106
// over a network or permanently stored and only used for the runtime of
108107
// Chromium, this is not a concern.
109-
hasher.AddCharacters(reinterpret_cast<const LChar*>(filename_.data()),
110-
static_cast<unsigned>(filename_.length()));
108+
if (HasFilename()) {
109+
const auto& filename = Filename();
110+
hasher.AddCharacters(reinterpret_cast<const LChar*>(filename.data()),
111+
static_cast<unsigned>(filename.length()));
112+
}
111113
hasher.AddCharacters(reinterpret_cast<const LChar*>(&ttc_index_),
112114
sizeof(ttc_index_));
113115
hasher.AddCharacters(
@@ -121,17 +123,56 @@ class FontFaceCreationParams {
121123
bool operator==(const FontFaceCreationParams& other) const {
122124
return creation_type_ == other.creation_type_ &&
123125
DeprecatedEqualIgnoringCase(family_, other.family_) &&
124-
filename_ == other.filename_ &&
126+
FilenameEqual(other) &&
125127
fontconfig_interface_id_ == other.fontconfig_interface_id_ &&
126128
ttc_index_ == other.ttc_index_;
127129
}
128130

129131
private:
130132
FontFaceCreationType creation_type_;
131133
AtomicString family_;
134+
135+
void SetFilename(std::string& filename) {
136+
#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_QTWEBENGINE)
137+
*filename_ = filename;
138+
#else
139+
filename_ = filename;
140+
#endif
141+
}
142+
143+
bool FilenameEqual(const FontFaceCreationParams& other) const {
144+
#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_QTWEBENGINE)
145+
if (!filename_.has_value() || !other.filename_.has_value()) {
146+
return filename_.has_value() == other.filename_.has_value();
147+
}
148+
return *filename_ == *other.filename_;
149+
#else
150+
return filename_ == other.filename_;
151+
#endif
152+
}
153+
154+
bool HasFilename() const {
155+
#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_QTWEBENGINE)
156+
return filename_.has_value();
157+
#else
158+
return true;
159+
#endif
160+
}
161+
162+
#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_QTWEBENGINE)
163+
// We put the `std::string` behind an optional as ASAN counter checks require
164+
// that we properly call constructors and destructors for all strings. This is
165+
// not the case when `FontFaceCreationParams` is used in `WTF::HashMap` as key
166+
// where we also cosntruct empty and deleted values that are never properly
167+
// destroyed.
168+
//
169+
// See crbug.com/346174906.
170+
std::optional<std::string> filename_;
171+
#else
132172
std::string filename_;
133-
int fontconfig_interface_id_;
134-
int ttc_index_;
173+
#endif
174+
int fontconfig_interface_id_ = 0;
175+
int ttc_index_ = 0;
135176
};
136177

137178
} // namespace blink

0 commit comments

Comments
 (0)