Skip to content

Conversation

@kernelpoetlaureate
Copy link

cmp: fix -n flag incorrectly enabling verbose output

Bug: When using cmp -n NUM without -l, the program would incorrectly continue comparing after finding the first difference, printing multiple 'differ' lines instead of just one.

Root Cause: The bug was in line 144: if (opt) checked if ANY option was set (including -n), causing it to continue. It should only continue for -l (verbose) mode: if (opt & CMP_OPT_l).

Test Case:

echo -n AAAAA > file1
echo -n BBBBB > file2
# Before: cmp -n 3 file1 file2 → 3 lines of output
# After:  cmp -n 3 file1 file2 → 1 line of output
# Both:   cmp -l -n 3 file1 file2 → 3 lines (correct)

rmyorston and others added 30 commits December 9, 2024 02:16
When getopt32() has complementary options it's possible to specify
the minimum and maximum number of arguments allowed.  Checking
these values was inconsistent:

- '?' correctly checked that it was followed by a digit but set
  the otherwise unused spec_flgs variable on error.

- '=' failed to check that it was followed by a digit.

function                                             old     new   delta
vgetopt32                                           1307    1319     +12

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Fix bug introduced in busybox 1.37.0 that broke kernel builds.

Fixes commit e2287f9 (od: for !DESKTOP, match output more closely
to GNU coreutils 9.1, implement -s)

function                                             old     new   delta
rewrite                                              967     976      +9

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Using cut with the delimiter flag ("-d") with the "-s" flag to only
output lines containing the delimiter will print blank lines. This is
deviant behavior from cut provided by GNU Coreutils. Blank lines should
be omitted if "-s" is used with "-d".

This change introduces a somewhat naiive, yet efficient solution, where
line length is checked before looping though bytes. If line length is
zero and the "-s" flag is used, the code will jump to parsing the next
line to avoid printing a newline character.

function                                             old     new   delta
cut_main                                            1196    1185     -11

Signed-off-by: Colin McAllister <colinmca242@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 0068ce2 (cut: add toybox-compatible options -O OUTSEP,
-D, -F LIST) added detection of reversed ranges.  Further
improvements are possible.

- The test for reversed ranges compared the start after it had been
  decremented with the end before decrement.  It thus missed ranges
  of the form 2-1.

- Zero isn't a valid start value for a range.  (Nor is it a valid
  end value, but that's caught by the test for a reversed range.)

- The code

        if (!*ltok)
            e = INT_MAX;

  duplicates a check that's already been made.

- Display the actual range in the error message to make it easier
  to find which range was at fault.

function                                             old     new   delta
.rodata                                           100273  100287     +14
cut_main                                            1239    1237      -2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 14/-2)              Total: 12 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This imporves readability

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1218    1228     +10

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1228    1201     -27

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
packed_usage                                       34897   34849     -48

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1204    1261     +57
static.cut_longopts                                    -      20     +20
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 77/0)               Total: 77 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1261    1353     +92
packed_usage                                       34925   34901     -24
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 92/-24)             Total: 68 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
packed_usage                                       34901   34934     +33
cut_main                                            1353    1339     -14
.rodata                                           105724  105685     -39
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/2 up/down: 33/-53)            Total: -20 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1339    1348      +9

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1344    1339      -5

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1339    1391     +52

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1391    1410     +19

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
.rodata                                           105685  105659     -26

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
…ariable

function                                             old     new   delta
cut_main                                            1410    1404      -6

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
We don't need to mimic GNU cut error messages.

$ cut -d@ -b3
cut: -d DELIM makes sense only with -f or -F
$ cut -s -b3
cut: -s makes sense only with -f or -F

function                                             old     new   delta
static._op_on_field                                   31      32      +1
.rodata                                           105659  105598     -61
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 1/-61)             Total: -60 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
$ cut -s -b3
cut: -s requires -f or -F
$ cut -d@ -b3
cut: -d DELIM requires -f or -F

function                                             old     new   delta
static.requires_f                                      -      19     +19
static._op_on_field                                   32       -     -32
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 0/0 up/down: 19/-32)            Total: -13 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
cut_main                                            1404    1388     -16

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Denys Vlasenko added 24 commits August 17, 2025 17:59
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
done_word                                            790     766     -24

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
For some reason, it was only happening in interactive use

function                                             old     new   delta
initialize_context                                    39      54     +15
parse_stream                                        3077    3063     -14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 15/-14)              Total: 1 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
done_word                                            766     777     +11
static.reserved_match                                 16      12      -4
reserved_list                                        240     168     -72
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/2 up/down: 11/-76)            Total: -65 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
parse_stream                                        3063    3075     +12
done_word                                            777     784      +7
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 19/0)               Total: 19 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
write2pipe                                             -     133    +133
.rodata                                           105992  106009     +17
readtoken1                                          3101    3111     +10
cmdtxt                                               631     641     +10
nodesize                                              27      28      +1
redirect                                             961     916     -45
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 4/1 up/down: 171/-45)           Total: 126 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
…quence attacks

This fixes CVE-2025-46394 (terminal escape sequence injection)

Original credit: Ian.Norton at entrust.com

function                                             old     new   delta
header_list                                            9      15      +6
header_verbose_list                                  239     244      +5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 11/0)               Total: 11 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Currently vi in Busybox doesn't support filtering text through an
external command with ':1,2!cmd'.  Instead it behaves as if no
range had been supplied and displays the output of the command.

Issue a warning and do nothing in such cases.

function                                             old     new   delta
colon                                               3993    4010     +17

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Remove the puts(cterm) call that was likely leftover debugging code.
The controlling terminal name is already properly displayed via the
'Controlling term:' label, so the raw terminal name output was redundant
and could cause issues when cterm is NULL.

Also add proper cleanup for the allocated cterm string.

function                                             old     new   delta
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0)                 Total: 0 bytes

Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Specifying a PID of 0 for the -p option of chrt would previously result
in a "number 0... not in range" error. Now, it means instead that the
calling process (i.e. chrt itself) should be operated on; this is to be
consistent with the behavior of util-linux's version of chrt.

function                                             old     new   delta
chrt_main                                            462     474     +12

Signed-off-by: Zuo An <zuoan.penguin@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
busybox cp refuses to overwrite another symlink to a directory due to
an incorrect stat() call that should be lstat(). When using -T, we want
to consider the target argument directly without resolving symlinks.

function                                             old     new   delta
cp_main                                              496     514     +18

Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
…on ppc64le

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
update_local_clock                                   872     951     +79

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
busybox_main                                         695     734     +39

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The first login entry is ignored if a log file contains more than one
entry. To fix it, do not break the while loop if the offset is zero.

Signed-off-by: Dmitry Klochkov <dmitry.klochkov@bell-sw.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
'\W' in PS1 returned an empty string for the root directory.  bash
displays '/' in similar circumstances.

Avoid returning an empty string for the directory.

function                                             old     new   delta
parse_and_put_prompt                                 873     883     +10

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Since commit 551bfdb (ls: implement -q, fix -w0, reduce startup
time) the '--color' option behaves as though the default argument
'always' had been specified.

This is due to an explicit short option for '--color' being given,
but without specifying that an argument is expected.

function                                             old     new   delta
.rodata                                           106027  106029      +2

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When running `pgrep -x example` against a process `/bin/example --arg`,
BusyBox fails to match, while GNU pgrep succeeds. The reason is that the
comparison is done only against the full argv[0] rather than comm. This
patch changes pgrep -x to also try /proc/[pid]/comm for exact matching.

function                                             old     new   delta
pgrep_main                                           681     670     -11

Signed-off-by: Paulius Zaleckas <paulius.zaleckas@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
xatoull_range_sfx                                      -      49     +49
dd_main                                             1607    1640     +33
bb_banner                                             47      46      -1
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 82/-1)              Total: 81 bytes

Signed-off-by: Sertonix <sertonix@posteo.net>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Fixes missing [-s] option in trivial usage section of `eject --help`

function                                             old     new   delta
packed_usage                                       35125   35127      +2

Signed-off-by: Nir Lichtman <nir@lichtman.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
.rodata                                           106388  106438     +50
tls_xread_record                                     650     681     +31
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 81/0)               Total: 81 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
function                                             old     new   delta
packed_usage                                       35768   35802     +34
xxd_main                                            1447    1449      +2
.rodata                                           106438  106439      +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 37/0)               Total: 37 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
@kernelpoetlaureate kernelpoetlaureate force-pushed the fix/cmp-n-flag-bug branch 2 times, most recently from a0a6340 to 8e2db66 Compare December 6, 2025 08:21
When using 'cmp -n NUM' without '-l', the program would incorrectly
continue comparing after finding the first difference, printing
multiple 'differ' lines instead of just one.

The bug was in line 144: 'if (opt)' checked if ANY option was set
(including -n), causing it to continue. It should only continue
for -l (verbose) mode: 'if (opt & CMP_OPT_l)'.

This was correct when originally written (only -l and -s existed),
but became a bug when -n was added later.

Test case:
  echo -n AAAAA > file1
  echo -n BBBBB > file2
  Before: cmp -n 3 file1 file2 -> 3 lines of output
  After:  cmp -n 3 file1 file2 -> 1 line of output
  Both:   cmp -l -n 3 file1 file2 -> 3 lines (correct)

v2: Removed stale comment as suggested by Harald van Dijk.

Signed-off-by: Giorgi Tchankvetadze <giorgitchankvetadze1997@gmail.com>
Stop wasting CPU when skip values exceed file size.
Performance improvement: 5500x faster for large skips.
@robang74
Copy link
Contributor

robang74 commented Jan 19, 2026

This repository is rarely updated as you can see by 100+ commits into your PR, sent the patch to: busybox@busybox.net

By the way, I am using my git-function project to keep update my fork of busybox:

+:git-shell:master:busybox> lsrmt
busybox.net git://busybox.net/busybox.git (fetch)
busybox.net git://busybox.net/busybox.git (push)
origin https://github.com/robang74/busybox.git (fetch)
origin https://github.com/robang74/busybox.git (push)

While git-functions project stays here:

I will appreciate testers and contributors to the (*) gitshell project. I am very satisfied by using it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.