[PATCH] Give a useful meaning to arc4random_uniform(0);

Alejandro Colomar alx.manpages@gmail.com
Sat Dec 31 15:59:46 GMT 2022


Hi Theo,

On 12/31/22 16:13, Alejandro Colomar wrote:
> Hi Theo,
> 
> On 12/31/22 15:56, Alejandro Colomar wrote:
>>>
>>> I do not like your proposal at all.  A function like arc4random_range()
>>> is even more likely to be used wrong by passing backwards points
>>> and you seem to have a lot of hubris to add a range check to it.
> 
> I didn't understand the entire sentence, since I'm not a native English speaker. 
>   Sorry for that.  About adding a range check, I'm not against it.  But what to 
> do in that case?  abort()?  I don't see anything significantly better?  In the 
> Linux kernel, the used something BUILD_BUG, but I don't know those macros very 
> much.
> 
> I'm really open to discussion about what would the the best behavior when max < 
> min.

Since there's no obvious thing to do when the bounds are reversed (some may want 
to abort(); others may prefer to set errno?; others may just want to ignore the 
possibility...

I tried to understand what it does with the obvious implementation:


 > Alejandro Colomar <alx.manpages@gmail.com> wrote:
 >> uint32_t
 >> arc4random_range(uint32_t min, uint32_t max)
 >> {
 >> 	return arc4random_uniform(max - min + 1) + min;
 >> }

Well, let's substitute with some actual values:

	arc4random_range(7, 4);

This will result in:

	arc4random_uniform(4 - 7 + 1) + 7;

which evaluates to:

	arc4random_uniform(-2) + 7;

and is equivalent to:

	arc4random_uniform(UINT32_MAX - 1) + 7;

Let's first ignore the +7.  The arc4random_uniform(UINT32_MAX - 1) call can 
generate 2^32 - 2 random numbers.  By offsetting to 7, the 2 value that are 
excluded are 6 and 5.

So it seems that a reversed call to arc4random_range(min, max) has an 
interesting property: it generates random numbers outside of the non-inclusive 
range (min, max), that is the compementary set of numbers that arc4random(max, 
min) would produce.

If properly documented, it's not a bad behavior.

So, I'd rather not check bounds, and instead document the behavior when the 
ranges are reversed.  Then, anyone is free to add their own wrapper that adds 
checks and performs their favourite action on reversed input, which might differ 
from one programmer to another.

Cheers,

Alex

> 
> Cheers,
> 
> Alex
> 
>>
>> Oh, I just checked hubris in the dictionary and it seems you did mention ego. 
>> I'll try to rebate you with something useful.
>>
>> If you run `grep -rn 'arc4random_uniform('` in the OpenBSD tree, there will be 
>> many cases where you'd really benefit from this.  I'll just pick a few:
>>
>>
>> sys/net/pf_lb.c:224:
>>              cut = arc4random_uniform(1 + high - low) + low;
>> better as:
>>              cut = arc4random_range(low, high);
>>
>>
>> sys/kern/kern_fork.c:648:
>>          pid = 2 + arc4random_uniform(PID_MAX - 1);
>> better as:
>>          pid = arc4random_range(2, PID_MAX);
>>
>>
>> usr.bin/nc/netcat.c:1501:
>>                  cp = arc4random_uniform(x + 1);
>> better as:
>>                  cp = arc4random_range(0, x);
>>
>>

-- 
<http://www.alejandro-colomar.es/>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20221231/d2ad513f/attachment-0001.sig>


More information about the Libc-alpha mailing list