]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
pr: guard input position update against overflow
authorGuanqiang Han <hanguanqiang@kylinos.cn>
Tue, 7 Jul 2026 14:58:43 +0000 (22:58 +0800)
committerPádraig Brady <P@draigBrady.com>
Fri, 10 Jul 2026 21:19:46 +0000 (22:19 +0100)
* src/pr.c (char_to_clump): Use ckd_add() and report integer overflow.
* tests/pr/options.sh: Add a test case.
* NEWS: Mention the bug fix.
Fixes https://bugs.gnu.org/81393

NEWS
src/pr.c
tests/pr/options.sh

diff --git a/NEWS b/NEWS
index 0e3d9bd5f9196ee8f1f17d5736668287b706ddfa..191d2ec63c797e9a5163a09d03158a9de0abddf8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   standard output is fully buffered, e.g., when redirected to a file.
   [bug introduced in coreutils-9.10]
 
+  'pr' now exits gracefully upon exceeding internal accounting limits,
+  like when processing large tab stops.
+  [This bug was present in "the beginning".]
+
   'shred' no longer blocks when opening a FIFO that has no readers.
   [This bug was present in "the beginning".]
 
index 09a1b94a8c74db831f8514d61f83590f020b7987..c3e085bcd5076eeb6fc209cbc9d9ae918280513c 100644 (file)
--- a/src/pr.c
+++ b/src/pr.c
@@ -2732,7 +2732,10 @@ char_to_clump (char c)
   else if (width < 0 && input_position <= -width)
     input_position = 0;
   else
-    input_position += width;
+    {
+      if (ckd_add (&input_position, input_position, width))
+        integer_overflow ();
+    }
 
   return chars;
 }
index feaf49f1959dda9f864fa55d97cac313d61f30fb..2324eb57e262c5ef3bb9d26212f67b05e857ca08 100755 (executable)
@@ -57,4 +57,15 @@ printf '%s\n' "pr: '-e' extra characters or $INV in the argument: '-1'" \
  >exp || framework_failure_
 compare exp err || fail=1
 
+# Ensure we exit gracefully upon internal overflow limits
+# Tag as expensive as it uses little mem, but about 10s on a 2020 class machine.
+if { test "$RUN_VERY_EXPENSIVE_TESTS" = yes ||
+     test "$RUN_EXPENSIVE_TESTS" = yes; } &&
+   test "$INT_MAX" = 2147483647; then  # restrict to usual 32 bit limits
+  head -c1M /dev/zero | tr '\0' '\t' |
+  returns_ 1 pr -t -e$(($INT_MAX/(1024*1024) + 1)) 2>err >/dev/null || fail=1
+  printf '%s\n' "pr: integer overflow" > exp || framework_failure_
+  compare exp err || fail=1
+fi
+
 Exit $fail