This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch releases/13.0
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/releases/13.0 by this push:
new 502feadb3de stdlib/rand: replace weak LCG with xorshift32 PRNG
502feadb3de is described below
commit 502feadb3de5feb7b995bf7c47d6b6750ccfaa0b
Author: hanzhijian <[email protected]>
AuthorDate: Wed Jul 1 11:45:15 2026 +0800
stdlib/rand: replace weak LCG with xorshift32 PRNG
The existing first-order LCG (seed = 470001 * seed % 999563) has several
quality problems:
- Output range limited to [1, 999562] (~20 bits) instead of full 32-bit
- Lower bits have very short periods (8-bit period = 1, 16-bit = 105)
- Overall period only ~1M, far too short for many applications
- Causes mbedtls_rsa_gen_key to loop forever when rand() consumption
aligns with the cycle length (issue #16760)
Replace the entire order-based LCG implementation (CONFIG_LIBC_RAND_ORDER
0-3) with Marsaglia's xorshift32:
- Full 32-bit output range
- Period 2^32 - 1 (~4.29 billion)
- Fast: just three XOR/shift operations
- No floating-point math needed
- No CONFIG_LIBC_RAND_ORDER configuration required
Remove the CONFIG_LIBC_RAND_ORDER Kconfig option and clean up all
defconfig references (12 boards) and related comments.
Signed-off-by: hanzhijian <[email protected]>
---
.../stm32f1/et-stm32-stamp/configs/nsh/defconfig | 1 -
boards/arm/stm32f1/maple/configs/nsh/defconfig | 1 -
boards/arm/stm32f1/maple/configs/nx/defconfig | 1 -
boards/arm/stm32f1/maple/configs/usbnsh/defconfig | 1 -
.../tlsr82/tlsr8278adk80d/configs/nsh/defconfig | 1 -
boards/sim/sim/sim/configs/configdata/defconfig | 1 -
boards/sim/sim/sim/configs/linuxspi/defconfig | 1 -
boards/sim/sim/sim/configs/mtdpart/defconfig | 1 -
boards/sim/sim/sim/configs/mtdrwb/defconfig | 1 -
boards/sim/sim/sim/configs/nxffs/defconfig | 1 -
boards/sim/sim/sim/configs/spiffs/defconfig | 1 -
.../esp32s3-devkit/configs/mbedtls/defconfig | 1 -
drivers/crypto/Kconfig | 8 +-
libs/libc/stdlib/Kconfig | 9 -
libs/libc/stdlib/lib_srand.c | 254 ++++-----------------
15 files changed, 45 insertions(+), 238 deletions(-)
diff --git a/boards/arm/stm32f1/et-stm32-stamp/configs/nsh/defconfig
b/boards/arm/stm32f1/et-stm32-stamp/configs/nsh/defconfig
index 33ca6384081..30e6bb6b8c8 100644
--- a/boards/arm/stm32f1/et-stm32-stamp/configs/nsh/defconfig
+++ b/boards/arm/stm32f1/et-stm32-stamp/configs/nsh/defconfig
@@ -17,7 +17,6 @@ CONFIG_BOARD_LOOPSPERMSEC=5483
CONFIG_BUILTIN=y
CONFIG_DEFAULT_SMALL=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
-CONFIG_LIBC_RAND_ORDER=2
CONFIG_LINE_MAX=80
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=1024
diff --git a/boards/arm/stm32f1/maple/configs/nsh/defconfig
b/boards/arm/stm32f1/maple/configs/nsh/defconfig
index 619ff1f1dbf..8e133e7cdd2 100644
--- a/boards/arm/stm32f1/maple/configs/nsh/defconfig
+++ b/boards/arm/stm32f1/maple/configs/nsh/defconfig
@@ -32,7 +32,6 @@ CONFIG_BOARD_LOOPSPERMSEC=5483
CONFIG_BUILTIN=y
CONFIG_DEFAULT_SMALL=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
-CONFIG_LIBC_RAND_ORDER=2
CONFIG_LINE_MAX=80
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=1024
diff --git a/boards/arm/stm32f1/maple/configs/nx/defconfig
b/boards/arm/stm32f1/maple/configs/nx/defconfig
index 5d98c00a330..c53fce0cccb 100644
--- a/boards/arm/stm32f1/maple/configs/nx/defconfig
+++ b/boards/arm/stm32f1/maple/configs/nx/defconfig
@@ -45,7 +45,6 @@ CONFIG_I2C=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_LCD=y
CONFIG_LCD_SHARP_MEMLCD=y
-CONFIG_LIBC_RAND_ORDER=2
CONFIG_LINE_MAX=80
CONFIG_MQ_MAXMSGSIZE=64
CONFIG_NSH_BUILTIN_APPS=y
diff --git a/boards/arm/stm32f1/maple/configs/usbnsh/defconfig
b/boards/arm/stm32f1/maple/configs/usbnsh/defconfig
index 128d504fd3f..9ad34495e29 100644
--- a/boards/arm/stm32f1/maple/configs/usbnsh/defconfig
+++ b/boards/arm/stm32f1/maple/configs/usbnsh/defconfig
@@ -38,7 +38,6 @@ CONFIG_CDCACM_TXBUFSIZE=256
CONFIG_DEFAULT_SMALL=y
CONFIG_I2C=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
-CONFIG_LIBC_RAND_ORDER=2
CONFIG_LINE_MAX=80
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=1024
diff --git a/boards/arm/tlsr82/tlsr8278adk80d/configs/nsh/defconfig
b/boards/arm/tlsr82/tlsr8278adk80d/configs/nsh/defconfig
index aaf6a79db3d..796425b9c11 100644
--- a/boards/arm/tlsr82/tlsr8278adk80d/configs/nsh/defconfig
+++ b/boards/arm/tlsr82/tlsr8278adk80d/configs/nsh/defconfig
@@ -58,7 +58,6 @@ CONFIG_EXAMPLES_HELLO=y
CONFIG_FILE_STREAM=y
CONFIG_FS_PROCFS=y
CONFIG_INIT_ENTRYPOINT="nsh_main"
-CONFIG_LIBC_RAND_ORDER=0
CONFIG_LIBM=y
CONFIG_LINE_MAX=80
CONFIG_MTD=y
diff --git a/boards/sim/sim/sim/configs/configdata/defconfig
b/boards/sim/sim/sim/configs/configdata/defconfig
index 9c5c36b288c..993a31cc1bf 100644
--- a/boards/sim/sim/sim/configs/configdata/defconfig
+++ b/boards/sim/sim/sim/configs/configdata/defconfig
@@ -21,7 +21,6 @@ CONFIG_FS_FAT=y
CONFIG_FS_NXFFS=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="configdata_main"
-CONFIG_LIBC_RAND_ORDER=3
CONFIG_MTD=y
CONFIG_MTD_BYTE_WRITE=y
CONFIG_MTD_CONFIG=y
diff --git a/boards/sim/sim/sim/configs/linuxspi/defconfig
b/boards/sim/sim/sim/configs/linuxspi/defconfig
index d2a3159e298..08ce24951c2 100644
--- a/boards/sim/sim/sim/configs/linuxspi/defconfig
+++ b/boards/sim/sim/sim/configs/linuxspi/defconfig
@@ -18,7 +18,6 @@ CONFIG_FS_FAT=y
CONFIG_FS_NXFFS=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="nxffs_main"
-CONFIG_LIBC_RAND_ORDER=3
CONFIG_MTD=y
CONFIG_NXFFS_SCAN_VOLUME=y
CONFIG_RAMMTD=y
diff --git a/boards/sim/sim/sim/configs/mtdpart/defconfig
b/boards/sim/sim/sim/configs/mtdpart/defconfig
index 4c656e485bf..0b80d37dbe5 100644
--- a/boards/sim/sim/sim/configs/mtdpart/defconfig
+++ b/boards/sim/sim/sim/configs/mtdpart/defconfig
@@ -18,7 +18,6 @@ CONFIG_EXAMPLES_MTDPART=y
CONFIG_FS_FAT=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="mtdpart_main"
-CONFIG_LIBC_RAND_ORDER=3
CONFIG_MTD=y
CONFIG_MTD_PARTITION=y
CONFIG_RAMMTD=y
diff --git a/boards/sim/sim/sim/configs/mtdrwb/defconfig
b/boards/sim/sim/sim/configs/mtdrwb/defconfig
index 91024b95017..5abb2285ec8 100644
--- a/boards/sim/sim/sim/configs/mtdrwb/defconfig
+++ b/boards/sim/sim/sim/configs/mtdrwb/defconfig
@@ -19,7 +19,6 @@ CONFIG_EXAMPLES_MTDRWB=y
CONFIG_FS_FAT=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="mtdrwb_main"
-CONFIG_LIBC_RAND_ORDER=3
CONFIG_MTD=y
CONFIG_MTD_PARTITION=y
CONFIG_MTD_READAHEAD=y
diff --git a/boards/sim/sim/sim/configs/nxffs/defconfig
b/boards/sim/sim/sim/configs/nxffs/defconfig
index d2a3159e298..08ce24951c2 100644
--- a/boards/sim/sim/sim/configs/nxffs/defconfig
+++ b/boards/sim/sim/sim/configs/nxffs/defconfig
@@ -18,7 +18,6 @@ CONFIG_FS_FAT=y
CONFIG_FS_NXFFS=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="nxffs_main"
-CONFIG_LIBC_RAND_ORDER=3
CONFIG_MTD=y
CONFIG_NXFFS_SCAN_VOLUME=y
CONFIG_RAMMTD=y
diff --git a/boards/sim/sim/sim/configs/spiffs/defconfig
b/boards/sim/sim/sim/configs/spiffs/defconfig
index d86d8f84708..490b25ca005 100644
--- a/boards/sim/sim/sim/configs/spiffs/defconfig
+++ b/boards/sim/sim/sim/configs/spiffs/defconfig
@@ -20,7 +20,6 @@ CONFIG_DISABLE_PTHREAD=y
CONFIG_FS_SPIFFS=y
CONFIG_IDLETHREAD_STACKSIZE=4096
CONFIG_INIT_ENTRYPOINT="fstest_main"
-CONFIG_LIBC_RAND_ORDER=3
CONFIG_MTD=y
CONFIG_RAMMTD=y
CONFIG_RAMMTD_FLASHSIM=y
diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/mbedtls/defconfig
b/boards/xtensa/esp32s3/esp32s3-devkit/configs/mbedtls/defconfig
index 7371be1a16b..2c816a4a984 100644
--- a/boards/xtensa/esp32s3/esp32s3-devkit/configs/mbedtls/defconfig
+++ b/boards/xtensa/esp32s3/esp32s3-devkit/configs/mbedtls/defconfig
@@ -51,7 +51,6 @@ CONFIG_IOB_BUFSIZE=400
CONFIG_IOB_NBUFFERS=100
CONFIG_IOB_NCHAINS=32
CONFIG_IOB_THROTTLE=40
-CONFIG_LIBC_RAND_ORDER=2
CONFIG_LINE_MAX=255
CONFIG_MBEDTLS_APPS=y
CONFIG_MBEDTLS_APP_BENCHMARK=y
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 00b4d3f9155..66b4381e640 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -43,12 +43,10 @@ config DEV_URANDOM_XORSHIFT128
config DEV_URANDOM_CONGRUENTIAL
bool "Congruential"
---help---
- Use the same congruential general used with srand(). This
algorithm
- is computationally more intense and uses double precision
floating
- point. NOTE: Good randomness from the congruential generator
also
- requires that you also select CONFIG_LIBC_RAND_ORDER > 2
+ Use the same PRNG used with srand()/rand(). Uses the system
+ random number generator (xorshift32).
- NOTE: Not cyptographically secure
+ NOTE: Not cryptographically secure
config DEV_URANDOM_RANDOM_POOL
bool "Entropy pool"
diff --git a/libs/libc/stdlib/Kconfig b/libs/libc/stdlib/Kconfig
index d594b4cd8e3..272258344e3 100644
--- a/libs/libc/stdlib/Kconfig
+++ b/libs/libc/stdlib/Kconfig
@@ -5,15 +5,6 @@
menu "stdlib Options"
-config LIBC_RAND_ORDER
- int "Order of the random number generate"
- default 1
- range 0 3
- ---help---
- The order of the random number generator. 0=fast but very bad
random
- numbers, 3=slow but very good random numbers.
- 0 just use integer generation, 1-3 use floating point generation
-
config LIBC_HOMEDIR
string "Home directory"
default "/"
diff --git a/libs/libc/stdlib/lib_srand.c b/libs/libc/stdlib/lib_srand.c
index 3b5cc7a3273..39bc2113e84 100644
--- a/libs/libc/stdlib/lib_srand.c
+++ b/libs/libc/stdlib/lib_srand.c
@@ -27,231 +27,62 @@
#include <nuttx/config.h>
#include <stdlib.h>
+#include <stdint.h>
#include <nuttx/lib/lib.h>
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* First, second, and thired order congruential generators are supported */
-
-#ifndef CONFIG_LIBC_RAND_ORDER
-# define CONFIG_LIBC_RAND_ORDER 1
-#endif
-
-#if CONFIG_LIBC_RAND_ORDER > 3
-# undef CONFIG_LIBC_RAND_ORDER
-# define CONFIG_LIBC_RAND_ORDER 3
-#endif
-
-#ifndef CONFIG_HAVE_DOUBLE
-typedef float float_t;
-#else
-typedef double float_t;
-#endif
-
-/* Values needed by the random number generator */
-
-#define RND1_CONSTK 470001
-#define RND1_CONSTP 999563
-#define RND2_CONSTK1 366528
-#define RND2_CONSTK2 508531
-#define RND2_CONSTP 998917
-#define RND3_CONSTK1 360137
-#define RND3_CONSTK2 519815
-#define RND3_CONSTK3 616087
-#define RND3_CONSTP 997783
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-/* First order congruential generators */
-
-static inline unsigned long fgenerate1(FAR unsigned long *seed);
-#if (CONFIG_LIBC_RAND_ORDER == 1)
-static float_t frand1(FAR unsigned long *seed);
-#endif
-
-/* Second order congruential generators */
-
-#if (CONFIG_LIBC_RAND_ORDER > 1)
-static inline unsigned long fgenerate2(void);
-#if (CONFIG_LIBC_RAND_ORDER == 2)
-static float_t frand2(void);
-#endif
-
-/* Third order congruential generators */
-
-#if (CONFIG_LIBC_RAND_ORDER > 2)
-static inline unsigned long fgenerate3(void);
-static float_t frand3(void);
-#endif
-#endif
-
/****************************************************************************
* Private Data
****************************************************************************/
-static unsigned long g_randint1;
-#if (CONFIG_LIBC_RAND_ORDER > 1)
-static unsigned long g_randint2;
-#if (CONFIG_LIBC_RAND_ORDER > 2)
-static unsigned long g_randint3;
-#endif
-#endif
+static uint32_t g_randstate = 1;
/****************************************************************************
* Private Functions
****************************************************************************/
-/* First order congruential generators */
-
-static inline unsigned long fgenerate1(FAR unsigned long *seed)
-{
- unsigned long randint;
-
- /* First order congruential generator. One may be added to the result of
- * the generated value to avoid the value zero. This would be fatal for
- * the first order random number generator.
- */
-
- randint = (RND1_CONSTK * (*seed)) % RND1_CONSTP;
- *seed = (randint == 0 ? 1 : randint);
- return randint;
-}
-
-#if (CONFIG_LIBC_RAND_ORDER == 1)
-static float_t frand1(FAR unsigned long *seed)
-{
- /* First order congruential generator. */
-
- unsigned long randint = fgenerate1(seed);
-
- /* Construct an floating point value in the range from 0.0 up to 1.0 */
-
- return ((float_t)randint) / ((float_t)RND1_CONSTP);
-}
-#endif
-
-/* Second order congruential generators */
-
-#if (CONFIG_LIBC_RAND_ORDER > 1)
-static inline unsigned long fgenerate2(void)
-{
- unsigned long randint;
-
- /* Second order congruential generator. */
-
- randint = (RND2_CONSTK1 * g_randint1 +
- RND2_CONSTK2 * g_randint2) % RND2_CONSTP;
-
- g_randint2 = g_randint1;
- g_randint1 = randint;
-
- /* We cannot permit both values to become zero. That would be fatal for
- * the second order random number generator.
- */
-
- if (g_randint2 == 0 && g_randint1 == 0)
- {
- g_randint2 = 1;
- }
-
- return randint;
-}
-
-#if (CONFIG_LIBC_RAND_ORDER == 2)
-static float_t frand2(void)
-{
- /* Second order congruential generator */
-
- unsigned long randint = fgenerate2();
-
- /* Construct an floating point value in the range from 0.0 up to 1.0 */
-
- return ((float_t)randint) / ((float_t)RND2_CONSTP);
-}
-#endif
-
-/* Third order congruential generators */
+/****************************************************************************
+ * Name: xorshift32
+ *
+ * Description:
+ * Marsaglia's xorshift32 PRNG. Period 2^32 - 1 (about 4.29 billion).
+ * Much better statistical properties than a simple LCG with a small
+ * modulus, while remaining fast (three XOR/shift operations).
+ *
+ ****************************************************************************/
-#if (CONFIG_LIBC_RAND_ORDER > 2)
-static inline unsigned long fgenerate3(void)
+static inline uint32_t xorshift32(FAR uint32_t *state)
{
- unsigned long randint;
-
- /* Third order congruential generator. */
-
- randint = (RND3_CONSTK1 * g_randint1 +
- RND3_CONSTK2 * g_randint2 +
- RND3_CONSTK2 * g_randint3) % RND3_CONSTP;
+ uint32_t x = *state;
- g_randint3 = g_randint2;
- g_randint2 = g_randint1;
- g_randint1 = randint;
-
- /* We cannot permit all three values to become zero. That would be fatal
- * for the third order random number generator.
+ /* State must never be zero, otherwise the generator is stuck.
+ * The seed path (srand / rand_r) already guards against this, but we
+ * check here as well for safety.
*/
- if (g_randint3 == 0 && g_randint2 == 0 && g_randint1 == 0)
+ if (x == 0)
{
- g_randint3 = 1;
+ x = 1;
}
- return randint;
-}
-
-static float_t frand3(void)
-{
- /* Third order congruential generator */
-
- unsigned long randint = fgenerate3();
+ x ^= x << 13;
+ x ^= x >> 17;
+ x ^= x << 5;
- /* Construct an floating point value in the range from 0.0 up to 1.0 */
-
- return ((float_t)randint) / ((float_t)RND3_CONSTP);
+ *state = x;
+ return x;
}
-#endif
-#endif
static unsigned long nrand_r(unsigned long limit,
- FAR unsigned long *seed)
+ FAR uint32_t *state)
{
-#if CONFIG_LIBC_RAND_ORDER > 0
- unsigned long result;
- float_t ratio;
-
- /* Loop to be sure a legal random number is generated */
-
- do
- {
- /* Get a random integer in the range 0.0 - 1.0 */
+ uint32_t randval = xorshift32(state);
-# if (CONFIG_LIBC_RAND_ORDER == 1)
- ratio = frand1(seed);
-# elif (CONFIG_LIBC_RAND_ORDER == 2)
- ratio = frand2();
-# elif (CONFIG_LIBC_RAND_ORDER > 2)
- ratio = frand3();
-#endif
-
- /* Then, produce the return-able value in the requested range */
-
- result = (unsigned long)(((float_t)limit) * ratio);
-
- /* Loop because there is an (unlikely) possibility that rounding
- * could increase the result at the limit value about the limit.
- */
- }
- while (result >= limit);
+ /* Map the 32-bit random value into the range [0, limit).
+ * The modulo bias is negligible for small limits relative to 2^32.
+ */
- return result;
-#else
- return fgenerate1(seed) % limit;
-#endif
+ return (unsigned long)(randval % (uint32_t)limit);
}
/****************************************************************************
@@ -262,21 +93,15 @@ static unsigned long nrand_r(unsigned long limit,
* Name: srand
*
* Description:
- * Seed the congruential random number generator.
+ * Seed the random number generator.
*
****************************************************************************/
void srand(unsigned int seed)
{
- g_randint1 = seed;
-#if (CONFIG_LIBC_RAND_ORDER > 1)
- g_randint2 = seed;
- fgenerate1(&g_randint1);
-#if (CONFIG_LIBC_RAND_ORDER > 2)
- g_randint3 = seed;
- fgenerate2();
-#endif
-#endif
+ /* Avoid a zero state which would make xorshift32 degenerate. */
+
+ g_randstate = (seed == 0) ? 1 : (uint32_t)seed;
}
/****************************************************************************
@@ -289,7 +114,7 @@ void srand(unsigned int seed)
unsigned long nrand(unsigned long limit)
{
- return nrand_r(limit, &g_randint1);
+ return nrand_r(limit, &g_randstate);
}
/****************************************************************************
@@ -308,10 +133,15 @@ unsigned long nrand(unsigned long limit)
int rand_r(FAR unsigned int *seedp)
{
- unsigned long seed = *seedp;
+ uint32_t state = (uint32_t)*seedp;
unsigned long rand;
- rand = nrand_r(INT_MAX, &seed);
- *seedp = (unsigned int)seed;
+ if (state == 0)
+ {
+ state = 1;
+ }
+
+ rand = nrand_r(INT_MAX, &state);
+ *seedp = (unsigned int)state;
return (int)rand;
}