Skip to content

Fix an undefined behaviour in os/rand.c#2050

Open
jkbonfield wants to merge 1 commit into
samtools:developfrom
jkbonfield:rand_ubsan
Open

Fix an undefined behaviour in os/rand.c#2050
jkbonfield wants to merge 1 commit into
samtools:developfrom
jkbonfield:rand_ubsan

Conversation

@jkbonfield

Copy link
Copy Markdown
Contributor

This is really picky and I almost didn't bother given this is just code lifted from FreeBSD which hasn't changed it in 32 years.

https://github.com/lattera/freebsd/blame/401a161083850a9a4ce916f37520c084cff1543b/lib/libc/gen/_rand48.c#L32-L49

However undefined behaviour sanitizer whinges about signed overflows. This happens because the promotion of unsigned short in arithmetic expressions is to signed int, and then multiplying signed ints can overflow from signed to unsigned.

Eg:

    (gdb) p (unsigned short)50000 * (unsigned short)45000
    $1 = -2044967296
    (gdb) p (unsigned int)50000 * (unsigned int)45000
    $2 = 2250000000

Due to 2s complement this makes no difference and casting both to unsigned int before the multiplcation gives you the same bit pattern. It's just the resulting type that differs, as we change that in the assignment anyway.

(Note there are similar undefined behaviour issues with md5.c, which I didn't fix.)

This is really picky and I almost didn't bother given this is just
code lifted from FreeBSD which hasn't changed it in 32 years.

https://github.com/lattera/freebsd/blame/401a161083850a9a4ce916f37520c084cff1543b/lib/libc/gen/_rand48.c#L32-L49

However undefined behaviour sanitizer whinges about signed overflows.
This happens because the promotion of unsigned short in arithmetic
expressions is to signed int, and then multiplying signed ints can
overflow from signed to unsigned.

Eg:
    (gdb) p (unsigned short)50000 * (unsigned short)45000
    $1 = -2044967296
    (gdb) p (unsigned int)50000 * (unsigned int)45000
    $2 = 2250000000

Due to 2s complement this makes no difference and casting both to
unsigned int before the multiplcation gives you the same bit pattern.
It's just the resulting type that differs, as we change that in the
assignment anyway.

(Note there are similar undefined behaviour issues with md5.c, which I
didn't fix.)

Signed-off-by: James Bonfield <jkb@sanger.ac.uk>
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.

1 participant