Skip to content

Commit 6d6c9b3

Browse files
xiaocangagentzh
authored andcommitted
bugfix: jit.prngstate() did not allow integer arg which broke backward compatibility.
1 parent 70f8877 commit 6d6c9b3

File tree

4 files changed

+61
-17
lines changed

4 files changed

+61
-17
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,20 @@ When the `state` argument is non-nil, it is expected to be an array of up to 8
153153
unsigned Lua numbers, each with value less than 2\*\*32-1. This will set the
154154
current PRNG state and return the state that was overridden.
155155

156+
**Note:** For backward compatibility, `state` argument can also be an unsigned
157+
Lua number less than 2\*\*32-1.
158+
159+
**Note:** When the `state` argument is an array and less than 8 numbers, or the
160+
`state` is a number, the remaining positions are filled with zeros.
161+
156162
Usage:
157163

158164
```lua
159165
local state = jit.prngstate()
160166
local oldstate = jit.prngstate{ a, b, c, ... }
167+
168+
jit.prngstate(32) -- {32, 0, 0, 0, 0, 0, 0, 0}
169+
jit.prngstate{432, 23, 50} -- {432, 23, 50, 0, 0, 0, 0, 0}
161170
```
162171

163172
**Note:** This API has no effect if LuaJIT is compiled with

src/lib_jit.c

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,28 +164,38 @@ LJLIB_CF(jit_prngstate)
164164

165165
/* We need to set new state using the input array. */
166166
if (L->base < L->top && !tvisnil(L->base)) {
167-
GCtab *t = lj_lib_checktab(L, 1);
168167
PRNGState prng;
169-
int i = 1, len = lj_tab_len(t);
168+
if (tvisnumber(L->base)) {
169+
TValue *o = L->base;
170170

171-
/* The input array must have at most 8 elements. */
172-
if (len > 8)
173-
lj_err_arg(L, 1, LJ_ERR_PRNGSTATE);
171+
if (!tvisint(o) && ((double)(uint32_t)numV(o) != numV(o)))
172+
lj_err_arg(L, 1, LJ_ERR_PRNGSTATE);
174173

175-
for (i = 1; i <= len; i++) {
176-
cTValue *v = lj_tab_getint(t, i);
174+
prng.u[0] = numberVint(o);
175+
for (i = 1; i < 4; i++)
176+
prng.u[i] = 0;
177+
} else {
178+
GCtab *t = lj_lib_checktab(L, 1);
179+
int i = 1, len = lj_tab_len(t);
177180

178-
if (!tvisint(v) && (!tvisnum(v) || (double)(uint32_t)numV(v) != numV(v)))
181+
/* The input array must have at most 8 elements. */
182+
if (len > 8)
179183
lj_err_arg(L, 1, LJ_ERR_PRNGSTATE);
180184

181-
if (i & 1)
182-
prng.u[(i-1)/2] = numberVint(v);
183-
else
184-
prng.u[(i-1)/2] = prng.u[(i-1)/2] | ((uint64_t)numberVint(v) << 32);
185-
}
185+
for (i = 1; i <= len; i++) {
186+
cTValue *v = lj_tab_getint(t, i);
187+
188+
if (!tvisint(v) && (!tvisnum(v) || (double)(uint32_t)numV(v) != numV(v)))
189+
lj_err_arg(L, 1, LJ_ERR_PRNGSTATE);
186190

187-
for (i /= 2; i < 4; i++)
188-
prng.u[i] = 0;
191+
if (i & 1)
192+
prng.u[(i-1)/2] = numberVint(v);
193+
else
194+
prng.u[(i-1)/2] = prng.u[(i-1)/2] | ((uint64_t)numberVint(v) << 32);
195+
}
196+
for (i /= 2; i < 4; i++)
197+
prng.u[i] = 0;
198+
}
189199

190200
/* Re-initialize the JIT prng. */
191201
J->prng = prng;

src/lj_errmsg.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ ERRDEF(NOJIT, "no JIT compiler for this architecture (yet)")
108108
ERRDEF(NOJIT, "JIT compiler permanently disabled by build option")
109109
#endif
110110
ERRDEF(JITOPT, "unknown or malformed optimization flag " LUA_QS)
111-
ERRDEF(PRNGSTATE, "PRNG state must be an array with up to 8 integers")
111+
ERRDEF(PRNGSTATE, "PRNG state must be an array with up to 8 integers "
112+
"or an integer")
112113

113114
/* Lexer/parser errors. */
114115
ERRDEF(XMODE, "attempt to load chunk with wrong mode")

t/prngstate.t

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ print_array(jit.prngstate({423,432,432,423,56,867,35,5347,452}))
3232
423 432 432 423 56 867 35 5347
3333
--- jv
3434
--- err
35-
bad argument #1 to 'prngstate' (PRNG state must be an array with up to 8 integers)
35+
bad argument #1 to 'prngstate' (PRNG state must be an array with up to 8 integers or an integer)
3636
--- exit: 1
3737
3838
@@ -50,3 +50,27 @@ ok
5050
--- jv
5151
--- err eval
5252
qr/trace too short at jit\.prngstate/
53+
54+
55+
56+
=== TEST 3: PRNG state can be an integer
57+
--- lua
58+
function print_array(a)
59+
local out = a[1]
60+
for i=2,#a do
61+
out = out.." "..tostring(a[i])
62+
end
63+
print(out)
64+
end
65+
66+
jit.prngstate(0)
67+
print_array(jit.prngstate(30))
68+
print_array(jit.prngstate(32))
69+
print_array(jit.prngstate(4294967296)) -- 2 ** 32
70+
--- out
71+
0 0 0 0 0 0 0 0
72+
30 0 0 0 0 0 0 0
73+
--- jv
74+
--- err
75+
bad argument #1 to 'prngstate' (PRNG state must be an array with up to 8 integers or an integer)
76+
--- exit: 1

0 commit comments

Comments
 (0)