Просмотр исходного кода

LibGfx/WOFF2: Tolerate incorrect `totalSfntSize` in WOFF2 header

The specification says that this value is for reference only, so we
should be able to load a file where this value is incorrect.
Tim Ledbetter 1 год назад
Родитель
Сommit
af633523af

+ 1 - 0
Tests/LibGfx/CMakeLists.txt

@@ -10,6 +10,7 @@ set(TEST_SOURCES
     TestRect.cpp
     TestScalingFunctions.cpp
     TestWOFF.cpp
+    TestWOFF2.cpp
 )
 
 foreach(source IN LISTS TEST_SOURCES)

+ 22 - 0
Tests/LibGfx/TestWOFF2.cpp

@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2023, Tim Ledbetter <timledbetter@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibGfx/Font/WOFF2/Font.h>
+#include <LibTest/TestCase.h>
+
+#ifdef AK_OS_SERENITY
+#    define TEST_INPUT(x) ("/usr/Tests/LibGfx/test-inputs/" x)
+#else
+#    define TEST_INPUT(x) ("test-inputs/" x)
+#endif
+
+TEST_CASE(tolerate_incorrect_sfnt_size)
+{
+    auto file = MUST(Core::MappedFile::map(TEST_INPUT("woff2/incorrect_sfnt_size.woff2"sv)));
+    auto font = TRY_OR_FAIL(WOFF2::Font::try_load_from_externally_owned_memory(file->bytes()));
+    EXPECT_EQ(font->family(), "Test"_string);
+    EXPECT_EQ(font->glyph_count(), 4u);
+}

BIN
Tests/LibGfx/test-inputs/woff2/incorrect_sfnt_size.woff2


+ 3 - 1
Userland/Libraries/LibGfx/Font/WOFF2/Font.cpp

@@ -856,6 +856,7 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Seekabl
     // The interpretation of the WOFF2 Header is the same as the WOFF Header in [WOFF1], with the addition of one new totalCompressedSize field.
     // NOTE: See WOFF/Font.cpp for more comments about this.
 
+    static constexpr size_t MAX_BUFFER_SIZE = 10 * MiB;
     if (header.length > TRY(stream.size()))
         return Error::from_string_literal("Invalid WOFF length");
     if (header.meta_length == 0 && header.meta_offset != 0)
@@ -869,7 +870,8 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Seekabl
     //        but if the transformed 'glyf' and 'loca' tables are present, the uncompressed size of the reconstructed tables and the total decompressed font size may differ
     //        substantially from the original total size specified in the WOFF2 Header."
     //        We use it as an initial size of the font buffer and extend it as necessary.
-    auto font_buffer = TRY(ByteBuffer::create_zeroed(header.total_sfnt_size));
+    auto font_buffer_size = clamp(header.total_sfnt_size, sizeof(OpenType::TableDirectory) + header.num_tables * sizeof(TableDirectoryEntry), MAX_BUFFER_SIZE);
+    auto font_buffer = TRY(ByteBuffer::create_zeroed(font_buffer_size));
 
     u16 search_range = pow_2_less_than_or_equal(header.num_tables);
     OpenType::TableDirectory table_directory {