Skip to content

bug(ls): when --tabsize is a negative number ls successeds instead of rejecting it#13278

Merged
sylvestre merged 15 commits into
uutils:mainfrom
Devel08:fix-issue-12835
Jul 5, 2026
Merged

bug(ls): when --tabsize is a negative number ls successeds instead of rejecting it#13278
sylvestre merged 15 commits into
uutils:mainfrom
Devel08:fix-issue-12835

Conversation

@Devel08

@Devel08 Devel08 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

this PR resolves #12835
Whenever the value from --tabsize can't be parsed, it'll now throw an error, which message is identical to GNU's one. error code is 2, like in GNU, hexadecimal values are accepted

@sylvestre

Copy link
Copy Markdown
Contributor

some jobs are still failing

@Devel08

Devel08 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

@sylvestre yeah, that because of clippy, im fixing them rn

@codspeed-hq

codspeed-hq Bot commented Jul 5, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 331 untouched benchmarks
⏩ 46 skipped benchmarks1


Comparing Devel08:fix-issue-12835 (0b41ec4) with main (62f307c)

Open in CodSpeed

Footnotes

  1. 46 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@Devel08

Devel08 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

@sylvestre ready for review :)

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/resolution (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/retry (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/tail-n0f (fails in this run but passes in the 'main' branch)

Comment thread src/uu/ls/src/config.rs Outdated
} else {
return Err(Box::new(LsError::InvalidTabSize(size_str.clone())));
}
}

@sylvestre sylvestre Jul 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be moved in a function
and it should look more like (ie without the Ok())

  fn parse_tab_size(size_str: &str) -> Result<usize, Box<LsError>> {
      size_str
          .parse::<usize>()
          .ok()
          .or_else(|| {
              size_str
                  .strip_prefix("0x")
                  .or_else(|| size_str.strip_prefix("0X"))
                  .and_then(|hex| usize::from_str_radix(hex, 16).ok())
          })
          .ok_or_else(|| Box::new(LsError::InvalidTabSize(size_str.to_string())))
  }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I'm going to use that function, thanks!

Comment thread src/uu/ls/src/config.rs Outdated
}

impl Config {
fn parse_tab_size(size_str: &str) -> Result<usize, Box<LsError>> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why in impl Config { ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, i'll move it under parse_width, sorry

Comment thread src/uu/ls/src/config.rs Outdated
Comment on lines +978 to +984
match Self::parse_tab_size(size_str) {
Ok(n) => Some(n),
Err(e) => return Err(e),
}
} else {
options
.get_one::<String>(options::format::TAB_SIZE)
.and_then(|size| size.parse::<usize>().ok())
.or_else(|| std::env::var("TABSIZE").ok().and_then(|s| s.parse().ok()))
}
.unwrap_or(SPACES_IN_TAB);
None
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like ?

Suggested change
match Self::parse_tab_size(size_str) {
Ok(n) => Some(n),
Err(e) => return Err(e),
}
} else {
options
.get_one::<String>(options::format::TAB_SIZE)
.and_then(|size| size.parse::<usize>().ok())
.or_else(|| std::env::var("TABSIZE").ok().and_then(|s| s.parse().ok()))
}
.unwrap_or(SPACES_IN_TAB);
None
};
Some(Self::parse_tab_size(size_str)?
};

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't directly propagate LsError, can we?

Comment thread tests/by-util/test_ls.rs Outdated

scene.ucmd().args(&["-T", "3"]).succeeds();
scene.ucmd().args(&["--tabsize", "0"]).succeeds();
scene.ucmd().arg("--tabsize=-3").fails();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify the error message
and also add a string and a decimal for --tabsize=

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright

sylvestre added a commit to sylvestre/coreutils-1 that referenced this pull request Jul 5, 2026
* tests/ls/ls-misc.pl (tabsize-negative, tabsize-non-numeric): New tests
verifying that a negative or non-numeric --tabsize argument is rejected
with "invalid tab size" and exit status 2.
uutils/coreutils#13278
Comment thread src/uu/ls/src/config.rs
let tab_size = if needs_color {
Some(0)
} else if let Some(size_str) = options.get_one::<String>(options::format::TAB_SIZE) {
match parse_tab_size(size_str) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to be improve too

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use match to check if its none or not, but I think that's the most readable way, should I do it with match?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


          } else if let Some(size_str) = options.get_one::<String>(options::format::TAB_SIZE) {
              Some(parse_tab_size(size_str)?)
          } else {


is the same

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but that can't be done, as parse_tab_size returns an LsError and it cannot be propagated to from()

sylvestre added a commit to sylvestre/coreutils-1 that referenced this pull request Jul 5, 2026
* tests/ls/ls-misc.pl: Add tests, generated by a loop over invalid
values, verifying that a negative (-9), non-numeric (zz), or
fractional (0.5) --tabsize argument is rejected with
"invalid tab size" and exit status 2.
uutils/coreutils#13278
@sylvestre sylvestre merged commit a1763bf into uutils:main Jul 5, 2026
177 of 178 checks passed
@sylvestre

Copy link
Copy Markdown
Contributor

#13283 as follow up

@oech3

oech3 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Why do we have our own parser at here instead of clap's validation?

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.

bug(ls): when --tabsize is a negative number ls successeds instead of rejecting it

3 participants