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;
 }

Reply via email to