fluffos/testsuite/include/trailing_comment_pin.h
Yucong Sun 1672e9a138 Hardening: lexer.l rename, LexTokenStream removed, five real bugs fixed,
coverage along the failure axes

RENAME + NORMALIZE:
- lex.l -> lexer.l, lex.h -> lexer.h, lex.autogen.cc -> lexer.autogen.cc
  (matching lexer_rules/lexer_utils); the flex POST_BUILD copy runs the
  same NORMALIZE path-sanitizing step as bison's outputs, with a
  symmetric DENORMALIZE no-flex fallback.

LEXTOKENSTREAM REMOVED (the scanner IS the interface):
- It had become a forwarding wrapper; compile_file and stage_output
  drive the reentrant scanner directly, with the scanner guard ordered
  BEFORE the cleanup guard.

FIVE REAL BUGS -- two caught in production on a live mud:
1. Unwind-order UAF: the wrapper was declared after the cleanup DEFER,
   so exception unwinds destroyed the scanner before teardown deleted
   the flex buffers. Fixed by guard ordering.
2. Stale active-scanner UAF (pinned by FatalAbortThenRecompile): an
   aborted compile skips end_new_file; the NEXT compile's current_line
   save read destroyed scanner guts. Owners now call
   lpc_lex_scanner_destroyed() before yylex_destroy.
3. Release-only spin: lpc_dump_stage_tokens skipped the shared-string
   table reset; a second dump walked stale hash chains into a freed
   A_STRINGS block. The stage env now mirrors the harness.
4. FIELD BUG -- #include with trailing comment: the include parser
   assumed the closing delimiter was the line's LAST character, so
   `#include <mudlib.h> /* ... */` swallowed the comment into the
   filename (classic-mudlib ftpdconf.h failed). Scan to the closing
   delimiter; trailing text is ignored (historical behavior); missing
   close is a clean error.
5. FIELD BUG -- teardown-vs-mem_block ordering UAF: an abort with a
   LIVE include buffer (inherit or fatal INSIDE an included file) had
   clean_parser free the mem_block areas BEFORE buffer teardown, whose
   include-accounting pops write into them (ASan WRITE on a live mud).
   Teardown now runs first in clean_parser; the success epilog is
   ordered symmetrically.

Also: compile_file_fd's explicit fd flag (a -1 sentinel silently
compiled the empty view), parse loop skipped on load failure, unified
stage_output cleanup.

COVERAGE (all portable: tmpfile(), no /tmp/mkstemp/open_memstream):
16 new unit tests -- fd entry success/bad-fd/pipe-growth, fatal aborts
from the main buffer, inside an include, and inside a #if expression
(suppress_expansion unstranded), unterminated text block/template,
include depth limit, empty and no-final-newline includes, trailing
block/line-comment includes with clean-name diagnostics, stage-output
pp/tokens/load-failure. Two LPC testsuite pins run under ASan on every
platform: include_trailing_comment.c (ftpdconf.h shape) and
inherit_via_include.c (the abort-and-reload with the inherit inside an
included file).

Post-CI portability/leak follow-ups folded in: the pipe-growth test is
fork-free (fits the pipe buffer; _pipe on Windows -- sys/wait.h broke
MinGW), and the two test environments share one init guard (mixing the
full boot with the tokenizer harness in one process double-called
init_strings, orphaning a 64KB string table -- LeakSanitizer-caught in
the CI sanitizer job).

297 tests under ASan/UBSan (leak detection on), driver-autotest x3.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 20:48:48 -04:00

4 lines
174 B
C

// Include target for include_trailing_comment.c -- resolved via the
// config's angle-bracket include path.
#define TRAILING_PIN_VALUE 42
#define TRAILING_PIN_NAME "pinned"