Pádraig Brady <[email protected]> writes:

> On 04/07/2026 00:33, Collin Funk wrote:
>> I was going to push this test, but then I realized this behavior was
>> probably an unintentional consequence of Paul's commit to prefer
>> signed types [1]. So perhaps it is better to check that --max-depth is
>> positive, i.e., make this change instead:
>> diff --git a/src/du.c b/src/du.c
>> index bff1b6672..8d99c4265 100644
>> --- a/src/du.c
>> +++ b/src/du.c
>> @@ -860,7 +860,7 @@ main (int argc, char **argv)
>>             {
>>               intmax_t tmp;
>>               if (xstrtoimax (optarg, NULL, 0, &tmp, "") == LONGINT_OK
>> -                && tmp <= IDX_MAX)
>> +                && 0 <= tmp && tmp <= IDX_MAX)
>>                 {
>>                   max_depth_specified = true;
>>                   max_depth = tmp;
>> Thoughts?
>
> Yes I think this is better.
> It would be confusing to allow negative values here.
> Also find -maxdepth disallows negative values.

Sounds good to me. I checked the 'find -maxdepth' example too before
sending and noticed that.

The behavior didn't seem *too* strange to me since it seemingly behaved
the same as 'du --max-depth=0' from my testing.

I pushed the attached patch restoring the original behavior, though.
While here I changed the overflow check to ckd_add which is my
preference. It removes the worry that the type of max_depth is different
than the limit macro, i.e., IDX_MAX. It also has the benefit of shutting
up coverity which complains the comparison is useless, which is not the
case on some machines where IDX_MAX < INTMAX_MAX. I closed a few of
those as "intentional".

Collin

>From 165b62de8083ed9dec9ef4e1699ed44c3c7a2b91 Mon Sep 17 00:00:00 2001
Message-ID: <165b62de8083ed9dec9ef4e1699ed44c3c7a2b91.1783135933.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Fri, 3 Jul 2026 20:24:39 -0700
Subject: [PATCH] du: treat negative --max-depth values as errors

* NEWS: Mention the bug fix.
* src/du.c (main): Prefer ckd_add to check for overflow. Emit an error
if the value is negative.
* tests/du/max-depth.sh: Add a test case for the bug.
---
 NEWS                  |  4 ++++
 src/du.c              |  7 ++-----
 tests/du/max-depth.sh | 11 +++++++++++
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index 2ae329509..b1ec92562 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   will correctly match the last delimiter specified.
   [bug introduced with multi-byte support in coreutils-9.11]
 
+  'du --max-depth=N' now exits with a nonzero exit status and an error message
+  if N is negative.  Previously it behaved as if N were zero.
+  [bug introduced in coreutils-9.4]
+
   'head' and 'tail' now quote names in file headers when needed.
   [This bug was present in "the beginning".]
 
diff --git a/src/du.c b/src/du.c
index bff1b6672..9b8063371 100644
--- a/src/du.c
+++ b/src/du.c
@@ -860,11 +860,8 @@ main (int argc, char **argv)
           {
             intmax_t tmp;
             if (xstrtoimax (optarg, NULL, 0, &tmp, "") == LONGINT_OK
-                && tmp <= IDX_MAX)
-              {
-                max_depth_specified = true;
-                max_depth = tmp;
-              }
+                && ! ckd_add (&max_depth, tmp, 0) && 0 <= max_depth)
+              max_depth_specified = true;
             else
               {
                 error (0, 0, _("invalid maximum depth %s"),
diff --git a/tests/du/max-depth.sh b/tests/du/max-depth.sh
index 8684379eb..420d88632 100755
--- a/tests/du/max-depth.sh
+++ b/tests/du/max-depth.sh
@@ -36,4 +36,15 @@ cut -f2- out > k && mv k out
 compare exp out || fail=1
 compare /dev/null err || fail=1
 
+# Repeat, but use -d -1 and check for an error.
+# coreutils 9.4 to 9.11 would mistakenly behave as if --max-depth=0 were
+# specified when given a negative value.
+cat <<\EOF >exp || framework_failure_
+du: invalid maximum depth '-1'
+Try 'du --help' for more information.
+EOF
+returns_ 1 du -d -1 a >out 2>err || fail=1
+compare /dev/null out || fail=1
+compare exp err || fail=1
+
 Exit $fail
-- 
2.55.0

Reply via email to