On 02/05/2022 07:03, Paul Eggert wrote:
Thanks for the bug report. This bug is entertaining, as it comes from
GCC now being so smart that it optimizes away a memset that cleared
padding bits. We added the memset in coreutils 8.14 (2011) to try to fix
the sort -g infinite loop bug (introduced in 1999), but the memset isn't
guaranteed to fix the bug because the memset can be optimized away.

If the padding bits happen to be clear already sort is OK, but if not
the results can be inconsistent when you compare two NaNs to each other,
and inconsistent results can make sort infloop.

The C standard allows this level of intelligence in the compiler, so
it's a bug in GNU 'sort'.

I installed the attached patch; please give it a try. For now I'll
boldly close the bug report; we can easily reopen it if this patch
doesn't actually fix the problem.

This is a bit slower of course, but since an edge case not a big concern:

  $ time yes nan | head -n128095 | timeout 10 sort -g >/dev/null
  real  0m0.693s

  $ time yes nan | head -n128095 | timeout 10 src/sort -g >/dev/null
  real  0m0.924s

I'll add the test case I think (attached)
since the existing one didn't trigger this.

thanks!
Pádraig
From bf12c9128523631d7f0ec251734fa05405f70c1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com>
Date: Mon, 2 May 2022 14:27:34 +0100
Subject: [PATCH] tests: sort-NaN-infloop: augment testing for recent fix

* tests/misc/sort-NaN-infloop.sh: Add test case from
https://unix.stackexchange.com/a/700967/37127
* src/sort.c: Avoid syntax-check failure.
---
 src/sort.c                     | 2 +-
 tests/misc/sort-NaN-infloop.sh | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/sort.c b/src/sort.c
index b2a465cf5..8af356c66 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -2006,7 +2006,7 @@ numcompare (char const *a, char const *b)
 static int
 nan_compare (long double a, long double b)
 {
-  char buf[2][sizeof "-nan()" + CHAR_BIT * sizeof a];
+  char buf[2][sizeof "-nan""()" + CHAR_BIT * sizeof a];
   snprintf (buf[0], sizeof buf[0], "%Lf", a);
   snprintf (buf[1], sizeof buf[1], "%Lf", b);
   return strcmp (buf[0], buf[1]);
diff --git a/tests/misc/sort-NaN-infloop.sh b/tests/misc/sort-NaN-infloop.sh
index 93cf9bd77..3e459884e 100755
--- a/tests/misc/sort-NaN-infloop.sh
+++ b/tests/misc/sort-NaN-infloop.sh
@@ -23,6 +23,9 @@ echo nan > F || framework_failure_
 printf 'nan\nnan\n' > exp || framework_failure_
 timeout 10 sort -g -m F F > out || fail=1
 
+# This was seen to infloop on some systems until coreutils v9.2 (bug 55212)
+yes nan | head -n128095 | timeout 10 sort -g > /dev/null || fail=1
+
 compare exp out || fail=1
 
 Exit $fail
-- 
2.26.2

Reply via email to