Repository navigation
Conversation
The fuzz targets are built by this Makefile, which compiles the Brotli decoder
from the brotli submodule. Brotli's default build reads 16, 32 and 64-bit words
by casting a byte pointer to the target type and dereferencing it. The
compressed input is byte addressed and advances by arbitrary amounts, so those
pointers are frequently misaligned, and the dereference is undefined behavior
on both the alignment and the strict aliasing count. The upstream harness
src/convert_woff2ttf_fuzzer.cc reports it:
c/dec/../common/platform.h:214:10: runtime error: load of misaligned
address 0x630000010469 for type 'const uint32_t' (aka 'const unsigned
int'), which requires 4 byte alignment
#0 BrotliUnalignedRead32 brotli/c/common/platform.h:214:10
google#1 BrotliFillBitWindow brotli/c/dec/bit_reader.h:130:30
google#2 BrotliFillBitWindow16 brotli/c/dec/bit_reader.h:159:3
google#3 ReadSymbolCodeLengths brotli/c/dec/decode.c:607:5
google#4 ReadHuffmanCode brotli/c/dec/decode.c:826:41
...
google#7 woff2::Woff2Uncompress src/woff2_dec.cc:801:32
google#8 woff2::ConvertWOFF2ToTTF src/woff2_dec.cc:1381:7
woff2 hands Brotli the raw compressed bytes of the WOFF2 stream, so the
misalignment cannot be avoided from this side. It is not specific to malformed
fonts either; a handful of ordinary WOFF2 fonts trips the same read on the
first file.
Brotli uses memcpy based loads when BROTLI_BUILD_PORTABLE is defined, and its
own CMake defines it for undefined behavior sanitizer builds. Pass it when
building the dependency here, so that `make`, which produces the fuzz targets,
no longer depends on undefined behavior.
Refreshing the brotli submodule to a release that no longer has the casts would
also work, but not by itself: Brotli removed its Makefile build in July 2023 and
this Makefile still drives that one, so moving woff2 onto Brotli's CMake build
has to happen first (google#144, google#162).
Decoding is unchanged: both builds decode real fonts to byte identical output,
and compilers still emit a single load on targets that support unaligned
access.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Friendly nudge: this has been open a week with no reviewer. @eustas @rsheeter would either of you have a moment to look? It is a one-line Makefile flag ( |
|
Friendly nudge — and apologies in advance for the direct pings. This has been open for a week with the CLA check and CI green and no reviewer @eustas @rsheeter @drott @sharadboni — would one of you have a moment to look at The change is a one-line addition to the BROTLI_CPPFLAGS ?= -DBROTLI_BUILD_PORTABLE
...
- $(MAKE) -C $(BROTLI) lib
+ $(MAKE) -C $(BROTLI) lib CPPFLAGS="$(BROTLI_CPPFLAGS)"Brotli's own CMake build does the same thing, and Why it seemed worth a PR rather than just a report: with clang and Reported in #202. Thanks either way. |
Problem
The fuzz targets built by this Makefile compile the Brotli decoder from the
brotlisubmodule. Brotli's default build reads 16, 32 and 64-bit words bycasting a byte pointer to the target type and dereferencing it, for example in
brotli/c/common/platform.h:The compressed input is byte addressed and the bit reader advances
next_inbyan arbitrary number of bytes, so those pointers are frequently misaligned and
the dereference is undefined behavior. Found with UBSan under the upstream
src/convert_woff2ttf_fuzzer.ccharness:This is not specific to malformed input. With the same build, a small corpus of
ordinary WOFF2 fonts reports the identical read on its first file.
woff2 hands Brotli the raw compressed bytes of the WOFF2 stream, so the
misalignment cannot be avoided from this side; the load itself has to change.
Change
Brotli already ships the implementation this needs. When
BROTLI_BUILD_PORTABLEis defined, the same helpers read throughmemcpy, andBrotli's own CMake build defines it whenever
ENABLE_SANITIZERisundefined:Pass that define to the dependency from the
depsrule, which is the buildthat produces the fuzz targets.
Alternatives
repository.
brotlibecame a submodule, and the helper named in the originalreport (
brotli/c/dec/bit_reader.h,BrotliLoad32LE(), from the v1.0.2snapshot) does not exist at the pinned revision. The same reads are now
BrotliUnalignedRead32()and friends inbrotli/c/common/platform.h.brotlisubmodule to a release whose loads no longer use typedcasts, and keeping the vendored copy in sync, is the right long term fix, but
it is not sufficient by itself: the submodule is pinned to a 2018 commit, and
Brotli removed its Makefile build in July 2023 (google/brotli
d1fadddc94),which is the build this Makefile drives. Renewing the dependency therefore
means moving woff2 onto Brotli's CMake build first (Update brotli to v1.0.9 #144, feat: update brotli to v1.1.0 #162).
Verification
Built with clang and
-fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer -O2 -g,using
makefor the dependency and the fuzz target, and run throughsrc/convert_woff2ttf_fuzzer.cc.misaligned load above.
diagnostics.
produces byte-identical TTF output.
Fixes #202