Martin Natano wrote:
> Hi,
>
> The add_entropy_words() function performs a right shift by
> (32 - entropy_input_rotate) bits, with entropy_input_rotate being an
> integer between [0..31]. This can lead to a shift of 32 on a 32 bit
> value, which is undefined behaviour in C. The standard says this: "If
> the value of the right operand is negative or is greater than or equal
> to the width of the promoted left operand, the behaviour is undefined."
> In our case the value is 32 and the width of the promoted left operand
> is 32 too, thus the behaviour is undefined.
>
> As a matter of fact the expression doesn't yield the (probably) expected
> result of 0 on i386 and amd64 machines. The reason being, that the shift
> exponent is truncated to 5 bits on x86.
>
> natano@obsd:~$ uname -a
> OpenBSD obsd.my.domain 5.9 GENERIC.MP#1862 amd64
> natano@obsd:~$ cat test.c
> #include <stdio.h>
>
> int
> main(void)
> {
> unsigned int x = 0xffffffff;
> printf("x >> 32: 0x%x\n", x >> 32);
> return 0;
> }
> natano@obsd:~$ cc test.c
> test.c: In function 'main':
> test.c:7: warning: right shift count >= width of type
> natano@obsd:~$ ./a.out
> x >> 32: 0xffffffff
> natano@obsd:~$
>
> On the other hand ppc truncates the shift exponent to 6 bits. (I didn't
> try it, but
> http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
> says so).
>
> In the specific instance below, the differing behaviour between x86 and
> pcc doesn't matter, because of the equality (x | x) == (x | 0) == x.
>
> However, I think it might be still worth fixing this, because we can't
> rely on future versions of gcc and other compilers retaining this
> behaviour. The behaviour is undefined, so the compiler can do whatever
> it wants (insert obligatory reference to nasal demons here).
I think we don't mix declarations and code.
Would this be an option?
diff --git a/dev/rnd.c b/dev/rnd.c
index 819ce0d..0f57b1b 100644
--- a/dev/rnd.c
+++ b/dev/rnd.c
@@ -421,7 +421,7 @@ add_entropy_words(const u_int32_t *buf, u_int n)
for (; n--; buf++) {
u_int32_t w = (*buf << entropy_input_rotate) |
- (*buf >> (32 - entropy_input_rotate));
+ (*buf >> ((32 - entropy_input_rotate) & 31));
u_int i = entropy_add_ptr =
(entropy_add_ptr - 1) & POOLMASK;
/*
> Index: dev/rnd.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/rnd.c,v
> retrieving revision 1.178
> diff -u -p -u -r1.178 rnd.c
> --- dev/rnd.c 8 Jan 2016 07:54:02 -0000 1.178
> +++ dev/rnd.c 31 Jan 2016 10:11:17 -0000
> @@ -420,8 +420,9 @@ add_entropy_words(const u_int32_t *buf,
> };
>
> for (; n--; buf++) {
> - u_int32_t w = (*buf << entropy_input_rotate) |
> - (*buf >> (32 - entropy_input_rotate));
> + u_int32_t w = *buf << entropy_input_rotate;
> + if (entropy_input_rotate > 0)
> + w |= *buf >> (32 - entropy_input_rotate);
> u_int i = entropy_add_ptr =
> (entropy_add_ptr - 1) & POOLMASK;
> /*
>
> cheers,
> natano
>