Skip to content

Commit a7cdb55

Browse files
authored
Merge pull request NixOS#12013 from DeterminateSystems/fix-11996
nix hash convert: Support SRI hashes that lack trailing '=' characters
2 parents 49fa31f + 408c2fa commit a7cdb55

File tree

3 files changed

+30
-14
lines changed

3 files changed

+30
-14
lines changed

src/libutil/hash.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ std::string Hash::to_string(HashFormat hashFormat, bool includeAlgo) const
134134

135135
Hash Hash::dummy(HashAlgorithm::SHA256);
136136

137-
Hash Hash::parseSRI(std::string_view original) {
137+
Hash Hash::parseSRI(std::string_view original)
138+
{
138139
auto rest = original;
139140

140141
// Parse the has type before the separater, if there was one.

src/nix/hash.cc

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,11 @@ struct CmdToBase : Command
163163
HashFormat hashFormat;
164164
std::optional<HashAlgorithm> hashAlgo;
165165
std::vector<std::string> args;
166+
bool legacyCli;
166167

167-
CmdToBase(HashFormat hashFormat) : hashFormat(hashFormat)
168+
CmdToBase(HashFormat hashFormat, bool legacyCli = false)
169+
: hashFormat(hashFormat)
170+
, legacyCli(legacyCli)
168171
{
169172
addFlag(flag::hashAlgoOpt("type", &hashAlgo));
170173
expectArgs("strings", &args);
@@ -181,7 +184,8 @@ struct CmdToBase : Command
181184

182185
void run() override
183186
{
184-
warn("The old format conversion sub commands of `nix hash` were deprecated in favor of `nix hash convert`.");
187+
if (!legacyCli)
188+
warn("The old format conversion subcommands of `nix hash` were deprecated in favor of `nix hash convert`.");
185189
for (const auto & s : args)
186190
logger->cout(Hash::parseAny(s, hashAlgo).to_string(hashFormat, hashFormat == HashFormat::SRI));
187191
}
@@ -222,11 +226,18 @@ struct CmdHashConvert : Command
222226
Category category() override { return catUtility; }
223227

224228
void run() override {
225-
for (const auto& s: hashStrings) {
226-
Hash h = Hash::parseAny(s, algo);
227-
if (from && h.to_string(*from, from == HashFormat::SRI) != s) {
229+
for (const auto & s : hashStrings) {
230+
Hash h =
231+
from == HashFormat::SRI
232+
? Hash::parseSRI(s)
233+
: Hash::parseAny(s, algo);
234+
if (from
235+
&& from != HashFormat::SRI
236+
&& h.to_string(*from, false) !=
237+
(from == HashFormat::Base16 ? toLower(s) : s))
238+
{
228239
auto from_as_string = printHashFormat(*from);
229-
throw BadHash("input hash '%s' does not have the expected format '--from %s'", s, from_as_string);
240+
throw BadHash("input hash '%s' does not have the expected format for '--from %s'", s, from_as_string);
230241
}
231242
logger->cout(h.to_string(to, to == HashFormat::SRI));
232243
}
@@ -321,7 +332,7 @@ static int compatNixHash(int argc, char * * argv)
321332
}
322333

323334
else {
324-
CmdToBase cmd(hashFormat);
335+
CmdToBase cmd(hashFormat, true);
325336
cmd.args = ss;
326337
if (hashAlgo.has_value()) cmd.hashAlgo = hashAlgo;
327338
cmd.run();

tests/functional/hash-convert.sh

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,19 @@ try3() {
9393
# Asserting input format fails.
9494
#
9595

96-
fail=$(nix hash convert --hash-algo "$1" --from nix32 "$2" 2>&1 || echo "exit: $?")
97-
[[ "$fail" == *"error: input hash"*"exit: 1" ]]
98-
fail=$(nix hash convert --hash-algo "$1" --from base16 "$3" 2>&1 || echo "exit: $?")
99-
[[ "$fail" == *"error: input hash"*"exit: 1" ]]
100-
fail=$(nix hash convert --hash-algo "$1" --from nix32 "$4" 2>&1 || echo "exit: $?")
101-
[[ "$fail" == *"error: input hash"*"exit: 1" ]]
96+
expectStderr 1 nix hash convert --hash-algo "$1" --from sri "$2" | grepQuiet "is not SRI"
97+
expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$2" | grepQuiet "input hash"
98+
expectStderr 1 nix hash convert --hash-algo "$1" --from base16 "$3" | grepQuiet "input hash"
99+
expectStderr 1 nix hash convert --hash-algo "$1" --from nix32 "$4" | grepQuiet "input hash"
102100

101+
# Base-16 hashes can be in uppercase.
102+
nix hash convert --hash-algo "$1" --from base16 "$(echo $2 | tr [a-z] [A-Z])"
103103
}
104104

105105
try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8="
106106
try3 sha256 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="
107107
try3 sha512 "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" "12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0" "IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ=="
108+
109+
# Test SRI hashes that lack trailing '=' characters. These are incorrect but we need to support them for backward compatibility.
110+
[[ $(nix hash convert --from sri "sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0") = sha256-ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0= ]]
111+
[[ $(nix hash convert --from sri "sha512-IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ") = sha512-IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ== ]]

0 commit comments

Comments
 (0)