From a32cd16f640a2eeee2c5cd46557004d94ee5bd51 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Sun, 15 Feb 2026 11:20:57 -0500 Subject: [PATCH] libflake: fix assertion crash when malformed URL falls through to path scheme When a URL like `github:nixos/nixpkgs/nixpkgs.git?ref=` (using `ref` instead of `rev`) failed the github input scheme, it fell through to `parsePathFlakeRefWithFragment` which constructed a `path:` `ParsedURL` with an empty authority but a relative path. This violated RFC 3986 section 3.3 (authority present requires path starting with `/`), causing an assertion failure in `renderAuthorityAndPath` when `PathInputScheme` tried to format the URL for an error message. This commit only sets the authority on absolute paths. Relative paths get `std::nullopt` for authority, which is the correct representation per the URL spec. Fixes #15196. Fixes #14830. --- src/libflake-tests/flakeref.cc | 14 ++++++++++++++ src/libflake/flakeref.cc | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libflake-tests/flakeref.cc b/src/libflake-tests/flakeref.cc index eb8b56ea2..5fcbbc9c3 100644 --- a/src/libflake-tests/flakeref.cc +++ b/src/libflake-tests/flakeref.cc @@ -283,4 +283,18 @@ TEST(to_string, doesntReencodeUrl) ASSERT_EQ(unparsed, expected); } +TEST(parseFlakeRef, malformedGithubUrlDoesNotCrash) +{ + experimentalFeatureSettings.experimentalFeatures.get().insert(Xp::Flakes); + + fetchers::Settings fetchSettings; + + // Using ref= instead of rev= with a github: URL should produce an + // error, not an assertion failure in renderAuthorityAndPath + // (https://github.com/NixOS/nix/issues/15196). + EXPECT_THROW( + parseFlakeRef(fetchSettings, "github:nixos/nixpkgs/nixpkgs.git?ref=aead170c1a49253ebfa5027010dfd89a77b73ca4"), + Error); +} + } // namespace nix diff --git a/src/libflake/flakeref.cc b/src/libflake/flakeref.cc index 0a55ac35c..f3bfb9527 100644 --- a/src/libflake/flakeref.cc +++ b/src/libflake/flakeref.cc @@ -205,7 +205,7 @@ std::pair parsePathFlakeRefWithFragment( fetchSettings, { .scheme = "path", - .authority = ParsedURL::Authority{}, + .authority = isAbsolute(path) ? std::optional{ParsedURL::Authority{}} : std::nullopt, .path = splitString>(path, "/"), .query = query, .fragment = fragment,