Skip to content

Global Buffer Underflow (OOB Write) in scan.l via embedded null byte #725

Description

@MarcSchoenefeld

When parsing an %option directive containing a quoted string, if the input file contains a literal null byte (\0) immediately following the opening quote, strlen() evaluates to 0. The subsequent attempt to strip the trailing quote results in an index -1 write, corrupting the memory immediately preceding the nmstr buffer.

Depending on the compiler and memory layout, this null-byte underflow can corrupt adjacent global variables, leading to undefined behavior during C-code generation.

  1. Environment
    Target: GNU flex commit 13c8018 (HEAD -> master, origin/master, origin/HEAD)
    Compiler: clang with AddressSanitizer (-fsanitize=address)

  2. Reproduction Steps
    I have attached the minimized 14-byte PoC. Because copying and pasting null bytes can be tricky, you can reconstruct it via printf:

# 1. Generate the PoC
printf '\x25\x6f\x70\x74\x69\x6f\x6e\x65\x6d\x69\x74\x22\x00\x22' > poc.l


# 2. Run flex
./src/flex -o /dev/null poc.l
  1. ASAN Trace Summary
==ERROR: AddressSanitizer: global-buffer-overflow ...
WRITE of size 1 at 0x5f0f489a2e3f thread T0
    #0 0x5f0f47f17fd0 in flexscan flex/src/scan.l:490:31
    #1 0x5f0f47efb830 in yylex flex/src/yylex.c:51:13


0x5f0f489a2e3f is located 1 bytes before global variable 'nmstr' of size 2048
  1. Root Cause & Suggested Patch
    In src/scan.l (around line 490), the code attempts to strip a trailing character without verifying that the string has a length greater than 0:
nmstr[strlen( nmstr ) - 1] = '\0';

If a null byte is embedded in the token, strlen(nmstr) evaluates to 0, resulting in nmstr[-1] = '\0'.

Suggested Fix:
Add a bounds check to ensure the string is not empty before decrementing:

size_t len = strlen(nmstr);
if (len > 0) {
    nmstr[len - 1] = '\0';
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions