UBSAN error in lib/sh/random.c:79

2023-01-06 Thread Sam James
Hi folks,

I'm currently testing common Linux userland with UndefinedBehaviorSanitizer 
(UBSAN, -fsanitize=undefined).

With Bash 5.2_p15, I get the following with this script:
```
$ cat /tmp/guess_suffix
guess_suffix() {
tmpdir="${TMPDIR}"/.ecompress$$.${RANDOM}
}
guess_suffix
```

It seems easier to trigger if I run it as an external script rather than as a 
function in an interactive
shell.

```
$ export UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1"
$ bash -x /tmp/guess_suffix
+ guess_suffix
random.c:79:21: runtime error: signed integer overflow: 31789 * 127773 cannot 
be represented in type 'int'
#0 0x559791a301ce in intrand32 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/lib/sh/random.c:79
#1 0x559791a301ce in brand 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/lib/sh/random.c:106
#2 0x5597918cde5c in get_random_number 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/variables.c:1436
#3 0x5597918cde5c in get_random 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/variables.c:1448
#4 0x5597918d0021 in find_variable 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/variables.c:2425
#5 0x55979194a881 in parameter_brace_expand_word 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:7514
#6 0x559791939783 in parameter_brace_expand 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:9845
#7 0x559791939783 in param_expand 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:10538
#8 0x559791941732 in expand_word_internal 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:11236
#9 0x5597919487b8 in call_expand_word_internal 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:4325
#10 0x5597919487b8 in expand_string_assignment 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:4423
#11 0x559791935c27 in expand_string_if_necessary 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:3855
#12 0x5597919365c3 in do_assignment_internal 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:3587
#13 0x55979190e40b in do_assignment_statements 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:12898
#14 0x559791952269 in expand_word_list_internal 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:12978
#15 0x559791952269 in expand_words 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/subst.c:12280
#16 0x5597918be644 in execute_simple_command 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:4506
#17 0x5597918be644 in execute_command_internal 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:866
#18 0x5597918bce56 in execute_command_internal 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:1033
#19 0x5597918c5e7b in execute_function 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:5242
#20 0x5597918bf4d4 in execute_builtin_or_function 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:5487
#21 0x5597918bf4d4 in execute_simple_command 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:4737
#22 0x5597918bf4d4 in execute_command_internal 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:866
#23 0x5597918c13bb in execute_command 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/execute_cmd.c:413
#24 0x559791879fac in reader_loop 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/eval.c:171
#25 0x559791877463 in main 
/usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/shell.c:833
#26 0x7f3c001c5289  (/usr/lib64/libc.so.6+0x23289)
#27 0x7f3c001c5344 in __libc_start_main (/usr/lib64/libc.so.6+0x23344)
#28 0x559791878590 in _start (/usr/bin/bash.self+0x13e590)
```

This is on x86_64-pc-linux-gnu with GCC 13.0.0_pre20230101.

Best,
sam


signature.asc
Description: Message signed with OpenPGP


Re: UBSAN error in lib/sh/random.c:79

2023-01-06 Thread Greg Wooledge
On Sat, Jan 07, 2023 at 01:37:30AM +, Sam James wrote:
> $ cat /tmp/guess_suffix
> guess_suffix() {
> tmpdir="${TMPDIR}"/.ecompress$$.${RANDOM}
> }
> guess_suffix

> $ export UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1"
> $ bash -x /tmp/guess_suffix
> + guess_suffix
> random.c:79:21: runtime error: signed integer overflow: 31789 * 127773 cannot 
> be represented in type 'int'
> #0 0x559791a301ce in intrand32 
> /usr/src/debug/app-shells/bash-5.2_p15/bash-5.2/lib/sh/random.c:79

Well, the code in question looks like this (with comments removed):

static u_bits32_t
intrand32 (last)
 u_bits32_t last;
{
  bits32_t h, l, t;
  u_bits32_t ret;

  ret = (last == 0) ? 123459876 : last;
  h = ret / 127773;
  l = ret - (127773 * h);
  t = 16807 * l - 2836 * h;
  ret = (t < 0) ? t + 0x7fff : t;

  return (ret);
}

The line your error refers to is "l = ..." where the multiplication
occurs.  Also of note,

unicorn:/var/tmp/bash/bash-5.2$ grep bits32_t *.h
config.h:#define bits32_t int
config.h:#define u_bits32_t unsigned int
externs.h:extern u_bits32_t get_urandom32 PARAMS((void));

Variables "h" and "l" are both of type int (with a fancy name) on my
platform, and it seems on yours as well, based on your error message.

It would not surprise me if this is a long-standing bug in this RNG, but
I haven't analyzed the code well enough to understand why some of the
variables are defined with a signed type, and some with an unsigned
type.

Here are the comments which accompany the code:

  /* Minimal Standard generator from
 "Random number generators: good ones are hard to find",
 Park and Miller, Communications of the ACM, vol. 31, no. 10,
 October 1988, p. 1195. Filtered through FreeBSD.

 x(n+1) = 16807 * x(n) mod (m).

 We split up the calculations to avoid overflow.

 h = last / q; l = x - h * q; t = a * l - h * r
 m = 2147483647, a = 16807, q = 127773, r = 2836

 There are lots of other combinations of constants to use; look at
 https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-gener
ators.html#Other-random-number-generators */