mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
update fuzzer docs
This commit is contained in:
@@ -114,6 +114,33 @@ harness ignores the extra bytes, so libFuzzer does not waste its budget:
|
||||
fuzz_postprocessor 8196 4 selector bytes + the POST body, truncated
|
||||
to 8192.
|
||||
|
||||
### rss_limit_mb, and why a long run creeps
|
||||
|
||||
libFuzzer's default `-rss_limit_mb=2048` counts the whole process, and an
|
||||
ASan-instrumented target grows slowly over hundreds of millions of
|
||||
executions even with no leak at all: ASan's allocator keeps a quarantine
|
||||
of freed chunks and does not return memory to the OS eagerly. A local
|
||||
two-hour campaign hit exactly this -- `fuzz_options` crept from 686 MB to
|
||||
1804 MB over 26M executions and was killed as an OOM, while
|
||||
LeakSanitizer stayed silent across 3M-execution runs and
|
||||
`MALLOC_ARENA_MAX` changed nothing (it is glibc's knob, and none of these
|
||||
allocations go through glibc).
|
||||
|
||||
Three arms of the same target over the same corpus, 4M executions each,
|
||||
settle it:
|
||||
|
||||
ASan, default quarantine 608 MB
|
||||
ASan, ASAN_OPTIONS=quarantine_size_mb=1 266 MB
|
||||
no sanitizer at all (glibc allocator) 36 MB
|
||||
|
||||
17x between the first and the last, with no code difference: the growth
|
||||
is the sanitizer's allocator holding freed memory, not the harness and
|
||||
not MHD.
|
||||
|
||||
So treat a slow, monotonic RSS climb as allocator retention rather than a
|
||||
finding. ClusterFuzz restarts its fuzzers periodically, which bounds it;
|
||||
do the same locally rather than raising the limit forever.
|
||||
|
||||
### close_fd_mask
|
||||
|
||||
Deliberately **not** set. The harnesses are quiet by default (MHD's
|
||||
|
||||
+56
-6
@@ -651,18 +651,68 @@ K9 postprocessor.c:1119 post_process_multipart():
|
||||
path no longer overwrites the old pointer either.
|
||||
Repro: corpus/known-findings/K9-fuzz_postprocessor-nested-boundary-leak.bin
|
||||
|
||||
K10 memorypool.c MHD_pool_deallocate(): end block of an exactly-full
|
||||
pool was never returned; the front/end dispatch tested pool->pos,
|
||||
where the two ranges meet. Fixed.
|
||||
|
||||
K11 memorypool.c MHD_pool_reallocate(): returned non-NULL for a
|
||||
wrapping @a new_size, handing the caller a block it believed was
|
||||
nearly SIZE_MAX bytes long. Fixed.
|
||||
|
||||
K12 daemon.c MHD_start_daemon_va(): leaked the GnuTLS DH parameters
|
||||
built from MHD_OPTION_HTTPS_MEM_DHPARAMS on every startup-failure
|
||||
exit. The application cannot free them. Fixed.
|
||||
|
||||
K13 daemon.c MHD_epoll() / MHD_quiesce_daemon(): both threads remove
|
||||
the listening socket from the epoll set, and the loser aborts on
|
||||
ENOENT. Open; two alternative fixes are proposed as
|
||||
../../patches/K13.diff (tolerate ENOENT everywhere) and
|
||||
../../patches/K13b.diff (take a lock, keep the strict check).
|
||||
|
||||
K14 daemon.c:1358 call_handlers():
|
||||
mhd_assert (! force_close || MHD_CONNECTION_CLOSED == con->state)
|
||||
Open, fix proposed in ../../patches/K14.diff.
|
||||
|
||||
MHD_connection_handle_read() closes the connection when its
|
||||
@a socket_error argument is set -- but only once it gets far enough
|
||||
to try. It returns early, leaving the state untouched, when the
|
||||
connection is suspended, when a TLS handshake is in progress, and
|
||||
when the read buffer has no free space at all. The caller asserts
|
||||
the post-condition unconditionally.
|
||||
|
||||
Instrumenting the assertion site with the reproducer gives
|
||||
|
||||
state=12 (HEADERS_PROCESSED) suspended=0
|
||||
rb_size=2021 rb_off=2021 evinfo=READ
|
||||
|
||||
i.e. the read buffer is exactly full. A client that fills the
|
||||
connection memory pool without the application consuming the body
|
||||
gets there; no unusual API use is involved. Observed through
|
||||
MHD_run_from_select2(), i.e. from the external event loop.
|
||||
|
||||
The reproducer does NOT fire on a plain in-tree gcc build: ASan's
|
||||
pool redzones change the buffer arithmetic enough to matter, so
|
||||
confirm it against the OSS-Fuzz build configuration.
|
||||
Repro: corpus/known-findings/K14-fuzz_eventloop-force-close-not-closed.bin
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
All nine findings are fixed on master:
|
||||
K1-K12 are fixed on master:
|
||||
|
||||
K1 300a2ab0 K4a 0b750975 K7 acef58a0
|
||||
K2 68c83f22 K4b 0b750975 K8 07c051dd
|
||||
K3 e04eb218 K5 6fcdfd43 K9 (this tree)
|
||||
K1 300a2ab0 K4a 0b750975 K7 acef58a0 K10 (memorypool)
|
||||
K2 68c83f22 K4b 0b750975 K8 07c051dd K11 (memorypool)
|
||||
K3 e04eb218 K5 6fcdfd43 K9 (postproc) K12 (daemon/TLS)
|
||||
K6 f438804c
|
||||
|
||||
The nine reproducers in `corpus/known-findings/` therefore all replay
|
||||
clean on a build configured with `--enable-asserts`, and
|
||||
K13 and K14 are open, with proposed fixes in ../../patches/. Until K14
|
||||
lands, `make check-corpus` fails on an `--enable-asserts` build, because
|
||||
its reproducer is committed and still reproduces -- which is the
|
||||
documented behaviour for an open finding, but worth knowing before a CI
|
||||
run.
|
||||
|
||||
The reproducers in `corpus/known-findings/` otherwise all replay clean
|
||||
on a build configured with `--enable-asserts`, and
|
||||
`make check-corpus` asserts exactly that -- it replays that directory
|
||||
along with the generated corpus. K8 has no reproducer, because its
|
||||
trigger is an argument the application chooses rather than anything that
|
||||
|
||||
@@ -170,6 +170,15 @@ hand-written input would be clobbered or renumbered by the next
|
||||
nested-boundary-leak.bin leaked the previous nested boundary
|
||||
on every extra nested
|
||||
multipart/mixed part
|
||||
K14-fuzz_eventloop- daemon.c call_handlers() asserted a
|
||||
force-close-not-closed.bin post-condition that
|
||||
MHD_connection_handle_read() does
|
||||
not guarantee when the read buffer
|
||||
is full
|
||||
*** still open, see ../../../patches ***
|
||||
Only fires on an --enable-asserts
|
||||
*ASan* build: the redzones change
|
||||
the pool arithmetic that reaches it.
|
||||
|
||||
These files are *not* regenerated by `--write-corpus`; they are edited by
|
||||
hand. When the input format changes they have to be migrated, and the
|
||||
|
||||
Reference in New Issue
Block a user