sort: fix bug in --debug when \0 is followed by \t
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 3 Aug 2010 17:24:11 +0000 (10:24 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 3 Aug 2010 17:25:47 +0000 (10:25 -0700)
* src/sort.c (debug_width): New function, which does not stop
counting tabs at \0, and also invokes mbsnwidth.  Stamp out strnlen!
(count_tabs): Remove.
(debug_key): Use debug_width instead of mbsnwidth and count_tabs.
* tests/misc/sort-debug-keys: Check that \0 and \t intermix.

src/sort.c
tests/misc/sort-debug-keys

index e02e547..1df711d 100644 (file)
@@ -2102,23 +2102,17 @@ compare_version (char *restrict texta, size_t lena,
   return diff;
 }
 
-/* For debug mode, count tabs in the passed string
-   so we can adjust the widths returned by mbswidth.
+/* Return the printable width of the block of memory starting at
+   TEXT and ending just before LIM, counting each tab as one byte.
    FIXME: Should we generally be counting non printable chars?  */
 
 static size_t
-count_tabs (char const *text, size_t len)
+debug_width (char const *text, char const *lim)
 {
-  size_t tabs = 0;
-  size_t tlen = strnlen (text, len);
-
-  while (tlen--)
-    {
-      if (*text++ == '\t')
-        tabs++;
-    }
-
-  return tabs;
+  size_t width = mbsnwidth (text, lim - text, 0);
+  while (text < lim)
+    width += (*text++ == '\t');
+  return width;
 }
 
 /* For debug mode, "underline" a key at the
@@ -2161,12 +2155,8 @@ debug_key (char const *sline, char const *sfield, char const *efield,
         }
     }
 
-  size_t offset = mbsnwidth (sline, sfield - sline, 0) + (sa - sfield);
-  offset += count_tabs (sline, sfield - sline);
-
-  size_t width = mbsnwidth (sa, flen, 0);
-  width += count_tabs (sa, flen);
-
+  size_t offset = debug_width (sline, sfield) + (sa - sfield);
+  size_t width = debug_width (sa, sa + flen);
   mark_key (offset, width);
 }
 
index 36b67d2..54bac57 100755 (executable)
@@ -236,6 +236,8 @@ ___
 _
 2b
 _
+>a
+ _
 EOF
 
 (
@@ -274,6 +276,9 @@ printf "2,,3\n2.4\n" | sort -s -k1n --debug
 
 # -z means we convert \0 to \n
 printf "1a\x002b\x00" | sort -s -n -z --debug
+
+# Check that \0 and \t intermix.
+printf "\0\ta\n" | sort -s -k2b,2 --debug | tr -d '\0'
 ) > out
 
 compare out exp || fail=1