Fix undefined overflow behavior when converting double to integer (#3629)

Overflows in conversions from floating-point to integer are
undefined behavior in the C99 standard. (Clause 6.3.1.4: "If the
value of the integral part cannot be represented by the integer
type, the behavior is undefined.")

When UBSAN is enabled, this gets reported at `srand()` calls. (The
random seed is usually initialized using the date port API, which
represents dates as `double`s. But `srand` takes an `unsigned int`.
A simple cast from `double` to `unsigned` becomes undefined
behavior if the value is too large. And "now" is too large
nowadays. So, effectively, all executions start with an undefined
behavior.)

This patch fixes this by casting the floating-point value of the
date to an integer through a union.

JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu
This commit is contained in:
Akos Kiss 2020-03-27 11:03:28 +01:00 committed by GitHub
parent 18a4cba062
commit f29e6f9020
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 26 additions and 9 deletions

View File

@ -1084,7 +1084,8 @@ int
main (void)
{
/* Initialize srand value */
srand ((unsigned) jerry_port_get_current_time ());
union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () };
srand (now.u);
/* Generate a random number, and print it */
const jerry_char_t script[] = "var a = Math.random (); print(a)";

View File

@ -72,7 +72,12 @@ int
main (int argc,
char **argv)
{
srand ((unsigned) jerry_port_get_current_time ());
union
{
double d;
unsigned u;
} now = { .d = jerry_port_get_current_time () };
srand (now.u);
if (argc <= 1 || (argc == 2 && (!strcmp ("-h", argv[1]) || !strcmp ("--help", argv[1]))))
{
print_help (argv[0]);

View File

@ -467,7 +467,12 @@ int
main (int argc,
char **argv)
{
srand ((unsigned) jerry_port_get_current_time ());
union
{
double d;
unsigned u;
} now = { .d = jerry_port_get_current_time () };
srand (now.u);
JERRY_VLA (const char *, file_names, argc);
int files_counter = 0;

View File

@ -136,7 +136,8 @@ void eval_jerry_script (int argc, char *argv[], struct tcmd_handler_ctx *ctx)
void jerry_start ()
{
srand ((unsigned) jerry_port_get_current_time ());
union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () };
srand (now.u);
jerry_init (JERRY_INIT_EMPTY);
jerry_value_t global_obj_val = jerry_get_global_object ();
jerry_value_t print_func_name_val = jerry_create_string ((jerry_char_t *) "print");

View File

@ -26,7 +26,8 @@ static const char* fn_sys_loop_name = "sysloop";
void js_entry ()
{
srand ((unsigned) jerry_port_get_current_time ());
union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () };
srand (now.u);
jerry_init (JERRY_INIT_EMPTY);
js_register_functions ();

View File

@ -68,7 +68,8 @@ static int load_javascript() {
}
int jsmbed_js_init() {
srand ((unsigned) jerry_port_get_current_time());
union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () };
srand (now.u);
jerry_init_flag_t flags = JERRY_INIT_EMPTY;
jerry_init(flags);

View File

@ -98,7 +98,8 @@ const shell_command_t shell_commands[] = {
int main (void)
{
srand ((unsigned) jerry_port_get_current_time ());
union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () };
srand (now.u);
printf ("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
printf ("This board features a(n) %s MCU.\n", RIOT_MCU);

View File

@ -79,7 +79,8 @@ static int shell_cmd_handler (char *source_buffer)
void main (void)
{
srand ((unsigned) jerry_port_get_current_time ());
union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () };
srand (now.u);
uint32_t zephyr_ver = sys_kernel_version_get ();
printf ("JerryScript build: " __DATE__ " " __TIME__ "\n");
printf ("JerryScript API %d.%d.%d\n", JERRY_API_MAJOR_VERSION, JERRY_API_MINOR_VERSION, JERRY_API_PATCH_VERSION);

View File

@ -49,7 +49,8 @@
#define TEST_INIT() \
do \
{ \
srand ((unsigned) jerry_port_get_current_time ()); \
union { double d; unsigned u; } now = { .d = jerry_port_get_current_time () }; \
srand (now.u); \
} while (0)
/**