LibGfx/WOFF: Ensure header totalSfntSize matches expected value

This commit is contained in:
Tim Ledbetter 2023-10-23 21:48:15 +01:00 committed by Andreas Kling
parent 7ee09ca49d
commit c2112cde76
Notes: sideshowbarker 2024-07-17 01:51:00 +09:00
4 changed files with 37 additions and 0 deletions

View file

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

27
Tests/LibGfx/TestWOFF.cpp Normal file
View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023, Tim Ledbetter <timledbetter@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Font/WOFF/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(malformed_woff)
{
Array test_inputs = {
TEST_INPUT("woff/invalid_sfnt_size.woff"sv)
};
for (auto test_input : test_inputs) {
auto file = MUST(Core::MappedFile::map(test_input));
auto font_or_error = WOFF::Font::try_load_from_externally_owned_memory(file->bytes());
EXPECT(font_or_error.is_error());
}
}

Binary file not shown.

View file

@ -91,6 +91,7 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Readonl
// (The value 0x74727565 'true' has been used for some TrueType-flavored fonts on Mac OS, for example.)
// Whether client software will actually support other types of sfnt font data is outside the scope of the WOFF specification, which simply describes how the sfnt is repackaged for Web use.
auto expected_total_sfnt_size = sizeof(OpenType::TableDirectory) + header.num_tables * 16;
if (header.length > buffer.size())
return Error::from_string_literal("Invalid WOFF length");
if (header.num_tables > NumericLimits<u16>::max() / 16)
@ -103,6 +104,8 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Readonl
return Error::from_string_literal("Invalid WOFF private block offset");
if (sizeof(Header) + header.num_tables * sizeof(TableDirectoryEntry) > header.length)
return Error::from_string_literal("Truncated WOFF table directory");
if (header.total_sfnt_size < expected_total_sfnt_size)
return Error::from_string_literal("Invalid WOFF total sfnt size");
if (header.total_sfnt_size > 10 * MiB)
return Error::from_string_literal("Uncompressed font is more than 10 MiB");
auto font_buffer = TRY(ByteBuffer::create_zeroed(header.total_sfnt_size));
@ -121,6 +124,9 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Readonl
for (size_t i = 0; i < header.num_tables; ++i) {
auto entry = TRY(stream.read_value<TableDirectoryEntry>());
expected_total_sfnt_size += (entry.orig_length + 3) & 0xFFFFFFFC;
if (expected_total_sfnt_size > header.total_sfnt_size)
return Error::from_string_literal("Invalid WOFF total sfnt size");
if ((size_t)entry.offset + entry.comp_length > header.length)
return Error::from_string_literal("Truncated WOFF table");
if (font_buffer_offset + entry.orig_length > font_buffer.size())
@ -150,6 +156,9 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Readonl
font_buffer_offset += entry.orig_length;
}
if (header.total_sfnt_size != expected_total_sfnt_size)
return Error::from_string_literal("Invalid WOFF total sfnt size");
auto input_font = TRY(OpenType::Font::try_load_from_externally_owned_memory(font_buffer.bytes(), index));
auto font = adopt_ref(*new Font(input_font, move(font_buffer)));
return font;