Repository navigation
Conversation
|
@shadye-6 Thanks for the fix and the regression tests. The std::mismatch change looks correct to me: it avoids dereferencing past fsSaveToPath.end() while still requiring fsUploadDir to be a prefix of the destination path.
|
|
I checked the files changed of PR #2659. It modifies the same path-validation logic in
|
Please rebase from master branch and keep these tests, thanks so much. |
Use 4-iterator std::mismatch instead of 3-iterator std::equal when validating destination upload paths. Under ISO C++17 [alg.equal], 3-iterator std::equal assumes the second range has at least as many elements as the first. When an untrusted multipart filename resolves to an ancestor path with fewer components than the upload directory (e.g. .. or ../../c), std::equal dereferenced past-the-end iterators, causing SIGABRT under _GLIBCXX_ASSERTIONS. Also add unit test cases to HttpFileTest covering strict prefix traversal, dot-dot traversal, and legitimate nested subdirectory uploads. Fixes #2655
9b774a9 to
ff89c78
Compare
|
@an-tao after rebasing i encountered a Windows MSVC static CI timeout in HttpFileExceptionSafety, for which i tried debugging the root cause. |
Summary
Fixes #2655
In
HttpFileImpl::save(const std::string &path)(lib/src/HttpFileImpl.cc), destination path validation previously used the three-iterator overload ofstd::equal:if (!std::equal(fsUploadDir.begin(), fsUploadDir.end(), fsSaveToPath.begin()))Under ISO C++17
[alg.equal], three-iteratorstd::equalrequires that the second range (fsSaveToPath) contains at least as many elements as the first range (fsUploadDir). When an untrusted multipart upload filename resolves viastd::filesystem::weakly_canonicalto an ancestor directory (such as../../cwhen uploading to.../a/b/c/upload, or..),fsSaveToPathcontains fewer path components thanfsUploadDir.When all components of the shorter destination path match the corresponding upload-directory components, std::equal attempts to dereference the second iterator after it has reached fsSaveToPath.end(). This violates the algorithm's range precondition and results in undefined behavior. Under standard library assertion modes (
-D_GLIBCXX_ASSERTIONS), this consistently triggers a process abort inside thenoexceptmethod:Solution
Replaced the three-iterator
std::equalwith the four-iterator overload ofstd::mismatch:Unlike four-iterator
std::equal(which enforces strict equality of range lengths and would reject legitimate uploads to subdirectories),std::mismatchensuresfsUploadDiris a valid prefix offsSaveToPathwhile safely handling shorter, equal, or longer destination paths without out-of-bounds access.Additions & Tests Added
Added 3 regression sub-tests to
lib/tests/unittests/HttpFileTest.cc:FileNameWithStrictPrefixTraversal: Sets upload path to.../test_uploads_dir/a/b/c/uploadand filename to../../c. The canonical destination.../test_uploads_dir/a/b/chas fewer components while matching every prefix component. This reproduces the abort on the unpatched codebase under-D_GLIBCXX_ASSERTIONSand safely returns-1with the patch applied.FileNameWithDotDotTraversal: Verifies that single..traversal is safely rejected (return -1).FileNameWithNestedSubdirectory: Verifies that legitimate uploads into nested subdirectories (nested/test_nested_file) continue to succeed (return 0).Verification & Checks
-D_GLIBCXX_ASSERTIONS.-1) without aborting.0)..clang-formatconfiguration (note: rootformat.shenforces clang-format version 17; modified files were verified against.clang-formatwith zero diffs).