[PATCH 1/1] unexpand: fix -f converting non-leading blanks

Diogo Santos dsan.dev.71 at gmail.com
Tue Jan 14 17:35:42 UTC 2025


Bug report 16180 shows that unexpand, when used with the
--first-only (-f) option, may convert non-leading blanks.

To address this, the if statement in line 163 was updated.
When '-f' is set and `ptr == line` (i.e., no leading blanks were found),
the line should be printed as-is, and processing should continue to the
next line. Since the if body already performs this behavior, the second
condition can be removed.

The test suite was updated:

- Added '-a' to test case 7 (it previously assumed the '-a' behavior).
- Added test case 9, which is based on an example from the bug report.
- Reorganized three test cases (because of the former).
- Added two new test cases to convey that '-f' overrides
  both '-a' and '-t'.
- Added '-a' to the last test (it previously assumed the '-a' behavior).

All tests pass when using GNU unexpand version 9.5
(after replacing '-f' with '--first-only').

The second argument of 'strcspn' was changed to reduce the size of
the '.rodata' section. The following command shows that the string
"\t " appears once, while " \t" appears eight times:

```
git grep -F '"\t "' | wc -l
git grep -F '" \t"' | wc -l
```

Fixes: https://bugs.busybox.net/show_bug.cgi?id=16180
Signed-off-by: Diogo Santos <dsan.dev.71 at gmail.com>
---
 coreutils/expand.c       |  4 ++--
 testsuite/unexpand.tests | 12 ++++++++++--
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/coreutils/expand.c b/coreutils/expand.c
index c4db26055..8f9d84ba8 100644
--- a/coreutils/expand.c
+++ b/coreutils/expand.c
@@ -160,11 +160,11 @@ static void unexpand(FILE *file, unsigned tab_size, unsigned opt)
 					putchar('\t');
 			}
 
-			if (!(opt & OPT_ALL) && ptr != line) {
+			if (!(opt & OPT_ALL)) {
 				printf("%*s%s", len, "", ptr);
 				break;
 			}
-			n = strcspn(ptr, "\t ");
+			n = strcspn(ptr, " \t");
 			printf("%*s%.*s", len, "", n, ptr);
 # if ENABLE_UNICODE_SUPPORT
 			{
diff --git a/testsuite/unexpand.tests b/testsuite/unexpand.tests
index aeaae13f0..665ce0121 100755
--- a/testsuite/unexpand.tests
+++ b/testsuite/unexpand.tests
@@ -26,9 +26,15 @@ testing "unexpand case 6" "unexpand" \
 	"\t12345678\n" "" "     \t12345678\n" \
 
 testing "unexpand case 7" "unexpand" \
+	"123 \t 45678\n" "" "123 \t 45678\n" \
+
+testing "unexpand case 8" "unexpand -a" \
 	"123\t 45678\n" "" "123 \t 45678\n" \
 
-testing "unexpand case 8" "unexpand" \
+testing "unexpand case 9" "unexpand" \
+	"1234567 8\n" "" "1234567 8\n" \
+
+testing "unexpand case 10" "unexpand" \
 	"a b\n" "" "a b\n" \
 
 testcase()
@@ -41,6 +47,7 @@ testcase()
 want='\ta       b    c'
 testcase
 testcase -f
+testcase -f -a
 testcase -f -t8
 testcase -t8 -f
 testcase -t8 --first-only
@@ -61,12 +68,13 @@ testcase -t4 -a
 want='\t\ta       b    c'
 testcase -t4 -f
 testcase -f -t4
+testcase -f -t4 -a
 testcase -t4 --first-only
 testcase --first-only -t4
 
 test x"$CONFIG_UNICODE_SUPPORT" = x"y" \
 && test x"$CONFIG_UNICODE_USING_LOCALE" != x"y" \
-&& testing "unexpand with unicode characher 0x394" "unexpand" \
+&& testing "unexpand with unicode characher 0x394" "unexpand -a" \
 	"1ΔΔΔ5\t99999\n" "" "1ΔΔΔ5   99999\n"
 
 exit $FAILCOUNT
-- 
2.39.5



More information about the busybox mailing list