Skip to content

Instantly share code, notes, and snippets.

@rfl890
Created January 24, 2024 23:15

Revisions

  1. rfl890 created this gist Jan 24, 2024.
    97 changes: 97 additions & 0 deletions 0001-Update-PRNG.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    From c796842c4aaaca1b640a1fd0e03c9d8e85f571c8 Mon Sep 17 00:00:00 2001
    From: rfl890 <87506407+rfl890@users.noreply.github.com>
    Date: Wed, 24 Jan 2024 18:14:16 -0500
    Subject: [PATCH] Update PRNG

    ---
    src/lib_math.c | 2 +-
    src/lj_prng.c | 43 ++++++++++++++++++++++---------------------
    2 files changed, 23 insertions(+), 22 deletions(-)

    diff --git a/src/lib_math.c b/src/lib_math.c
    index 4539f804..5ca674f6 100644
    --- a/src/lib_math.c
    +++ b/src/lib_math.c
    @@ -194,7 +194,7 @@ LJLIB_CF(math_randomseed)
    LUALIB_API int luaopen_math(lua_State *L)
    {
    PRNGState *rs = (PRNGState *)lua_newuserdata(L, sizeof(PRNGState));
    - lj_prng_seed_fixed(rs);
    + lj_prng_seed_secure(rs);
    LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
    return 1;
    }
    diff --git a/src/lj_prng.c b/src/lj_prng.c
    index 326b41e6..1697a304 100644
    --- a/src/lj_prng.c
    +++ b/src/lj_prng.c
    @@ -17,10 +17,7 @@

    /* -- PRNG step function -------------------------------------------------- */

    -/* This implements a Tausworthe PRNG with period 2^223. Based on:
    -** Tables of maximally-equidistributed combined LFSR generators,
    -** Pierre L'Ecuyer, 1991, table 3, 1st entry.
    -** Full-period ME-CF generator with L=64, J=4, k=223, N1=49.
    +/* This implements an Xoshiro256** PRNG with period 2^256.
    **
    ** Important note: This PRNG is NOT suitable for cryptographic use!
    **
    @@ -31,33 +28,37 @@
    ** the difficulty for various attacks on the VM.
    */

    -/* Update generator i and compute a running xor of all states. */
    -#define TW223_GEN(rs, z, r, i, k, q, s) \
    - z = rs->u[i]; \
    - z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
    - r ^= z; rs->u[i] = z;
    +static LJ_AINLINE uint64_t rotl(const uint64_t x, int k) {
    + return (x << k) | (x >> (64 - k));
    +}
    +
    +static uint64_t xs256(uint64_t *s) {
    + const uint64_t result = rotl(s[1] * 5, 7) * 9;
    +
    + const uint64_t t = s[1] << 17;
    +
    + s[2] ^= s[0];
    + s[3] ^= s[1];
    + s[1] ^= s[2];
    + s[0] ^= s[3];

    -#define TW223_STEP(rs, z, r) \
    - TW223_GEN(rs, z, r, 0, 63, 31, 18) \
    - TW223_GEN(rs, z, r, 1, 58, 19, 28) \
    - TW223_GEN(rs, z, r, 2, 55, 24, 7) \
    - TW223_GEN(rs, z, r, 3, 47, 21, 8)
    + s[2] ^= t;
    +
    + s[3] = rotl(s[3], 45);
    +
    + return result;
    +}

    /* PRNG step function with uint64_t result. */
    LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs)
    {
    - uint64_t z, r = 0;
    - TW223_STEP(rs, z, r)
    - return r;
    + return xs256(rs->u);
    }

    /* PRNG step function with double in uint64_t result. */
    LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs)
    {
    - uint64_t z, r = 0;
    - TW223_STEP(rs, z, r)
    - /* Returns a double bit pattern in the range 1.0 <= d < 2.0. */
    - return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000);
    + return (xs256(rs->u) & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000);
    }

    /* Condition seed: ensure k[i] MSB of u[i] are non-zero. */
    --
    2.43.0.windows.1