NetBSD Problem Report #59522
From www@netbsd.org Wed Jul 9 06:43:47 2025
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id B2F5E1A923C
for <gnats-bugs@gnats.NetBSD.org>; Wed, 9 Jul 2025 06:43:47 +0000 (UTC)
Message-Id: <20250709064346.4CC751A923E@mollari.NetBSD.org>
Date: Wed, 9 Jul 2025 06:43:46 +0000 (UTC)
From: mrg@eterna23.net
Reply-To: mrg@eterna23.net
To: gnats-bugs@NetBSD.org
Subject: jot random seed handling relies upon undefined float to integer conversion
X-Send-Pr-Version: www-1.0
>Number: 59522
>Category: bin
>Synopsis: jot random seed handling relies upon undefined float to integer conversion
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Jul 09 06:45:00 +0000 2025
>Originator: matthew green
>Release: 10.1 or so
>Organization:
>Environment:
evbmips64eb. i also heard it affects evbarmv7.
>Description:
i noticed that jot -r output was identical for different runs where the
-r option is supposed to generate random data.
eventually i tracked this down to the way the random seed is generated
by default. this first bit is the initialisation of 'step':
static double step = STEP_DEF;
...
if (randomize) {
/* 'step' is the seed here, use pseudo-random default */
if (!(have & STEP))
step = time(NULL) * getpid();
'step' is them passed into srandom(3):
srandom((unsigned long) step);
note that this is also converted to unsigned int via srandom prototype.
on x86 and most platforms, this conversion from double -> 32-bit int
provides the lower 32-bits that would be set in the converted value,
but on evbmips64-eb, the value is saturated, and so srandom() is passed
2^32-1 in all cases, as getpid() will be more than 2, and time(NULL)
will be more than 1/3rd of 32-bits (the range from pid 3 to pid 30000
here is 5254448208 to 52544482080000, clearly well beyond what can be
represented in a 32-bit value.)
as far as i can tell, depending on whether something is handled by the
builtin conversions, or via some libgcc/etc function, the result may
be even different on the same platform, as GCC and compiler-rt don't
agree about it always.
unfortunately, this conversion is undefined behaviour (C11):
6.3.1.4 Real floating and integer
When a finite value of real floating type is converted to an integer type other than _Bool,
the fractional part is discarded (i.e., the value is truncated toward zero). If the value of
the integral part cannot be represented by the integer type, the behavior is undefined.
>How-To-Repeat:
run "jot -r 1 0 21600" on a platform with the problem.
see the same output always.
>Fix:
since the seed is 32 bits, and the "step" range is basically between 30,000 * <latest epoch value>, this fits comfortably into a 64-bit
value for the next few millennia and beyond, i think the simplest
fix here is to change the srandom() call to:
srandom((unsigned int)(unsigned long long)step);
which works in my testing.
i couldn't find a good way to perform this truncation directly without
some sort of loop, otherwise i'd do that..
(Contact us)
$NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2025
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.