From af633523afc1cd49dcac53dc7590485b64f794e0 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Tue, 24 Oct 2023 07:54:20 +0100 Subject: [PATCH] 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. --- Tests/LibGfx/CMakeLists.txt | 1 + Tests/LibGfx/TestWOFF2.cpp | 22 ++++++++++++++++++ .../woff2/incorrect_sfnt_size.woff2 | Bin 0 -> 640 bytes Userland/Libraries/LibGfx/Font/WOFF2/Font.cpp | 4 +++- 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 Tests/LibGfx/TestWOFF2.cpp create mode 100644 Tests/LibGfx/test-inputs/woff2/incorrect_sfnt_size.woff2 diff --git a/Tests/LibGfx/CMakeLists.txt b/Tests/LibGfx/CMakeLists.txt index e11157988f..b66e75844c 100644 --- a/Tests/LibGfx/CMakeLists.txt +++ b/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) diff --git a/Tests/LibGfx/TestWOFF2.cpp b/Tests/LibGfx/TestWOFF2.cpp new file mode 100644 index 0000000000..221ff53110 --- /dev/null +++ b/Tests/LibGfx/TestWOFF2.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023, Tim Ledbetter + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +#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); +} diff --git a/Tests/LibGfx/test-inputs/woff2/incorrect_sfnt_size.woff2 b/Tests/LibGfx/test-inputs/woff2/incorrect_sfnt_size.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..086e00413a654f7bccc6fe56b3c279a8890c7bf6 GIT binary patch literal 640 zcmXT-cQayOWME)mU}|9C1JNMNqzw@Ru~D(Tn_GyljFb#p0z;D%2a6yFS4|@uHx~n= z8IuaL0E+@^a}>Ll^iLLsdCi5+@m?L*oLpRPu8{tITKeOMzc;oQ-`}mBmMN_??dTfE z%!;IpCB7A>^$Mkp@4xzfd9S>KvL4@yPfTkfB+3|KOstNnZreI{$D)FXXV-;4(^~U) z|Lhp{DF@iCreE8T!5ejcd8?*adiQkJX$eZHbECWx*Z2_Yd^u$jR&S_byt=>%ef}-s#=?RiVMF?{s8OvF2!K zPW#x^<=N#Ml@gOLwxp!bOzO(!%N1P>8EOoH0SpX`wTZ0L=V`k;m`IsSSRg8TSAuau zgcI|`n|Cf=ncAM)_D%SzvpHYvTp!e5`@Fs8?3w%S(*7ypjB)JK@^)=|@i%yS z+Tq*2*H`^qUa&GaMOZgM;&HuWVY<_YCzn1RPp`Vvy;k#R;gPz5T>|Ex36Ay2Q55IrSl a{5N`B&|f*%e6t^;l%@a!gOK9NJQe^V(g*ec literal 0 HcmV?d00001 diff --git a/Userland/Libraries/LibGfx/Font/WOFF2/Font.cpp b/Userland/Libraries/LibGfx/Font/WOFF2/Font.cpp index d27805928c..f22a894995 100644 --- a/Userland/Libraries/LibGfx/Font/WOFF2/Font.cpp +++ b/Userland/Libraries/LibGfx/Font/WOFF2/Font.cpp @@ -856,6 +856,7 @@ ErrorOr> 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> 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 {