Skip to content

Unhandled std::out_of_range exception in MultipartParser::processPartData causes process termination #10

@hjpaul17

Description

@hjpaul17

Summary

MultipartParser::processPartData() may throw an uncaught std::out_of_range exception when parsing certain malformed multipart inputs.
If the caller does not explicitly catch this exception, the entire process terminates.

This behavior can be triggered by crafted input alone and was discovered via coverage-guided fuzzing.


Steps to Reproduce

1. Minimal crashing input

Save the following input as min_crash.

Base64-encoded:
LS1CT1VOREFSWQ0KQ2VuRGlzcG9zaXRpLUJPVU5EQVJZDQot

Decoded content:
--BOUNDARY
CenDispositi-BOUNDARY


2. Reproducer program

Create a file named repro.cpp with the following contents:

#include <fstream>
#include <vector>
#include <iostream>
#include "MultipartReader.h"

int main(int argc, char** argv) {
    if (argc != 2) {
        std::cerr << "usage: " << argv[0] << " <input>\n";
        return 1;
    }

    std::ifstream f(argv[1], std::ios::binary);
    std::vector<char> buf(
        (std::istreambuf_iterator<char>(f)),
        std::istreambuf_iterator<char>()
    );

    MultipartReader r("BOUNDARY");

    try {
        size_t off = 0;
        while (off < buf.size() && !r.stopped()) {
            size_t chunk = std::min<size_t>(16, buf.size() - off);
            r.feed(buf.data() + off, chunk);
            off += chunk;
        }
    } catch (const std::exception& e) {
        std::cerr << "caught exception: " << e.what() << "\n";
        return 1;
    }

    return 0;
}

3. Build and run

clang++ -O1 -g -I. repro.cpp -o repro
./repro min_crash

Actual Behavior

The program terminates due to an uncaught exception:

caught exception: index overflows lookbehind buffer

If the exception is not explicitly caught by the caller, the process aborts:

libc++abi: terminating due to uncaught exception of type std::out_of_range

Expected Behavior

Malformed multipart input should be handled gracefully, for example by:

  • Transitioning to an internal error state
  • Returning an error code
  • Rejecting the input without throwing an uncaught exception

The parser should not terminate the entire process due to malformed input.

Root Cause Analysis

In MultipartParser::processPartData():

if (index - 1 >= lookbehindSize) {
    setError("Parser bug: index overflows lookbehind buffer. "
             "Please send bug report with input file attached.");
    throw std::out_of_range("index overflows lookbehind buffer");
}

When parsing malformed multipart boundaries, the internal index value can grow beyond lookbehindSize.
This triggers a std::out_of_range exception, which is not handled inside the parser and propagates to the caller.

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