nametabletest.cpp: fix out-of-bounds access on endianness conversion#74
nametabletest.cpp: fix out-of-bounds access on endianness conversion#74trofi wants to merge 1 commit intosilnrsi:masterfrom
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.
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 testBdeclarations 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
nametabletesttest failre on today'sgcc-13.-fsanitize=undefineddetected 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
toBigEndianhelper 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.