With GNU extensions disabled, before_max_width can go negative, and
define_all_fields then loops forever trying to shrink the before field
to a width narrower than empty:

  $ printf 'qux\n' | src/ptx -G -w2
  [hangs]

Commit v6.12-96-g773be9eca added a clamp for this, but placed it in
the GNU-extensions branch only.  Move it after that if/else so that
both branches are covered.

* src/ptx.c (fix_output_parameters): Clamp before_max_width for both
the GNU and non-GNU cases.
* tests/ptx/ptx.pl: Add a test case.
* NEWS: Mention the bug fix.
---

Hi,

While working on a research project, I discovered a bug in the ptx
command that caused it to loop forever and hog my CPU. This essentially
happens when GNU extensions are disabled. When the output width is
narrow, the maximum width of the before field can become negative, and
define_all_fields then loops forever trying to shrink the before field.
I have attached a minimal reproducer below, but there are various
scenarios where this can occur, essentially any time GNU extensions are
disabled and the output width is narrow. It depends on the specific
values of the gap size and the output width, as well as reference
lengths if that flag is used. I have attached a patch for this as well,
including a test case.

  $ printf 'qux\n' | ptx -G -w2
  [hangs]

Commit v6.12-96-g773be9eca added a clamp for this, but placed it in the
GNU-extensions branch only. I think it should be placed after that
if/else so that both branches are covered.

This is my first patch to coreutils so apologies for any mistakes I
might have made. I'm happy to fix anything you point out.

Thanks!
Aysha

 NEWS             | 5 +++++
 src/ptx.c        | 5 +++--
 tests/ptx/ptx.pl | 4 ++++
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index fd0902cb7..28d1da64d 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,11 @@ GNU coreutils NEWS                                    -*- 
outline -*-
   like when processing large tab stops.
   [This bug was present in "the beginning".]
 
+  'ptx -G' no longer hangs when the output width is smaller than twice the
+  gap size, as with 'ptx -G -w4', or when a long reference leaves that
+  little room, as with 'ptx -G -r'.
+  [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".]
 
diff --git a/src/ptx.c b/src/ptx.c
index 8c7d1535a..6ef19ee15 100644
--- a/src/ptx.c
+++ b/src/ptx.c
@@ -1145,8 +1145,6 @@ fix_output_parameters (void)
          right side, or one on either side.  */
 
       before_max_width -= 2 * truncation_string_length;
-      if (before_max_width < 0)
-        before_max_width = 0;
       keyafter_max_width -= 2 * truncation_string_length;
     }
   else
@@ -1161,6 +1159,9 @@ fix_output_parameters (void)
       keyafter_max_width -= 2 * truncation_string_length + 1;
     }
 
+  if (before_max_width < 0)
+    before_max_width = 0;
+
   /* Compute which characters need special output processing.  Initialize
      by flagging any white space character.  Some systems do not consider
      form feed as a space character, but we do.  */
diff --git a/tests/ptx/ptx.pl b/tests/ptx/ptx.pl
index 625a6c6bf..b2c5d880d 100755
--- a/tests/ptx/ptx.pl
+++ b/tests/ptx/ptx.pl
@@ -38,6 +38,10 @@ my @Tests =
 ["narrow", '-w2', {IN=>"qux\n"},    {OUT=>"      qux\n"}],
 ["narrow-g", '-g1 -w2', {IN=>"ta\n"}, {OUT=>"  ta\n"}],
 
+# with coreutils-9.11 and earlier, this would infloop with -G whenever
+# (width >> 1) < gap size.
+["narrow-trad", '-G -w2', {IN=>"qux\n"}, {OUT=>".xx \"\" \"\" \"qux\" 
\"\"\n"}],
+
 # with coreutils-6.12 and earlier, this would act like "ptx F1 F1"
 ["2files", '-g1 -w1', {IN=>{F1=>"a"}}, {IN=>{F2=>"b"}}, {OUT=>"  a\n  b\n"}],
 
-- 
2.55.0




Reply via email to