Skip to content

Potential crash / out-of-bounds iterator dereference in HttpFileImpl::save() #2655

Open

Description

@shadye-6

Describe the bug

Found a potential invalid iterator dereference while fuzzing in HttpFileImpl::save(const std::string &path) in lib/src/HttpFileImpl.cc. HttpFileImpl::save(const std::string &path) in lib/src/HttpFileImpl.cc uses the three-iterator overload of std::equal to check whether the canonical destination is inside the configured upload directory:

if (!std::equal(fsUploadDir.begin(),
                fsUploadDir.end(),
                fsSaveToPath.begin()))

This overload requires the second range to contain at least as many elements as the first. That condition is not guaranteed here. When a traversal filename resolves to a strict ancestor of the upload directory, the destination has fewer path components. std::equal may then dereference an iterator past fsSaveToPath.end(), resulting in undefined behavior. With libstdc++ assertions enabled (-D_GLIBCXX_ASSERTIONS), this reproduces as a process abort:

Assertion '_M_cur != _M_path->_M_cmpts.end()' failed.

To Reproduce

  1. Set the upload directory to:

    /tmp/drogon_app/a/b/c/upload
    
  2. Create an HttpFileImpl with the filename ../../c.

  3. Call file.save().

The canonical destination becomes /tmp/drogon_app/a/b/c, which has fewer path components than the upload directory.
Build Drogon's HttpFileImpl.cc with -D_GLIBCXX_ASSERTIONS and run the reproducer. The process aborts during the std::equal comparison.

Expected behavior

The traversal attempt should be rejected safely, with save() returning -1. Valid uploads, including those targeting nested subdirectories, should continue to work.

Environment

  • OS: Ubuntu 24.04 (WSL2)
  • Compiler: Clang 18.1.3
  • Standard library: GCC 13 libstdc++
  • Build: -D_GLIBCXX_ASSERTIONS
  • Drogon commit: df418bfdd99d4cc1ebd8598b8ced4f74d4f488ce

Suggested fix

Use the four-iterator overload of std::mismatch for a bounds-safe component-wise prefix check:

auto mismatch = std::mismatch(
    fsUploadDir.begin(),
    fsUploadDir.end(),
    fsSaveToPath.begin(),
    fsSaveToPath.end()
);

if (mismatch.first != fsUploadDir.end())
{
    LOG_ERROR
        << "Attempt writing outside of upload directory detected. Path: "
        << fileName_;
    return -1;
}

Unlike four-iterator std::equal, this allows the destination to contain additional components, preserving valid nested uploads while safely rejecting shorter or non-matching paths.
I can submit a PR with the proposed fix and regression tests if this approach looks reasonable.

Activity

  1. shadye-6 commented on Oct 31, 2026

    @shadye-6
    ContributorAuthor

    i've submitted a PR addressing this issue.
    PR: #2656 – [Fix out-of-bounds iterator dereference in HttpFileImpl::save()](#2656)
    The PR includes the std::mismatch fix and regression tests covering traversal paths and valid nested uploads. suggestions or changes will be appreciated.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions