aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-03-29 15:10:50 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-03-29 15:10:50 -0300
commit88a50ffa715483e7187c0d7d6caaf708ebacf756 (patch)
treeabd032613bb066ebf4b4d3d2cb2e031347945c0a
parent86a8e74824b3ec7918e3dbeaff222bb1ea1ec22f (diff)
downloadlua-88a50ffa715483e7187c0d7d6caaf708ebacf756.tar.gz
lua-88a50ffa715483e7187c0d7d6caaf708ebacf756.tar.bz2
lua-88a50ffa715483e7187c0d7d6caaf708ebacf756.zip
Fixed dangling 'StkId' in 'luaV_finishget'
Bug introduced in 05932567.
Diffstat (limited to '')
-rw-r--r--lobject.h2
-rw-r--r--ltm.c43
-rw-r--r--ltm.h4
-rw-r--r--lvm.c10
-rw-r--r--testes/events.lua9
5 files changed, 42 insertions, 26 deletions
diff --git a/lobject.h b/lobject.h
index b42539cf..169512f8 100644
--- a/lobject.h
+++ b/lobject.h
@@ -256,6 +256,8 @@ typedef union {
256 256
257 257
258#define l_isfalse(o) (ttisfalse(o) || ttisnil(o)) 258#define l_isfalse(o) (ttisfalse(o) || ttisnil(o))
259#define tagisfalse(t) ((t) == LUA_VFALSE || novariant(t) == LUA_TNIL)
260
259 261
260 262
261#define setbfvalue(obj) settt_(obj, LUA_VFALSE) 263#define setbfvalue(obj) settt_(obj, LUA_VFALSE)
diff --git a/ltm.c b/ltm.c
index c28f9122..236f3bb4 100644
--- a/ltm.c
+++ b/ltm.c
@@ -116,8 +116,8 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
116} 116}
117 117
118 118
119void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, 119int luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
120 const TValue *p2, StkId res) { 120 const TValue *p2, StkId res) {
121 ptrdiff_t result = savestack(L, res); 121 ptrdiff_t result = savestack(L, res);
122 StkId func = L->top.p; 122 StkId func = L->top.p;
123 setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ 123 setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
@@ -131,6 +131,7 @@ void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
131 luaD_callnoyield(L, func, 1); 131 luaD_callnoyield(L, func, 1);
132 res = restorestack(L, result); 132 res = restorestack(L, result);
133 setobjs2s(L, res, --L->top.p); /* move result to its place */ 133 setobjs2s(L, res, --L->top.p); /* move result to its place */
134 return ttypetag(s2v(res)); /* return tag of the result */
134} 135}
135 136
136 137
@@ -139,15 +140,16 @@ static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
139 const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ 140 const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
140 if (notm(tm)) 141 if (notm(tm))
141 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ 142 tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
142 if (notm(tm)) return 0; 143 if (notm(tm))
143 luaT_callTMres(L, tm, p1, p2, res); 144 return -1; /* tag method not found */
144 return 1; 145 else /* call tag method and return the tag of the result */
146 return luaT_callTMres(L, tm, p1, p2, res);
145} 147}
146 148
147 149
148void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 150void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
149 StkId res, TMS event) { 151 StkId res, TMS event) {
150 if (l_unlikely(!callbinTM(L, p1, p2, res, event))) { 152 if (l_unlikely(callbinTM(L, p1, p2, res, event) < 0)) {
151 switch (event) { 153 switch (event) {
152 case TM_BAND: case TM_BOR: case TM_BXOR: 154 case TM_BAND: case TM_BOR: case TM_BXOR:
153 case TM_SHL: case TM_SHR: case TM_BNOT: { 155 case TM_SHL: case TM_SHR: case TM_BNOT: {
@@ -164,11 +166,14 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
164} 166}
165 167
166 168
169/*
170** The use of 'p1' after 'callbinTM' is safe because, when a tag
171** method is not found, 'callbinTM' cannot change the stack.
172*/
167void luaT_tryconcatTM (lua_State *L) { 173void luaT_tryconcatTM (lua_State *L) {
168 StkId top = L->top.p; 174 StkId p1 = L->top.p - 2; /* first argument */
169 if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, 175 if (l_unlikely(callbinTM(L, s2v(p1), s2v(p1 + 1), p1, TM_CONCAT) < 0))
170 TM_CONCAT))) 176 luaG_concaterror(L, s2v(p1), s2v(p1 + 1));
171 luaG_concaterror(L, s2v(top - 2), s2v(top - 1));
172} 177}
173 178
174 179
@@ -200,17 +205,17 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
200*/ 205*/
201int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, 206int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
202 TMS event) { 207 TMS event) {
203 if (callbinTM(L, p1, p2, L->top.p, event)) /* try original event */ 208 int tag = callbinTM(L, p1, p2, L->top.p, event); /* try original event */
204 return !l_isfalse(s2v(L->top.p)); 209 if (tag >= 0) /* found tag method? */
210 return !tagisfalse(tag);
205#if defined(LUA_COMPAT_LT_LE) 211#if defined(LUA_COMPAT_LT_LE)
206 else if (event == TM_LE) { 212 else if (event == TM_LE) {
207 /* try '!(p2 < p1)' for '(p1 <= p2)' */ 213 /* try '!(p2 < p1)' for '(p1 <= p2)' */
208 L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ 214 L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */
209 if (callbinTM(L, p2, p1, L->top.p, TM_LT)) { 215 tag = callbinTM(L, p2, p1, L->top.p, TM_LT);
210 L->ci->callstatus ^= CIST_LEQ; /* clear mark */ 216 L->ci->callstatus ^= CIST_LEQ; /* clear mark */
211 return l_isfalse(s2v(L->top.p)); 217 if (tag >= 0) /* found tag method? */
212 } 218 return tagisfalse(tag);
213 /* else error will remove this 'ci'; no need to clear mark */
214 } 219 }
215#endif 220#endif
216 luaG_ordererror(L, p1, p2); /* no metamethod found */ 221 luaG_ordererror(L, p1, p2); /* no metamethod found */
diff --git a/ltm.h b/ltm.h
index 3c49713a..df05b741 100644
--- a/ltm.h
+++ b/ltm.h
@@ -81,8 +81,8 @@ LUAI_FUNC void luaT_init (lua_State *L);
81 81
82LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, 82LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
83 const TValue *p2, const TValue *p3); 83 const TValue *p2, const TValue *p3);
84LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f, 84LUAI_FUNC int luaT_callTMres (lua_State *L, const TValue *f,
85 const TValue *p1, const TValue *p2, StkId p3); 85 const TValue *p1, const TValue *p2, StkId p3);
86LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 86LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
87 StkId res, TMS event); 87 StkId res, TMS event);
88LUAI_FUNC void luaT_tryconcatTM (lua_State *L); 88LUAI_FUNC void luaT_tryconcatTM (lua_State *L);
diff --git a/lvm.c b/lvm.c
index cfa9961b..37023afb 100644
--- a/lvm.c
+++ b/lvm.c
@@ -308,8 +308,8 @@ int luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
308 /* else will try the metamethod */ 308 /* else will try the metamethod */
309 } 309 }
310 if (ttisfunction(tm)) { /* is metamethod a function? */ 310 if (ttisfunction(tm)) { /* is metamethod a function? */
311 luaT_callTMres(L, tm, t, key, val); /* call it */ 311 tag = luaT_callTMres(L, tm, t, key, val); /* call it */
312 return ttypetag(s2v(val)); 312 return tag; /* return tag of the result */
313 } 313 }
314 t = tm; /* else try to access 'tm[key]' */ 314 t = tm; /* else try to access 'tm[key]' */
315 luaV_fastget(t, key, s2v(val), luaH_get, tag); 315 luaV_fastget(t, key, s2v(val), luaH_get, tag);
@@ -606,8 +606,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
606 if (tm == NULL) /* no TM? */ 606 if (tm == NULL) /* no TM? */
607 return 0; /* objects are different */ 607 return 0; /* objects are different */
608 else { 608 else {
609 luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ 609 int tag = luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */
610 return !l_isfalse(s2v(L->top.p)); 610 return !tagisfalse(tag);
611 } 611 }
612} 612}
613 613
@@ -914,7 +914,7 @@ void luaV_finishOp (lua_State *L) {
914 914
915/* 915/*
916** Auxiliary function for arithmetic operations over floats and others 916** Auxiliary function for arithmetic operations over floats and others
917** with two register operands. 917** with two operands.
918*/ 918*/
919#define op_arithf_aux(L,v1,v2,fop) { \ 919#define op_arithf_aux(L,v1,v2,fop) { \
920 lua_Number n1; lua_Number n2; \ 920 lua_Number n1; lua_Number n2; \
diff --git a/testes/events.lua b/testes/events.lua
index 8d8563b9..5360ac30 100644
--- a/testes/events.lua
+++ b/testes/events.lua
@@ -248,6 +248,15 @@ end
248test(Op(1), Op(2), Op(3)) 248test(Op(1), Op(2), Op(3))
249 249
250 250
251do -- test nil as false
252 local x = setmetatable({12}, {__eq= function (a,b)
253 return a[1] == b[1] or nil
254 end})
255 assert(not (x == {20}))
256 assert(x == {12})
257end
258
259
251-- test `partial order' 260-- test `partial order'
252 261
253local function rawSet(x) 262local function rawSet(x)