Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package uriparser for openSUSE:Factory checked in at 2026-06-17 16:18:36 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/uriparser (Old) and /work/SRC/openSUSE:Factory/.uriparser.new.1981 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "uriparser" Wed Jun 17 16:18:36 2026 rev:16 rq:1359804 version:1.0.2 Changes: -------- --- /work/SRC/openSUSE:Factory/uriparser/uriparser.changes 2026-01-13 21:37:40.975751379 +0100 +++ /work/SRC/openSUSE:Factory/.uriparser.new.1981/uriparser.changes 2026-06-17 16:19:26.901897877 +0200 @@ -1,0 +2,13 @@ +Tue Jun 16 15:22:18 UTC 2026 - Adam Majer <[email protected]> + +- Update to version 1.0.2: + * Fixed: [CVE-2026-44927, bsc#1264578] Stop truncating ptrdiff_t to int + * Fixed: [CVE-2026-44928, bsc#1264579] Fix EqualsUri with regard to .absolutePath + * Fixed: [CVE-2026-42371, bsc#1262999] Protect from integer overflow in text range comparison + * Fixed: Fix OOM related memory leak in CopyUriMm + * Improved: Simplify internal function CompareRange into RangeEquals + * Improved: Make function RangeEquals use size_t internally + +- cmake_fixes.patch: fix compilation with newer GTest + +------------------------------------------------------------------- Old: ---- uriparser-1.0.0.tar.xz New: ---- _scmsync.obsinfo build.specials.obscpio cmake_fixes.patch uriparser-1.0.2.tar.xz ----------(New B)---------- New: - cmake_fixes.patch: fix compilation with newer GTest ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ uriparser.spec ++++++ --- /var/tmp/diff_new_pack.SQYiA2/_old 2026-06-17 16:19:27.653929343 +0200 +++ /var/tmp/diff_new_pack.SQYiA2/_new 2026-06-17 16:19:27.653929343 +0200 @@ -24,13 +24,14 @@ %define so_ver 1 Name: uriparser -Version: 1.0.0 +Version: 1.0.2 Release: 0 Summary: A strictly RFC 3986 compliant URI parsing library License: Apache-2.0 AND BSD-3-Clause AND LGPL-2.1-or-later Group: Development/Libraries/C and C++ URL: https://uriparser.github.io Source: https://github.com/uriparser/uriparser/releases/download/uriparser-%{version}/uriparser-%{version}.tar.xz +Patch1: cmake_fixes.patch Source1: baselibs.conf BuildRequires: cmake BuildRequires: doxygen @@ -95,11 +96,12 @@ This subpackage contains the documentation for %{name}. %prep -%setup -q -n %{name}-%{version} +%autosetup -p1 -n %{name}-%{version} %build %cmake \ -DCMAKE_INSTALL_DOCDIR:PATH=%{_docdir}/%{name} \ + -DCMAKE_CXX_STANDARD=17 \ -DBUILD_SHARED_LIBS:BOOL=ON \ -DURIPARSER_BUILD_CHAR:BOOL=ON \ -DURIPARSER_BUILD_DOCS:BOOL=ON \ ++++++ _scmsync.obsinfo ++++++ mtime: 1781623378 commit: 0f3321c782b254586078a32601447a2f382466e59ae39a55042435eb043f71cc url: https://src.opensuse.org/c_cpp/uriparser revision: main ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-06-16 17:22:58.000000000 +0200 @@ -0,0 +1,4 @@ +*.obscpio +*.osc +_build.* +.pbuild ++++++ cmake_fixes.patch ++++++ Index: uriparser-1.0.2/CMakeLists.txt =================================================================== --- uriparser-1.0.2.orig/CMakeLists.txt +++ uriparser-1.0.2/CMakeLists.txt @@ -93,9 +93,9 @@ if(URIPARSER_BUILD_TESTS OR URIPARSER_BU enable_language(CXX) if(URIPARSER_BUILD_FUZZERS) - set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ Standard to use") else() - set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ Standard to use") endif() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # i.e. -std=c++11 rather than default -std=gnu++11 ++++++ uriparser-1.0.0.tar.xz -> uriparser-1.0.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/.github/workflows/build-and-test.yml new/uriparser-1.0.2/.github/workflows/build-and-test.yml --- old/uriparser-1.0.0/.github/workflows/build-and-test.yml 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/.github/workflows/build-and-test.yml 2026-05-09 19:24:52.000000000 +0200 @@ -34,7 +34,7 @@ -DMINGW=ON runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Add Clang/LLVM repositories (Non-MinGW) if: "${{ ! contains(matrix.cmake_args, 'mingw') }}" @@ -90,8 +90,8 @@ ( cd googletest-release-${GTEST_VERSION}/ - # Silence warning "Compatibility with CMake < 2.8.12 will be removed" - find -name CMakeLists.txt -print -exec sed 's/cmake_minimum_required.*/cmake_minimum_required(VERSION 3.5.0)/' -i {} \; + # Silence warning "Compatibility with CMake < 3.10 will be removed" + find -name CMakeLists.txt -print -exec sed 's/cmake_minimum_required.*/cmake_minimum_required(VERSION 3.10.0)/' -i {} \; cmake \ -DBUILD_SHARED_LIBS=ON \ @@ -117,7 +117,7 @@ -pedantic ) CFLAGS="${compile_flags[*]} -std=c99" - CXXFLAGS="${compile_flags[*]} -std=c++98" + CXXFLAGS="${compile_flags[*]} -std=c++11" LDFLAGS='-g ${{ matrix.ldflags }}' cmake_args=( -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/.github/workflows/clang_format.yml new/uriparser-1.0.2/.github/workflows/clang_format.yml --- old/uriparser-1.0.0/.github/workflows/clang_format.yml 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/.github/workflows/clang_format.yml 2026-05-09 19:24:52.000000000 +0200 @@ -17,7 +17,7 @@ clang_format: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Clang 21 run: |- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/.github/workflows/codespell.yml new/uriparser-1.0.2/.github/workflows/codespell.yml --- old/uriparser-1.0.0/.github/workflows/codespell.yml 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/.github/workflows/codespell.yml 2026-05-09 19:24:52.000000000 +0200 @@ -18,7 +18,7 @@ name: Enforce codespell-clean spelling runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2.2 with: # "inout" is from "<b>INOUT</b>" markers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/.github/workflows/coverage.yml new/uriparser-1.0.2/.github/workflows/coverage.yml --- old/uriparser-1.0.0/.github/workflows/coverage.yml 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/.github/workflows/coverage.yml 2026-05-09 19:24:52.000000000 +0200 @@ -17,7 +17,7 @@ test_coverage: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Clang 21 run: |- @@ -70,7 +70,7 @@ llvm-cov report -instr-profile=coverage/indexed.profraw build/testrunner |& tee coverage/report.txt - name: Store coverage report - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: uriparser_coverage_${{ github.sha }} path: coverage/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/.github/workflows/fuzzing.yml new/uriparser-1.0.2/.github/workflows/fuzzing.yml --- old/uriparser-1.0.0/.github/workflows/fuzzing.yml 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/.github/workflows/fuzzing.yml 2026-05-09 19:24:52.000000000 +0200 @@ -30,7 +30,7 @@ env: fuzzer_name: ${{ matrix.fuzzer_name }} steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Clang 21 run: |- @@ -98,7 +98,7 @@ - name: Store fuzzing logs of last batch if: always() - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: uriparser_fuzzing_logs_last_${{ github.sha }}_${{ matrix.fuzzer_name }} path: build/*/fuzz-*.log diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/.github/workflows/windows.yml new/uriparser-1.0.2/.github/workflows/windows.yml --- old/uriparser-1.0.0/.github/workflows/windows.yml 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/.github/workflows/windows.yml 2026-05-09 19:24:52.000000000 +0200 @@ -21,14 +21,29 @@ matrix: include: # Visual Studio 2022, 32 bit - - runs-on: windows-2025 + - runs-on: windows-2022 cmake_generator: Visual Studio 17 2022 common_cmake_args: -A Win32 + uriparser_sln: uriparser.sln # Visual Studio 2022, 64 bit - - runs-on: windows-2025 + - runs-on: windows-2022 cmake_generator: Visual Studio 17 2022 common_cmake_args: -A x64 + uriparser_sln: uriparser.sln + + # Visual Studio 2026, 32 bit + - runs-on: windows-2025-vs2026 + cmake_generator: Visual Studio 18 2026 + common_cmake_args: -A Win32 + uriparser_sln: uriparser.slnx + + # Visual Studio 2026, 64 bit + - runs-on: windows-2025-vs2026 + cmake_generator: Visual Studio 18 2026 + common_cmake_args: -A x64 + uriparser_sln: uriparser.slnx + runs-on: ${{ matrix.runs-on }} defaults: run: @@ -39,9 +54,9 @@ GTEST_VERSION: 1.12.0 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + - uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3.0.0 - name: Build dependency googletest run: |- @@ -78,6 +93,8 @@ cmake "${cmake_args[@]}" - name: Build + env: + uriparser_sln: ${{ matrix.uriparser_sln }} run: |- msbuild_args=( -m @@ -85,7 +102,7 @@ ) set -x cd build - MSBuild.exe "${msbuild_args[@]}" uriparser.sln + MSBuild.exe "${msbuild_args[@]}" "${uriparser_sln}" - name: Run tests run: |- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/CMakeLists.txt new/uriparser-1.0.2/CMakeLists.txt --- old/uriparser-1.0.0/CMakeLists.txt 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/CMakeLists.txt 2026-05-09 19:24:52.000000000 +0200 @@ -38,7 +38,7 @@ project(uriparser VERSION - 1.0.0 + 1.0.2 LANGUAGES C ) @@ -48,7 +48,7 @@ # See https://verbump.de/ for what these numbers do set(URIPARSER_SO_CURRENT 3) -set(URIPARSER_SO_REVISION 0) +set(URIPARSER_SO_REVISION 2) set(URIPARSER_SO_AGE 2) include(CheckCCompilerFlag) @@ -91,6 +91,14 @@ if(URIPARSER_BUILD_TESTS OR URIPARSER_BUILD_FUZZERS) # We have to call enable_language() before modifying any CMAKE_CXX_* variables enable_language(CXX) + + if(URIPARSER_BUILD_FUZZERS) + set(CMAKE_CXX_STANDARD 17) + else() + set(CMAKE_CXX_STANDARD 11) + endif() + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) # i.e. -std=c++11 rather than default -std=gnu++11 endif() if(URIPARSER_SHARED_LIBS) @@ -306,6 +314,7 @@ find_package(GTest 1.8.0 REQUIRED) add_executable(testrunner + ${CMAKE_CURRENT_SOURCE_DIR}/test/CompareRangeLengthWrap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/copy.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/FourSuite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/MemoryManagerSuite.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/ChangeLog new/uriparser-1.0.2/ChangeLog --- old/uriparser-1.0.0/ChangeLog 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/ChangeLog 2026-05-09 19:24:52.000000000 +0200 @@ -2,6 +2,43 @@ https://github.com/uriparser/uriparser/labels/help%20wanted If you can help, please get in touch. Thanks! +2026-05-09 -- 1.0.2 + +>>>>>>>>>>>>> SECURITY >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * Fixed: [CVE-2026-44927] + Stop truncating `ptrdiff_t` to `int` + Thanks for the report to Ilia Alshanetsky and Joshua W. Windle! + (GitHub #304) + * Fixed: [CVE-2026-44928] + Fix `EqualsUri` with regard to `.absolutePath` + Thanks for the report to Ilia Alshanetsky! (GitHub #305) +>>>>>>>>>>>>> SECURITY >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * Fixed: Fix OOM related memory leak in `CopyUriMm` + Thanks for the report to Ilia Alshanetsky! (GitHub #306) + * Improved: Simplify internal function `CompareRange` into `RangeEquals` + (GitHub #303) + * Improved: Make function `RangeEquals` use size_t` internally + (GitHub #307) + * Soname: 3:2:2 — see https://verbump.de/ for what these numbers do + (liburiparser.so.1.2.2) + +2026-04-27 -- 1.0.1 + +>>>>>>>>>>>>> SECURITY >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * Fixed: [CVE-2026-42371] + Protect from integer overflow in text range comparison. + Thanks for the report and pull request to Joshua W. Windle! (GitHub #298) +>>>>>>>>>>>>> SECURITY >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + * Fixed: Fix `reallocarray` preprocessor handling for Illumos (GitHub #289) + * Improved: Fix an in-code comment typo in src/UriCommon.c; + Thanks for the report and pull request to Tim Düsterhus! (GitHub #290) + * Improved: CMake: Start enforcing supported C++ standard (GitHub #295) + * Improved: Allow use of C++11 to future unit tests (GitHub #296) + * Infrastructure: Cover compilation with Visual Studio 18 2026 (GitHub #301) + * Infrastructure: Address warning on CMake <3.10 in CI (GitHub #297) + * Soname: 3:1:2 — see https://verbump.de/ for what these numbers do + (liburiparser.so.1.2.1) + 2025-12-15 -- 1.0.0 >>>>>>>>>>>>> SECURITY >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/include/uriparser/Uri.h new/uriparser-1.0.2/include/uriparser/Uri.h --- old/uriparser-1.0.0/include/uriparser/Uri.h 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/include/uriparser/Uri.h 2026-05-09 19:24:52.000000000 +0200 @@ -1,4 +1,4 @@ -/* 5abed1007be99942f49ffe603a894d277066b79b9cb824547af0f3b9481cb9ca (1.0.0+) +/* c9d94656d067288e474df19a062d487c736b0fa8517d2ef7bbeb8dcd5a70c05b (1.0.2+) * * uriparser - RFC 3986 URI parsing library * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/include/uriparser/UriBase.h new/uriparser-1.0.2/include/uriparser/UriBase.h --- old/uriparser-1.0.0/include/uriparser/UriBase.h 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/include/uriparser/UriBase.h 2026-05-09 19:24:52.000000000 +0200 @@ -52,7 +52,7 @@ /* Version */ # define URI_VER_MAJOR 1 # define URI_VER_MINOR 0 -# define URI_VER_RELEASE 0 +# define URI_VER_RELEASE 2 # define URI_VER_SUFFIX_ANSI "" # define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriCommon.c new/uriparser-1.0.2/src/UriCommon.c --- old/uriparser-1.0.0/src/UriCommon.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriCommon.c 2026-05-09 19:24:52.000000000 +0200 @@ -66,6 +66,8 @@ # endif # include <assert.h> +# include <stddef.h> +# include <stdint.h> // SIZE_MAX /*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X"); /*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT("."); @@ -104,42 +106,35 @@ } /* Compares two text ranges for equal text content */ -int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) { - int diff; - +bool URI_FUNC(RangeEquals)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) { /* NOTE: Both NULL means equal! */ if ((a == NULL) || (b == NULL)) { - return ((a == NULL) ? 0 : 1) - ((b == NULL) ? 0 : 1); + return a == b; } /* NOTE: Both NULL means equal! */ if ((a->first == NULL) || (b->first == NULL)) { - return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1); - } - - diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first)); - if (diff > 0) { - return 1; - } else if (diff < 0) { - return -1; + return a->first == b->first; } - diff = URI_STRNCMP(a->first, b->first, (a->afterLast - a->first)); + const size_t lenA = a->afterLast - a->first; + const size_t lenB = b->afterLast - b->first; - if (diff > 0) { - return 1; - } else if (diff < 0) { - return -1; + if (lenA != lenB) { + return false; } - return diff; + return URI_STRNCMP(a->first, b->first, lenA) == 0; } UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange, const URI_TYPE(TextRange) * sourceRange, UriMemoryManager * memory) { - const int lenInChars = (int)(sourceRange->afterLast - sourceRange->first); - const int lenInBytes = lenInChars * sizeof(URI_CHAR); + const size_t lenInChars = sourceRange->afterLast - sourceRange->first; + if (lenInChars > SIZE_MAX / sizeof(URI_CHAR)) { // detect integer overflow + return URI_FALSE; + } + const size_t lenInBytes = lenInChars * sizeof(URI_CHAR); URI_CHAR * dup = memory->malloc(memory, lenInBytes); if (dup == NULL) { return URI_FALSE; @@ -178,7 +173,7 @@ walker->reserved = NULL; /* Prev pointer */ do { UriBool removeSegment = URI_FALSE; - int len = (int)(walker->text.afterLast - walker->text.first); + const size_t len = walker->text.afterLast - walker->text.first; switch (len) { case 1: if ((walker->text.first)[0] == _UT('.')) { @@ -727,7 +722,7 @@ } /* When dropping a host from a URI without a scheme, an absolute path - * and and empty first path segment, a consecutive reparse would rightfully + * and empty first path segment, a consecutive reparse would rightfully * mis-classify the first path segment as a host marker due to the "//". * To protect against this case, we prepend an artificial "." segment * to the path in here; the function is called after the host has diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriCommon.h new/uriparser-1.0.2/src/UriCommon.h --- old/uriparser-1.0.0/src/UriCommon.h 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriCommon.h 2026-05-09 19:24:52.000000000 +0200 @@ -67,6 +67,8 @@ # include <uriparser/UriDefsUnicode.h> # endif +# include <stdbool.h> + /* Used to point to from empty path segments. * X.first and X.afterLast must be the same non-NULL value then. */ extern const URI_CHAR * const URI_FUNC(SafeToPointTo); @@ -77,7 +79,7 @@ int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory); -int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b); +bool URI_FUNC(RangeEquals)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b); UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange, const URI_TYPE(TextRange) * sourceRange, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriCompare.c new/uriparser-1.0.2/src/UriCompare.c --- old/uriparser-1.0.0/src/UriCompare.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriCompare.c 2026-05-09 19:24:52.000000000 +0200 @@ -72,17 +72,17 @@ } /* scheme */ - if (URI_FUNC(CompareRange)(&(a->scheme), &(b->scheme))) { + if (!URI_FUNC(RangeEquals)(&(a->scheme), &(b->scheme))) { return URI_FALSE; } - /* absolutePath */ - if ((a->scheme.first == NULL) && (a->absolutePath != b->absolutePath)) { + /* absolutePath -- not meaningful for URIs with a host set! */ + if (!URI_FUNC(HasHost)(a) && (a->absolutePath != b->absolutePath)) { return URI_FALSE; } /* userInfo */ - if (URI_FUNC(CompareRange)(&(a->userInfo), &(b->userInfo))) { + if (!URI_FUNC(RangeEquals)(&(a->userInfo), &(b->userInfo))) { return URI_FALSE; } @@ -107,20 +107,20 @@ } if (a->hostData.ipFuture.first != NULL) { - if (URI_FUNC(CompareRange)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) { + if (!URI_FUNC(RangeEquals)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) { return URI_FALSE; } } if ((a->hostData.ip4 == NULL) && (a->hostData.ip6 == NULL) && (a->hostData.ipFuture.first == NULL)) { - if (URI_FUNC(CompareRange)(&(a->hostText), &(b->hostText))) { + if (!URI_FUNC(RangeEquals)(&(a->hostText), &(b->hostText))) { return URI_FALSE; } } /* portText */ - if (URI_FUNC(CompareRange)(&(a->portText), &(b->portText))) { + if (!URI_FUNC(RangeEquals)(&(a->portText), &(b->portText))) { return URI_FALSE; } @@ -133,7 +133,7 @@ URI_TYPE(PathSegment) * walkA = a->pathHead; URI_TYPE(PathSegment) * walkB = b->pathHead; do { - if (URI_FUNC(CompareRange)(&(walkA->text), &(walkB->text))) { + if (!URI_FUNC(RangeEquals)(&(walkA->text), &(walkB->text))) { return URI_FALSE; } if ((walkA->next == NULL) != (walkB->next == NULL)) { @@ -145,12 +145,12 @@ } /* query */ - if (URI_FUNC(CompareRange)(&(a->query), &(b->query))) { + if (!URI_FUNC(RangeEquals)(&(a->query), &(b->query))) { return URI_FALSE; } /* fragment */ - if (URI_FUNC(CompareRange)(&(a->fragment), &(b->fragment))) { + if (!URI_FUNC(RangeEquals)(&(a->fragment), &(b->fragment))) { return URI_FALSE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriCopy.c new/uriparser-1.0.2/src/UriCopy.c --- old/uriparser-1.0.0/src/UriCopy.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriCopy.c 2026-05-09 19:24:52.000000000 +0200 @@ -199,6 +199,12 @@ if (URI_FUNC(CopyRangeAsNeeded)(&destWalker->text, &sourceWalker->text, memory) == URI_FALSE) { + // Unless wired to `destUri` above, `destWalker` may be hanging + // in the air now + if (destUri->pathHead != destWalker) { + memory->free(memory, destWalker); + } + URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory); return URI_ERROR_MALLOC; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriFile.c new/uriparser-1.0.2/src/UriFile.c --- old/uriparser-1.0.0/src/UriFile.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriFile.c 2026-05-09 19:24:52.000000000 +0200 @@ -63,7 +63,8 @@ # include <uriparser/Uri.h> # endif -# include <stdlib.h> /* for size_t, avoiding stddef.h for older MSVCs */ +# include <stddef.h> // size_t +# include <stdint.h> // SIZE_MAX static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString, @@ -90,6 +91,11 @@ : _UT("file:///"); const size_t prefixLen = URI_STRLEN(prefix); + // Detect and avoid integer overflow + if (prefixLen > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_OUTPUT_TOO_LARGE; + } + /* Copy prefix */ memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR)); output += prefixLen; @@ -103,7 +109,13 @@ if (lastSep + 1 < input) { if (!fromUnix && absolute && (firstSegment == URI_TRUE)) { /* Quick hack to not convert "C:" to "C%3A" */ - const int charsToCopy = (int)(input - (lastSep + 1)); + const size_t charsToCopy = input - (lastSep + 1); + + // Detect and avoid integer overflow + if (charsToCopy > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_OUTPUT_TOO_LARGE; + } + memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR)); output += charsToCopy; } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriMemory.c new/uriparser-1.0.2/src/UriMemory.c --- old/uriparser-1.0.0/src/UriMemory.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriMemory.c 2026-05-09 19:24:52.000000000 +0200 @@ -45,12 +45,25 @@ #include "UriConfig.h" /* for HAVE_REALLOCARRAY */ #ifdef HAVE_REALLOCARRAY -# ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 +// For glibc >=2.29 of 2019-02-01 +# if !defined(_DEFAULT_SOURCE) +# define _DEFAULT_SOURCE 1 # endif -# ifdef __NetBSD__ + +// For NetBSD (stdlib.h revision 1.122 of 2020-05-26) +# if defined(__NetBSD__) && !defined(_OPENBSD_SOURCE) # define _OPENBSD_SOURCE 1 # endif + +// POSIX 2024 (XPG8) for e.g. Illumos/SmartOS +# if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0 < 800) +# undef _XOPEN_SOURCE +# define _XOPEN_SOURCE 800 +# endif +# if !defined(_POSIX_C_SOURCE) || (_POSIX_C_SOURCE - 0 < 202405L) +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 202405L +# endif #endif #include <errno.h> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriNormalize.c new/uriparser-1.0.2/src/UriNormalize.c --- old/uriparser-1.0.0/src/UriNormalize.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriNormalize.c 2026-05-09 19:24:52.000000000 +0200 @@ -73,6 +73,7 @@ # endif # include <assert.h> +# include <stdint.h> // SIZE_MAX static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask, unsigned int * outMask, @@ -254,20 +255,22 @@ static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first, const URI_CHAR ** afterLast, UriMemoryManager * memory) { - int lenInChars; const int lowerUpperDiff = (_UT('a') - _UT('A')); URI_CHAR * buffer; - int i = 0; + size_t i = 0; if ((first == NULL) || (afterLast == NULL) || (*first == NULL) || (*afterLast == NULL)) { return URI_FALSE; } - lenInChars = (int)(*afterLast - *first); + const size_t lenInChars = *afterLast - *first; if (lenInChars == 0) { return URI_TRUE; - } else if (lenInChars < 0) { + } + + // Detect and avoid integer overflow + if (lenInChars > SIZE_MAX / sizeof(URI_CHAR)) { return URI_FALSE; } @@ -295,8 +298,8 @@ const URI_CHAR * outFirst, const URI_CHAR ** outAfterLast) { URI_CHAR * write = (URI_CHAR *)outFirst; - const int lenInChars = (int)(inAfterLast - inFirst); - int i = 0; + const size_t lenInChars = inAfterLast - inFirst; + size_t i = 0; /* All but last two */ for (; i + 2 < lenInChars; i++) { @@ -350,7 +353,6 @@ static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first, const URI_CHAR ** afterLast, UriMemoryManager * memory) { - int lenInChars; URI_CHAR * buffer; /* Death checks */ @@ -360,10 +362,13 @@ } /* Old text length */ - lenInChars = (int)(*afterLast - *first); + const size_t lenInChars = *afterLast - *first; if (lenInChars == 0) { return URI_TRUE; - } else if (lenInChars < 0) { + } + + // Detect and avoid integer overflow + if (lenInChars > SIZE_MAX / sizeof(URI_CHAR)) { return URI_FALSE; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriQuery.c new/uriparser-1.0.2/src/UriQuery.c --- old/uriparser-1.0.0/src/UriQuery.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriQuery.c 2026-05-09 19:24:52.000000000 +0200 @@ -67,6 +67,7 @@ # include <limits.h> # include <stddef.h> /* size_t */ +# include <stdint.h> // SIZE_MAX static int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest, const URI_TYPE(QueryList) * queryList, @@ -254,7 +255,14 @@ if (dest != NULL) { write[0] = _UT('\0'); if (charsWritten != NULL) { - *charsWritten = (int)(write - dest) + 1; /* .. for terminator */ + const size_t lenInChars = write - dest; + + // Detect and avoid integer overflow + if (lenInChars > INT_MAX - 1) { + return URI_ERROR_OUTPUT_TOO_LARGE; + } + + *charsWritten = (int)(lenInChars + 1); /* .. for terminator */ } } @@ -267,8 +275,8 @@ const URI_CHAR * valueAfter, UriBool plusToSpace, UriBreakConversion breakConversion, UriMemoryManager * memory) { - const int keyLen = (int)(keyAfter - keyFirst); - const int valueLen = (int)(valueAfter - valueFirst); + const size_t keyLen = keyAfter - keyFirst; + const size_t valueLen = valueAfter - valueFirst; URI_CHAR * key; URI_CHAR * value; @@ -285,6 +293,13 @@ } (*prevNext)->next = NULL; + // Detect integer overflow + if ((keyLen > SIZE_MAX - 1) || (keyLen + 1 > SIZE_MAX / sizeof(URI_CHAR))) { + memory->free(memory, *prevNext); + *prevNext = NULL; + return URI_FALSE; // Raises malloc error + } + /* Fill key */ key = memory->malloc(memory, (keyLen + 1) * sizeof(URI_CHAR)); if (key == NULL) { @@ -305,6 +320,14 @@ /* Fill value */ if (valueFirst != NULL) { + // Detect integer overflow + if ((valueLen > SIZE_MAX - 1) || (valueLen + 1 > SIZE_MAX / sizeof(URI_CHAR))) { + memory->free(memory, key); + memory->free(memory, *prevNext); + *prevNext = NULL; + return URI_FALSE; // Raises malloc error + } + value = memory->malloc(memory, (valueLen + 1) * sizeof(URI_CHAR)); if (value == NULL) { memory->free(memory, key); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriRecompose.c new/uriparser-1.0.2/src/UriRecompose.c --- old/uriparser-1.0.0/src/UriRecompose.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriRecompose.c 2026-05-09 19:24:52.000000000 +0200 @@ -64,6 +64,9 @@ # include "UriCommon.h" # endif +# include <limits.h> // INT_MAX +# include <stdint.h> // SIZE_MAX + static int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri, int maxChars, int * charsWritten, int * charsRequired); @@ -116,10 +119,19 @@ /* clang-format off */ /* [03/19] append scheme to result; */ /* clang-format on */ - const int charsToWrite = - (int)(uri->scheme.afterLast - uri->scheme.first); + const size_t charsToWrite = uri->scheme.afterLast - uri->scheme.first; if (dest != NULL) { - if (written + charsToWrite <= maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, uri->scheme.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -131,6 +143,11 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - *charsRequired) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += charsToWrite; } /* clang-format off */ @@ -180,10 +197,20 @@ /* clang-format on */ /* UserInfo */ if (uri->userInfo.first != NULL) { - const int charsToWrite = - (int)(uri->userInfo.afterLast - uri->userInfo.first); + const size_t charsToWrite = + uri->userInfo.afterLast - uri->userInfo.first; if (dest != NULL) { - if (written + charsToWrite <= maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, uri->userInfo.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -206,6 +233,13 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if ((charsToWrite > (size_t)INT_MAX - 1) + || (charsToWrite + 1 + > (size_t)INT_MAX - *charsRequired)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += charsToWrite + 1; } } @@ -334,8 +368,8 @@ } } else if (uri->hostData.ipFuture.first != NULL) { /* IPvFuture */ - const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast - - uri->hostData.ipFuture.first); + const size_t charsToWrite = uri->hostData.ipFuture.afterLast + - uri->hostData.ipFuture.first; if (dest != NULL) { if (written + 1 <= maxChars) { memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR)); @@ -348,7 +382,17 @@ return URI_ERROR_TOSTRING_TOO_LONG; } - if (written + charsToWrite <= maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, uri->hostData.ipFuture.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -371,14 +415,31 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if ((charsToWrite > (size_t)INT_MAX - 1 - 1) + || (1 + charsToWrite + 1 + > (size_t)INT_MAX - *charsRequired)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += 1 + charsToWrite + 1; } } else if (uri->hostText.first != NULL) { /* Regname */ - const int charsToWrite = - (int)(uri->hostText.afterLast - uri->hostText.first); + const size_t charsToWrite = + uri->hostText.afterLast - uri->hostText.first; if (dest != NULL) { - if (written + charsToWrite <= maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, uri->hostText.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -390,14 +451,19 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - *charsRequired) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += charsToWrite; } } /* Port */ if (uri->portText.first != NULL) { - const int charsToWrite = - (int)(uri->portText.afterLast - uri->portText.first); + const size_t charsToWrite = + uri->portText.afterLast - uri->portText.first; if (dest != NULL) { /* Leading ':' */ if (written + 1 <= maxChars) { @@ -411,8 +477,18 @@ return URI_ERROR_TOSTRING_TOO_LONG; } + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + /* Port number */ - if (written + charsToWrite <= maxChars) { + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, uri->portText.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -424,6 +500,13 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if ((charsToWrite > (size_t)INT_MAX - 1) + || (1 + charsToWrite + > (size_t)INT_MAX - *charsRequired)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += 1 + charsToWrite; } } @@ -456,10 +539,20 @@ if (uri->pathHead != NULL) { URI_TYPE(PathSegment) * walker = uri->pathHead; do { - const int charsToWrite = - (int)(walker->text.afterLast - walker->text.first); + const size_t charsToWrite = + walker->text.afterLast - walker->text.first; if (dest != NULL) { - if (written + charsToWrite <= maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, walker->text.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -471,6 +564,11 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - *charsRequired) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += charsToWrite; } @@ -520,10 +618,19 @@ /* clang-format off */ /* [13/19] append query to result; */ /* clang-format on */ - const int charsToWrite = - (int)(uri->query.afterLast - uri->query.first); + const size_t charsToWrite = uri->query.afterLast - uri->query.first; if (dest != NULL) { - if (written + charsToWrite <= maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, uri->query.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -535,6 +642,11 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - *charsRequired) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += charsToWrite; } /* clang-format off */ @@ -565,10 +677,20 @@ /* clang-format off */ /* [17/19] append fragment to result; */ /* clang-format on */ - const int charsToWrite = - (int)(uri->fragment.afterLast - uri->fragment.first); + const size_t charsToWrite = + uri->fragment.afterLast - uri->fragment.first; if (dest != NULL) { - if (written + charsToWrite <= maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - written) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + + if (written + charsToWrite <= (size_t)maxChars) { + // Detect and avoid integer overflow + if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + memcpy(dest + written, uri->fragment.first, charsToWrite * sizeof(URI_CHAR)); written += charsToWrite; @@ -580,6 +702,11 @@ return URI_ERROR_TOSTRING_TOO_LONG; } } else { + // Detect and avoid integer overflow + if (charsToWrite > (size_t)INT_MAX - *charsRequired) { + return URI_ERROR_TOSTRING_TOO_LONG; + } + (*charsRequired) += charsToWrite; } /* clang-format off */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriResolve.c new/uriparser-1.0.2/src/UriResolve.c --- old/uriparser-1.0.0/src/UriResolve.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriResolve.c 2026-05-09 19:24:52.000000000 +0200 @@ -183,9 +183,8 @@ if ((options & URI_RESOLVE_IDENTICAL_SCHEME_COMPAT) && (absBase->scheme.first != NULL) && (relSource->scheme.first != NULL) - && (0 - == URI_FUNC(CompareRange)(&(absBase->scheme), - &(relSource->scheme)))) { + && (URI_FUNC(RangeEquals)(&(absBase->scheme), + &(relSource->scheme)))) { /* clang-format off */ /* [00/32] undefine(R.scheme); */ /* clang-format on */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/src/UriShorten.c new/uriparser-1.0.2/src/UriShorten.c --- old/uriparser-1.0.0/src/UriShorten.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/src/UriShorten.c 2026-05-09 19:24:52.000000000 +0200 @@ -111,14 +111,14 @@ /* IPvFuture */ if (first->hostData.ipFuture.first != NULL) { return ((second->hostData.ipFuture.first != NULL) - && !URI_FUNC(CompareRange)(&first->hostData.ipFuture, - &second->hostData.ipFuture)) + && URI_FUNC(RangeEquals)(&first->hostData.ipFuture, + &second->hostData.ipFuture)) ? URI_TRUE : URI_FALSE; } - return !URI_FUNC(CompareRange)(&first->hostText, &second->hostText) ? URI_TRUE - : URI_FALSE; + return URI_FUNC(RangeEquals)(&first->hostText, &second->hostText) ? URI_TRUE + : URI_FALSE; } static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest, @@ -152,7 +152,7 @@ /* clang-format off */ /* [01/50] if (A.scheme != Base.scheme) then */ /* clang-format on */ - if (URI_FUNC(CompareRange)(&absSource->scheme, &absBase->scheme)) { + if (!URI_FUNC(RangeEquals)(&absSource->scheme, &absBase->scheme)) { /* clang-format off */ /* [02/50] T.scheme = A.scheme; */ /* clang-format on */ @@ -255,8 +255,7 @@ /* clang-format on */ while ( (sourceSeg != NULL) && (baseSeg != NULL) - && !URI_FUNC(CompareRange)(&sourceSeg->text, - &baseSeg->text) + && URI_FUNC(RangeEquals)(&sourceSeg->text, &baseSeg->text) && !((sourceSeg->text.first == sourceSeg->text.afterLast) && ((sourceSeg->next == NULL) != (baseSeg->next == NULL)))) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/test/CompareRangeLengthWrap.cpp new/uriparser-1.0.2/test/CompareRangeLengthWrap.cpp --- old/uriparser-1.0.0/test/CompareRangeLengthWrap.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/uriparser-1.0.2/test/CompareRangeLengthWrap.cpp 2026-05-09 19:24:52.000000000 +0200 @@ -0,0 +1,97 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2026, Joshua W. Windle <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <uriparser/Uri.h> +#include <gtest/gtest.h> + +#include <cstdint> +#include <cstring> + +#if !defined(_WIN32) +# include <sys/mman.h> // mmap, mprotect, munmap +# include <unistd.h> // sysconf +#endif + +extern "C" { +bool uriRangeEqualsA(const UriTextRangeA * a, const UriTextRangeA * b); +} + +#if !defined(_WIN32) && (UINTPTR_MAX > UINT32_MAX) +namespace { +static size_t roundUpToPageSize(size_t value, size_t pageSize) { + const size_t remainder = value % pageSize; + if (remainder == 0U) { + return value; + } + + const size_t padding = pageSize - remainder; + EXPECT_LE(padding, SIZE_MAX - value); + return value + padding; +} + +static size_t queryPageSize() { + const long pageSize = sysconf(_SC_PAGESIZE); + EXPECT_GT(pageSize, 0); + return static_cast<size_t>(pageSize); +} +} // namespace + +TEST(UriSuite, TestRangeComparisonDoesNotWrapLengthChecksOn64Bit) { + const size_t hugeLen = (static_cast<size_t>(1) << 32) + 10U; + const size_t shortLen = 10U; + const size_t pageSize = queryPageSize(); + const size_t hugeMapLen = roundUpToPageSize(hugeLen, pageSize); + const size_t shortMapLen = pageSize * 2U; + + // Reserve a huge virtual range, with access disabled by default. + char * const hugeBase = static_cast<char *>( + mmap(NULL, hugeMapLen, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); + ASSERT_NE(hugeBase, MAP_FAILED); + // Allow access to the first page (and that only). + ASSERT_EQ(0, mprotect(hugeBase, pageSize, PROT_READ | PROT_WRITE)); + // Fill the readable prefix so the vulnerable implementation reaches + // content comparison after truncating the large length. + memset(hugeBase, 'a', pageSize); + + char * const shortBase = static_cast<char *>(mmap( + NULL, shortMapLen, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); + ASSERT_NE(shortBase, MAP_FAILED); + // Guard the following page so any over-read beyond shortLen faults. + ASSERT_EQ(0, mprotect(shortBase + pageSize, pageSize, PROT_NONE)); + + char * const shortStart = shortBase + pageSize - shortLen; + memset(shortStart, 'a', shortLen); + + UriTextRangeA hugeRange; + hugeRange.first = hugeBase; + hugeRange.afterLast = hugeBase + hugeLen; + + UriTextRangeA shortRange; + shortRange.first = shortStart; + shortRange.afterLast = shortStart + shortLen; + + const bool comparison = uriRangeEqualsA(&hugeRange, &shortRange); + + EXPECT_EQ(false, comparison); + + EXPECT_EQ(0, munmap(hugeBase, hugeMapLen)); + EXPECT_EQ(0, munmap(shortBase, shortMapLen)); +} +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/test/VersionSuite.cpp new/uriparser-1.0.2/test/VersionSuite.cpp --- old/uriparser-1.0.0/test/VersionSuite.cpp 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/test/VersionSuite.cpp 2026-05-09 19:24:52.000000000 +0200 @@ -36,6 +36,6 @@ TEST(VersionSuite, EnsureRuntimeVersionAsExpected) { // NOTE: This needs a bump for every release - EXPECT_STREQ(uriBaseRuntimeVersionA(), "1.0.0"); - EXPECT_STREQ(uriBaseRuntimeVersionW(), L"1.0.0"); + EXPECT_STREQ(uriBaseRuntimeVersionA(), "1.0.2"); + EXPECT_STREQ(uriBaseRuntimeVersionW(), L"1.0.2"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/test/test.cpp new/uriparser-1.0.2/test/test.cpp --- old/uriparser-1.0.0/test/test.cpp 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/test/test.cpp 2026-05-09 19:24:52.000000000 +0200 @@ -32,7 +32,7 @@ extern "C" { UriBool uri_TESTING_ONLY_ParseIpSixA(const char * text); UriBool uri_TESTING_ONLY_ParseIpFourA(const char * text); -int uriCompareRangeA(const UriTextRangeA * a, const UriTextRangeA * b); +bool uriRangeEqualsA(const UriTextRangeA * a, const UriTextRangeA * b); } #define URI_TEST_IP_FOUR_FAIL(x) ASSERT_EQ(URI_FALSE, uri_TESTING_ONLY_ParseIpFourA(x)) @@ -2106,6 +2106,76 @@ testEqualsHelper("//host:123"); } +TEST(UriSuite, TestEqualsAbsolutePathWithSchemeWithHost) { + UriUriA uriAbsPathTrue; + UriUriA uriAbsPathFalse; + + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathTrue, "scheme://host/path1", NULL), + URI_SUCCESS); + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathFalse, "scheme://host/path1", NULL), + URI_SUCCESS); + uriAbsPathTrue.absolutePath = URI_TRUE; // i.e. produce artificially + + EXPECT_EQ(uriAbsPathTrue.absolutePath, URI_TRUE); // self-test + EXPECT_EQ(uriAbsPathFalse.absolutePath, URI_FALSE); // self-test + + // NOTE: .absolutePath is ignored for URIs with hosts! + EXPECT_EQ(uriEqualsUriA(&uriAbsPathFalse, &uriAbsPathTrue), URI_TRUE); + + uriFreeUriMembersA(&uriAbsPathTrue); + uriFreeUriMembersA(&uriAbsPathFalse); +} + +TEST(UriSuite, TestEqualsAbsolutePathWithSchemeWithoutHost) { + UriUriA uriAbsPathTrue; + UriUriA uriAbsPathFalse; + + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathTrue, "scheme:/path1", NULL), URI_SUCCESS); + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathFalse, "scheme:path1", NULL), URI_SUCCESS); + + EXPECT_EQ(uriAbsPathTrue.absolutePath, URI_TRUE); // self-test + EXPECT_EQ(uriAbsPathFalse.absolutePath, URI_FALSE); // self-test + + EXPECT_EQ(uriEqualsUriA(&uriAbsPathFalse, &uriAbsPathTrue), URI_FALSE); + + uriFreeUriMembersA(&uriAbsPathTrue); + uriFreeUriMembersA(&uriAbsPathFalse); +} + +TEST(UriSuite, TestEqualsAbsolutePathWithoutSchemeWithHost) { + UriUriA uriAbsPathTrue; + UriUriA uriAbsPathFalse; + + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathTrue, "//host/path1", NULL), URI_SUCCESS); + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathFalse, "//host/path1", NULL), URI_SUCCESS); + uriAbsPathTrue.absolutePath = URI_TRUE; // i.e. produce artificially + + EXPECT_EQ(uriAbsPathTrue.absolutePath, URI_TRUE); // self-test + EXPECT_EQ(uriAbsPathFalse.absolutePath, URI_FALSE); // self-test + + // NOTE: .absolutePath is ignored for URIs with hosts! + EXPECT_EQ(uriEqualsUriA(&uriAbsPathFalse, &uriAbsPathTrue), URI_TRUE); + + uriFreeUriMembersA(&uriAbsPathTrue); + uriFreeUriMembersA(&uriAbsPathFalse); +} + +TEST(UriSuite, TestEqualsAbsolutePathWithoutSchemeWithoutHost) { + UriUriA uriAbsPathTrue; + UriUriA uriAbsPathFalse; + + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathTrue, "/path1", NULL), URI_SUCCESS); + ASSERT_EQ(uriParseSingleUriA(&uriAbsPathFalse, "path1", NULL), URI_SUCCESS); + + EXPECT_EQ(uriAbsPathTrue.absolutePath, URI_TRUE); // self-test + EXPECT_EQ(uriAbsPathFalse.absolutePath, URI_FALSE); // self-test + + EXPECT_EQ(uriEqualsUriA(&uriAbsPathFalse, &uriAbsPathTrue), URI_FALSE); + + uriFreeUriMembersA(&uriAbsPathTrue); + uriFreeUriMembersA(&uriAbsPathFalse); +} + TEST(UriSuite, TestHostTextTerminationIssue15) { UriParserStateA state; UriUriA uri; @@ -2167,8 +2237,8 @@ } namespace { -void testCompareRangeHelper(const char * a, const char * b, int expected, - bool avoidNullRange = true) { +void testRangeEqualsHelper(const char * a, const char * b, bool expected, + bool avoidNullRange = true) { UriTextRangeA ra; UriTextRangeA rb; @@ -2188,40 +2258,40 @@ rb.afterLast = NULL; } - const int received = uriCompareRangeA(((a == NULL) && avoidNullRange) ? NULL : &ra, + const bool received = uriRangeEqualsA(((a == NULL) && avoidNullRange) ? NULL : &ra, ((b == NULL) && avoidNullRange) ? NULL : &rb); if (received != expected) { - printf("Comparing <%s> to <%s> yields %d, expected %d.\n", a, b, received, - expected); + printf("Comparing <%s> to <%s> yields %d, expected %d.\n", a, b, (int)received, + (int)expected); } ASSERT_EQ(received, expected); } } // namespace TEST(UriSuite, TestRangeComparison) { - testCompareRangeHelper("", "", 0); - testCompareRangeHelper("a", "", 1); - testCompareRangeHelper("", "a", -1); - - testCompareRangeHelper("a", "a", 0); - testCompareRangeHelper("a", "b", -1); - testCompareRangeHelper("b", "a", 1); + testRangeEqualsHelper("", "", true); + testRangeEqualsHelper("a", "", false); + testRangeEqualsHelper("", "a", false); + + testRangeEqualsHelper("a", "a", true); + testRangeEqualsHelper("a", "b", false); + testRangeEqualsHelper("b", "a", false); - testCompareRangeHelper("a", "aa", -1); - testCompareRangeHelper("aa", "a", 1); + testRangeEqualsHelper("a", "aa", false); + testRangeEqualsHelper("aa", "a", false); // Fixed with 0.8.1: - testCompareRangeHelper(NULL, "a", -1); - testCompareRangeHelper("a", NULL, 1); - testCompareRangeHelper(NULL, NULL, 0); + testRangeEqualsHelper(NULL, "a", false); + testRangeEqualsHelper("a", NULL, false); + testRangeEqualsHelper(NULL, NULL, true); // Fixed with 0.8.3 const bool KEEP_NULL_RANGE = false; const bool AVOID_NULL_RANGE = true; - testCompareRangeHelper(NULL, "", -1, AVOID_NULL_RANGE); - testCompareRangeHelper(NULL, "", -1, KEEP_NULL_RANGE); - testCompareRangeHelper("", NULL, 1, AVOID_NULL_RANGE); - testCompareRangeHelper("", NULL, 1, KEEP_NULL_RANGE); + testRangeEqualsHelper(NULL, "", false, AVOID_NULL_RANGE); + testRangeEqualsHelper(NULL, "", false, KEEP_NULL_RANGE); + testRangeEqualsHelper("", NULL, false, AVOID_NULL_RANGE); + testRangeEqualsHelper("", NULL, false, KEEP_NULL_RANGE); } namespace { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/uriparser-1.0.0/tool/uriparse.c new/uriparser-1.0.2/tool/uriparse.c --- old/uriparser-1.0.0/tool/uriparse.c 2025-12-15 19:50:12.000000000 +0100 +++ new/uriparser-1.0.2/tool/uriparse.c 2026-05-09 19:24:52.000000000 +0200 @@ -36,6 +36,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <uriparser/Uri.h> @@ -55,12 +56,28 @@ # include <netinet/in.h> #endif -#define RANGE(x) (int)((x).afterLast - (x).first), ((x).first) - void usage(void) { printf("Usage: uriparse URI [..]\n"); } +void dumpRange(const char * label, const UriTextRangeA * range) { + assert(label != NULL); + assert(range != NULL); + assert(range->first != NULL); + + const int leftColumnMinWidthChars = 14; + const size_t labelLenChars = strlen(label); + + const int gapLenChars = + (leftColumnMinWidthChars - /* the colon */ 1 > labelLenChars) + ? (int)(leftColumnMinWidthChars - labelLenChars - /* the colon */ 1) + : /* minimum gap */ 1; + + fprintf(stdout, "%s:%*s", label, gapLenChars, ""); + fwrite(range->first, range->afterLast - range->first, 1, stdout); + fputc('\n', stdout); +} + int main(int argc, char * argv[]) { int retval = EXIT_SUCCESS; int i = 1; @@ -88,13 +105,13 @@ retval = EXIT_FAILURE; } else { if (uri.scheme.first) { - printf("scheme: %.*s\n", RANGE(uri.scheme)); + dumpRange("scheme", &(uri.scheme)); } if (uri.userInfo.first) { - printf("userInfo: %.*s\n", RANGE(uri.userInfo)); + dumpRange("userInfo", &(uri.userInfo)); } if (uri.hostText.first) { - printf("hostText: %.*s\n", RANGE(uri.hostText)); + dumpRange("hostText", &(uri.hostText)); } if (uri.hostData.ip4) { inet_ntop(AF_INET, uri.hostData.ip4->data, ipstr, sizeof ipstr); @@ -105,22 +122,22 @@ printf("hostData.ip6: %s\n", ipstr); } if (uri.hostData.ipFuture.first) { - printf("hostData.ipFuture: %.*s\n", RANGE(uri.hostData.ipFuture)); + dumpRange("hostData.ipFuture", &(uri.hostData.ipFuture)); } if (uri.portText.first) { - printf("portText: %.*s\n", RANGE(uri.portText)); + dumpRange("portText", &(uri.portText)); } if (uri.pathHead) { const UriPathSegmentA * p = uri.pathHead; for (; p; p = p->next) { - printf(" .. pathSeg: %.*s\n", RANGE(p->text)); + dumpRange(" .. pathSeg", &(p->text)); } } if (uri.query.first) { - printf("query: %.*s\n", RANGE(uri.query)); + dumpRange("query", &(uri.query)); } if (uri.fragment.first) { - printf("fragment: %.*s\n", RANGE(uri.fragment)); + dumpRange("fragment", &(uri.fragment)); } const char * const absolutePathLabel = "absolutePath: "; printf("%s%s\n", absolutePathLabel,
