Skip to content

Commit 9e61d63

Browse files
committed
Fix overflow on short loca with offset values > 65536.
1 parent 168592b commit 9e61d63

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

common/font_helper_test.cc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,61 @@ TEST_F(FontHelperTest, BuildFont) {
478478
ASSERT_EQ(table_2.str(), "table_2");
479479
}
480480

481+
TEST_F(FontHelperTest, GlyfData_ShortOverflow) {
482+
// This glyph has a start < 65536 and end > 65536 and so will create an
483+
// overflow in offset calculation if the wrong data types are used.
484+
auto data = FontHelper::GlyfData(roboto_vf.get(), 558);
485+
ASSERT_TRUE(data.ok()) << data.status();
486+
ASSERT_GT(data->size(), 0);
487+
}
488+
489+
TEST_F(FontHelperTest, GlyfData_ShortOverflowSynthetic) {
490+
hb_face_unique_ptr face = make_hb_face(hb_face_builder_create());
491+
492+
std::vector<uint8_t> loca = {
493+
0xC3, 0x50, // 50,000 (100,000 actual)
494+
0xC3, 0x52, // 50,002 (100,005 actual)
495+
};
496+
{
497+
auto blob =
498+
make_hb_blob(hb_blob_create((const char*)loca.data(), loca.size(),
499+
HB_MEMORY_MODE_READONLY, nullptr, nullptr));
500+
hb_face_builder_add_table(face.get(), HB_TAG('l', 'o', 'c', 'a'),
501+
blob.get());
502+
}
503+
504+
std::vector<uint8_t> head(53, 0);
505+
head[51] = 0;
506+
{
507+
auto blob =
508+
make_hb_blob(hb_blob_create((const char*)head.data(), head.size(),
509+
HB_MEMORY_MODE_READONLY, nullptr, nullptr));
510+
hb_face_builder_add_table(face.get(), HB_TAG('h', 'e', 'a', 'd'),
511+
blob.get());
512+
}
513+
514+
std::vector<uint8_t> glyf(100004, 0);
515+
glyf[100000] = 1;
516+
glyf[100001] = 2;
517+
glyf[100002] = 3;
518+
glyf[100003] = 4;
519+
{
520+
auto blob =
521+
make_hb_blob(hb_blob_create((const char*)glyf.data(), glyf.size(),
522+
HB_MEMORY_MODE_READONLY, nullptr, nullptr));
523+
hb_face_builder_add_table(face.get(), HB_TAG('g', 'l', 'y', 'f'),
524+
blob.get());
525+
}
526+
527+
auto blob = make_hb_blob(hb_face_reference_blob(face.get()));
528+
auto concrete_face = make_hb_face(hb_face_create(blob.get(), 0));
529+
530+
auto data = FontHelper::GlyfData(concrete_face.get(), 0);
531+
ASSERT_TRUE(data.ok()) << data.status();
532+
std::string expected = {1, 2, 3, 4};
533+
ASSERT_EQ(*data, expected);
534+
}
535+
481536
// TODO test BuildFont...
482537

483538
} // namespace common

common/indexed_data_reader.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef COMMON_INDEXED_DATA_READER_H_
22
#define COMMON_INDEXED_DATA_READER_H_
33

4+
#include <cstdint>
5+
46
#include "absl/status/statusor.h"
57
#include "absl/strings/str_cat.h"
68
#include "absl/strings/string_view.h"
@@ -28,11 +30,14 @@ class IndexedDataReader {
2830
absl::StrCat("Entry ", id, " not found in offset table."));
2931
}
3032

31-
offset_type start_offset =
32-
ReadValue(start_index, offsets_) * offset_multiplier;
33-
offset_type end_offset = ReadValue(end_index, offsets_) * offset_multiplier;
33+
uint32_t start_offset =
34+
((uint32_t)ReadValue(start_index, offsets_)) * offset_multiplier;
35+
uint32_t end_offset =
36+
((uint32_t)ReadValue(end_index, offsets_)) * offset_multiplier;
3437
if (end_offset < start_offset) {
35-
return absl::InvalidArgumentError("Invalid index. end < start.");
38+
return absl::InvalidArgumentError(
39+
absl::StrCat("Invalid index. end (", end_offset, ") < start (",
40+
start_offset, "), width = ", width, "."));
3641
}
3742

3843
if (end_offset > data_.size()) {

0 commit comments

Comments
 (0)