-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nametabletest.cpp: fix out-of-bounds access on endianness conversion #74
base: master
Are you sure you want to change the base?
Conversation
Initially observed as a `nametabletest` test failre on today's `gcc-13`. `-fsanitize=undefined` detected off-by-one error accessing one element past NameRecord array: $ ./tests/nametabletest/nametabletest tests/nametabletest/nametabletest.cpp:142:79: runtime error: index 5 out of bounds for type 'NameRecord [5]' ... tests/nametabletest/nametabletest.cpp:142:79: runtime error: index 7 out of bounds for type 'NameRecord [7]' ... This happens because test record are slightly inconsistent: when name array has N entries N+1 is specified as count, and local `toBigEndian` helper uses this count to iterate over local array. The rest of code (like `NameTable::getLanguageId`) seems to assume that table count is off-by-one. The change fixes test failure on this week's `gcc-13`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for spotting this bug. Looking into this further the real source of the bug is the use of sizeof(TtfUtil::Sfnt::FontNames)
in calculating the nameheader count values initialised into testA
and testB
declarations at the start of the file. The underlying structure (FontName
) includes a C++ spec compliant version of a flexible member array at the end, but due to C++ this cannot be 0, so it is 1 (these structures are designed for memory mapped reading of TTF files, rather than generation and writing). Several compilers permit 0 length arrays in that position, but that is due a compiler specific language extension, and we're trying to keep code like this as spec compliant as possible. That is where the +1 is coming from.
We do however include a non-entry for that first record embedded in the struct FontName
, which the code in NameTable::getLanguageId() does process thus the +1 count is correct there. But as you identified we don't processs entries after that first one in the testcase and therefore the code in toBigEndian requires require the adjusted value.
@trofi This lead down quite the rabbit hole as it turns out |
Without the change the test fails on gcc-13 as: $ ./tests/nametabletest/nametabletest tests/nametabletest/nametabletest.cpp:142:79: runtime error: index 5 out of bounds for type 'NameRecord [5]' ... tests/nametabletest/nametabletest.cpp:142:79: runtime error: index 7 out of bounds for type 'NameRecord [7]' ... In silnrsi/graphite#74 upstream agrees it's a problem in the test (and possibly the library). Let's disable the test itself until upstream fixes it completely.
Initially observed as a
nametabletest
test failre on today'sgcc-13
.-fsanitize=undefined
detected off-by-one error accessing one element past NameRecord array:This happens because test record are slightly inconsistent: when name array has N entries N+1 is specified as count, and local
toBigEndian
helper uses this count to iterate over local array.The rest of code (like
NameTable::getLanguageId
) seems to assume that table count is off-by-one.The change fixes test failure on this week's
gcc-13
.