coreutils
coreutils copied to clipboard
numfmt and printf with LONG_MIN and MAX
This is the issue I want to discuss.
I tried to run gnu tests locally. It appeared that some tests use all the memory.
After some investigation it appeared that there are this tests:
-
numfmt --padding=-9223372036854775808 0
So the test is actually
['pad-3.2', "--padding=$limits->{LONG_MIN} 0", {ERR => "$prog: invalid padding value '$limits->{LONG_MIN}'\n"}, {EXIT => '1'}],
this padding is unsupported in GNU version. And uutils version "supports" it, but probably not that I think that this use case with that large number bothers anyone. So GNU tests will fail, this will take many resources when running until all the memory is out, and also it's very slow if there is swap.
-
The same thing for other test cases
printf %.*d 2147483648 15
and
printf %*d 2147483648 15
which are
['d-big-prec', "%.*d $pow_2_31 15", # INT_MAX {EXIT=>1}, {ERR=>"$prog: invalid precision: '$pow_2_31'\n"}], ['d-big-fwidth', "%*d $pow_2_31 15", # INT_MAX {EXIT=>1}, {ERR=>"$prog: invalid field width: '$pow_2_31'\n"}],
What do you think, should we do?
- Just don't run them
- Change uutils version to handle the testcases as GNU does for these specific values
- Change uutils version to handle all big values as GNU does, not just these ones
- Somehow make a dummy preallocation of this size, to throw out
memory exhausted
error, and immediately free allocated memory. Somehow like that:
and change the tests to print the similar error. This will help to immediately raise an error, not wait until all memory comes out.{ // this is done just for gnu tests to pass let mut v = vec![0u8; 1]; v.try_reserve(implicit_padding.unwrap_or(options.padding).unsigned_abs()) .map_err(|_| "memory exhausted")? }
If I understand correctly, GNU has some limits on the inputs they accept? I think that would be a good design decision, because if the padding is that large, it's very likely to be an error.
I also like that solution. I will fix it then.
Focusing just on numfmt, I checked GNU[1] and they check specifically for
padding_width < -LONG_MAX
So we could just do the same? Although it's probably some implementation-specific reason for them to check for it.
1: https://github.com/coreutils/coreutils/blob/master/src/numfmt.c#L1500
Edit: I figured it out. They flip the padding_width
to positive if a negative integer is given. And since LONG_MIN = -LONG_MAX - 1
, they can't flip the value if it is LONG_MIN
. If we don't have this limitation, I suggest we disable the test.
And for printf
GNU version checks if INT_MIN <= width && width <= INT_MAX
and uutils version store it in isize
.
Disabled tests in #3781