NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
bin/59942: dd behaves differently compared to other BSD and GNU implementations when count=0
>Number: 59942
>Category: bin
>Synopsis: dd behaves differently compared to other BSD and GNU implementations when count=0
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Jan 25 19:25:00 +0000 2026
>Originator: Andrus Suvalau
>Release:
>Organization:
>Environment:
NetBSD 10.1 NetBSD 10.1 (GENERIC) #0: Mon Dec 16 13:08:11 UTC 2024 mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/amd64/compile/GENERIC amd64
>Description:
dd behaves differently on NetBSD compared to other BSD (OpenBSD, FreeBSD) and GNU implementations when count=0 is used to skip an offset in a data stream.
For example, on NetBSD the first invocation of dd does nothing:
printf "offset1234" | { dd bs=6 skip=1 count=0; dd; } 2>/dev/null
offset1234
However, the GNU implementation, as well as OpenBSD and FreeBSD, actually skip the offset:
printf "offset1234" | { dd bs=6 skip=1 count=0; dd; } 2>/dev/null
1234
As a result, a workaround is required on NetBSD, and it is not possible to use the same code to skip an offset across different platforms.
I propose aligning NetBSD?s dd behavior with other implementations so that it behaves the same way when count=0 is specified.
>How-To-Repeat:
1) Run the following command on NetBSD:
printf "offset1234" | { dd bs=6 skip=1 count=0; dd; } 2>/dev/null
2) Observe that the output is:
offset1234
3) Run the same command on GNU dd, OpenBSD, FreeBSD
4) Observe that the output is:
1234
>Fix:
>From 038977238de38b131d7a9edc3fe322ab6ccfec11 Mon Sep 17 00:00:00 2001
From: Andrus Suvalau <suvalov.andrew%gmail.com@localhost>
Date: Sun, 25 Jan 2026 12:48:18 +0100
Subject: [PATCH] dd: allow offset skipping when count=0 is specified
Make dd behave consistently with other BSD and GNU implementations
when count=0 is used.
---
bin/dd/args.c | 5 ++---
bin/dd/dd.c | 4 ++++
tests/bin/dd/t_dd.sh | 12 ++++++++++++
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/bin/dd/args.c b/bin/dd/args.c
index c3bb645ef9e6..52339885ab75 100644
--- a/bin/dd/args.c
+++ b/bin/dd/args.c
@@ -247,10 +247,9 @@ static void
f_count(char *arg)
{
- cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX);
+ cpy_cnt = strsuftoll("block count", arg, 0, LLONG_MAX - 1);
if (!cpy_cnt) {
- summary();
- exit(0);
+ cpy_cnt = LLONG_MAX;
}
}
diff --git a/bin/dd/dd.c b/bin/dd/dd.c
index b0966bbcb62f..2d43270491b4 100644
--- a/bin/dd/dd.c
+++ b/bin/dd/dd.c
@@ -369,6 +369,10 @@ dd_in(void)
int64_t n;
for (flags = ddflags;;) {
+ /* Process count=0. */
+ if (cpy_cnt == LLONG_MAX)
+ return;
+
if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt)
return;
diff --git a/tests/bin/dd/t_dd.sh b/tests/bin/dd/t_dd.sh
index 92652d8a021a..da395b3122ee 100644
--- a/tests/bin/dd/t_dd.sh
+++ b/tests/bin/dd/t_dd.sh
@@ -149,10 +149,22 @@ swab_body() {
test_swab badcfehg bs=8
}
+atf_test_case countzero
+countzero_head() {
+ atf_set "descr" "Tests count=0"
+}
+
+countzero_body() {
+ test_dd_length 512 \
+ "{ dd if=/dev/zero bs=528 count=1 | \
+ { dd of=/dev/null bs=16 skip=1 count=0; dd; }; } 2>/dev/null"
+}
+
atf_init_test_cases()
{
atf_add_test_case length
atf_add_test_case io
atf_add_test_case seek
atf_add_test_case swab
+ atf_add_test_case countzero
}
--
2.51.0
Home |
Main Index |
Thread Index |
Old Index