aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2026-04-23 17:57:42 -0300
committerRoberto I <roberto@inf.puc-rio.br>2026-04-23 17:57:42 -0300
commit3228a97c6a953dcf397944161bb64b12f1ff5384 (patch)
tree6497f6f8e93ba3bb381c0b48aed71646fca3f9b0 /ldo.c
parent0c16a42d61d08266033ff63bc5dfade6312b7359 (diff)
downloadlua-3228a97c6a953dcf397944161bb64b12f1ff5384.tar.gz
lua-3228a97c6a953dcf397944161bb64b12f1ff5384.tar.bz2
lua-3228a97c6a953dcf397944161bb64b12f1ff5384.zip
Bug: 'lua_load' does not preserve the stack
'lua_load' does not preserve the stack through the calls to the reader function, as it should. Immediately after the first call (to detect whether chunk is binary) it adds stuff, and it also adds a new table when starting the compilation of each new function.
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/ldo.c b/ldo.c
index 12e0364b..ec360ee8 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1128,28 +1128,54 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
1128} 1128}
1129 1129
1130 1130
1131/*
1132** Before the first call to the reader function, Lua reserves a slot
1133** with a table for anchoring stuff.
1134*/
1131static void f_parser (lua_State *L, void *ud) { 1135static void f_parser (lua_State *L, void *ud) {
1132 LClosure *cl; 1136 LClosure *cl;
1133 struct SParser *p = cast(struct SParser *, ud); 1137 struct SParser *p = cast(struct SParser *, ud);
1134 const char *mode = p->mode ? p->mode : "bt"; 1138 const char *mode = p->mode ? p->mode : "bt";
1135 int c = zgetc(p->z); /* read first character */ 1139 int c;
1140 Table *anchor;
1141 ptrdiff_t otop = savestack(L, L->top.p); /* original top */
1142 luaD_checkstack(L, 2);
1143 anchor = luaH_new(L); /* create the anchor table */
1144 sethvalue2s(L, L->top.p++, anchor); /* anchor the anchor table */
1145 c = zgetc(p->z); /* read first character */
1136 if (c == LUA_SIGNATURE[0]) { 1146 if (c == LUA_SIGNATURE[0]) {
1137 int fixed = 0; 1147 int fixed = 0;
1138 if (strchr(mode, 'B') != NULL) 1148 if (strchr(mode, 'B') != NULL)
1139 fixed = 1; 1149 fixed = 1;
1140 else 1150 else
1141 checkmode(L, mode, "binary"); 1151 checkmode(L, mode, "binary");
1142 cl = luaU_undump(L, p->z, p->name, fixed); 1152 cl = luaU_undump(L, p->z, anchor, p->name, fixed);
1143 } 1153 }
1144 else { 1154 else {
1145 checkmode(L, mode, "text"); 1155 checkmode(L, mode, "text");
1146 cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); 1156 cl = luaY_parser(L, p->z, anchor, &p->buff, &p->dyd, p->name, c);
1147 } 1157 }
1158 L->top.p = restorestack(L, otop); /* restore stack */
1159 setclLvalue2s(L, L->top.p++, cl); /* push closure */
1148 lua_assert(cl->nupvalues == cl->p->sizeupvalues); 1160 lua_assert(cl->nupvalues == cl->p->sizeupvalues);
1149 luaF_initupvals(L, cl); 1161 luaF_initupvals(L, cl);
1150} 1162}
1151 1163
1152 1164
1165/*
1166** Anchor an object in a table in the stack. First, anchor the object
1167** temporarily in the stack, as luaH_set may call an emergency GC.
1168** Then, add it in the table with itself as its key.
1169*/
1170void luaD_anchorobj (lua_State *L, Table *anchor, GCObject *obj) {
1171 setgcovalue(L, s2v(L->top.p++), obj); /* temporary anchor in the stack */
1172 luaH_set(L, anchor, s2v(L->top.p - 1), s2v(L->top.p - 1));
1173 /* Because this is a new key, luaH_set will call the GC barrier, so
1174 we don't need to call the barrier again here */
1175 L->top.p--;
1176}
1177
1178
1153TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name, 1179TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
1154 const char *mode) { 1180 const char *mode) {
1155 struct SParser p; 1181 struct SParser p;