-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
builtins.sort
crashes when nix
is build with -D_GLIBCXX_DEBUG
: Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).
#12106
Comments
Shorter reproducer without the need for external files:
|
nix-env
crashes when nix
is build with -D_GLIBCXX_DEBUG
: Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).builtins.sort
crashes when nix
is build with -D_GLIBCXX_DEBUG
: Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).
With the following hack against --- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -3633,6 +3633,24 @@ static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value
return CompareValues(state, noPos, "while evaluating the ordering function passed to builtins.sort")(a, b);
}
+ /* Validate basic ordering requirements for comparator: */
+ {
+ Value * vs[] = {a, a};
+ Value vBool;
+ state.callFunction(*args[0], vs, vBool, noPos);
+ bool br = state.forceBool(vBool, pos, "while evaluating the return value of the sorting function passed to builtins.sort");
+ if (br)
+ state.error<EvalError>("!(a < a) assert failed").atPos(pos).debugThrow();
+ }
+ {
+ Value * vs[] = {b, b};
+ Value vBool;
+ state.callFunction(*args[0], vs, vBool, noPos);
+ bool br = state.forceBool(vBool, pos, "while evaluating the return value of the sorting function passed to builtins.sort");
+ if (br)
+ state.error<EvalError>("!(b < b) assert failed").atPos(pos).debugThrow();
+ }
+
Value * vs[] = {a, b};
Value vBool;
state.callFunction(*args[0], vs, vBool, noPos); I can now see where in
It's an indirect way to point at preferable =
p1: p2: (isSupported p2 -> isSupported p1) && (strings.versionAtLeast p1.version p2.version);
# ...
newest = builtins.head (builtins.sort preferable allReleases); |
Incorrect sorting predicate was found as part of NixOS/nix#12106 where `nix` was crashing on the code like: $ nix eval --expr 'builtins.sort (a: b: true) [ 1 2 3 ]' ... Aborted (core dumped) Note: the crash happens here because sorting predicate does not implement `isLess` and triggers assertion failures for `std::stable_sort` that backs `builtins.sort`. THe change restore `isLess` semantic for `preferable`.
Incorrect sorting predicate was found as part of NixOS/nix#12106 where `nix` was crashing on the code like: $ nix eval --expr 'builtins.sort (a: b: true) [ 1 2 3 ]' ... Aborted (core dumped) Note: the crash happens here because sorting predicate does not implement `lessThan` and triggers assertion failures for `std::stable_sort` that backs `builtins.sort`. The change restores `lessThan` semantic for `version sorting`.
Incorrect sorting predicate was found as part of NixOS/nix#12106 where `nix` was crashing on the code like: $ nix eval --expr 'builtins.sort (a: b: true) [ 1 2 3 ]' ... Aborted (core dumped) Note: the crash happens here because sorting predicate does not implement `lessThan` and triggers assertion failures for `std::stable_sort` that backs `builtins.sort`. The change restores `lessThan` semantic for `version sorting`.
Incorrect sorting predicate was found as part of NixOS/nix#12106 where `nix` was crashing on the code like: $ nix eval --expr 'builtins.sort (a: b: true) [ 1 2 3 ]' ... Aborted (core dumped) Note: the crash happens here because sorting predicate does not implement `lessThan` and triggers assertion failures for `std::stable_sort` that backs `builtins.sort`. The change restores `lessThan` semantic for version sorting.
/cc @fricklerhandwerk if Valentin you are still looking after the documentation bits of |
This seems quite tricky and a reproducibility minefield if we were to try to make it succeed, because it's probably dependent on the standard library sort implementation details. a. Implement our own sort, so that it can do garbage-in garbage-out in a known, deterministic way, regardless of eval platform b. Validate the user-provided function If we only validate the user-provided function for the comparisons that are needed by the STL sort implementation, we will still be dependent on the platform's choice of sort implementation to pick the pairings for which the comparator is tested. This leads errors whose occurrence is non-deterministic. Checking all pairings is not feasible. The error message suggests that we only need to check So I'm leaning towards (a), implement our own sort. What did I miss? |
Describe the bug
In an attempt to reproduce an unrelated I tried to build
nix
with-D_GLIBCXX_DEBUG
. This exposed the invariant violation around the comparator tostable_sort
:Steps To Reproduce
Build
nix
with-D_GLIBCXX_DEBUG
. I did it as:Expected behavior
nix-env
should not crash.Metadata
nix-env (Nix) 2.25.3
Additional context
It looks like the predicate problem is already known at
nix/src/libexpr/primops.cc
Line 3642 in bff9296
The backtrace:
Checklist
Add 👍 to issues you find important.
The text was updated successfully, but these errors were encountered: