aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2025-03-11 23:04:30 +0100
committerMike Pall <mike>2025-03-11 23:04:30 +0100
commit538a82133ad6fddfd0ca64de167c4aca3bc1a2da (patch)
tree22fd80543291b6b51ba9a6f841719bab7ed7b3bd
parent84cb21ffaf648b472ff3884556e2c413e8abe179 (diff)
downloadluajit-538a82133ad6fddfd0ca64de167c4aca3bc1a2da.tar.gz
luajit-538a82133ad6fddfd0ca64de167c4aca3bc1a2da.tar.bz2
luajit-538a82133ad6fddfd0ca64de167c4aca3bc1a2da.zip
Change handling of nil value markers in template tables.HEADv2.1
Reported by Bernhard M. Wiedemann. #1348 #1155 Fixes from Peter Cawley, Christian Clason, Lewis Russell.
-rw-r--r--src/lj_bcread.c10
-rw-r--r--src/lj_bcwrite.c8
-rw-r--r--src/lj_opt_fold.c6
-rw-r--r--src/lj_opt_mem.c4
-rw-r--r--src/lj_parse.c20
-rw-r--r--src/lj_tab.c1
6 files changed, 24 insertions, 25 deletions
diff --git a/src/lj_bcread.c b/src/lj_bcread.c
index ee7d7c18..55709522 100644
--- a/src/lj_bcread.c
+++ b/src/lj_bcread.c
@@ -179,7 +179,7 @@ static const void *bcread_varinfo(GCproto *pt)
179} 179}
180 180
181/* Read a single constant key/value of a template table. */ 181/* Read a single constant key/value of a template table. */
182static void bcread_ktabk(LexState *ls, TValue *o) 182static void bcread_ktabk(LexState *ls, TValue *o, GCtab *t)
183{ 183{
184 MSize tp = bcread_uleb128(ls); 184 MSize tp = bcread_uleb128(ls);
185 if (tp >= BCDUMP_KTAB_STR) { 185 if (tp >= BCDUMP_KTAB_STR) {
@@ -191,6 +191,8 @@ static void bcread_ktabk(LexState *ls, TValue *o)
191 } else if (tp == BCDUMP_KTAB_NUM) { 191 } else if (tp == BCDUMP_KTAB_NUM) {
192 o->u32.lo = bcread_uleb128(ls); 192 o->u32.lo = bcread_uleb128(ls);
193 o->u32.hi = bcread_uleb128(ls); 193 o->u32.hi = bcread_uleb128(ls);
194 } else if (t && tp == BCDUMP_KTAB_NIL) { /* Restore nil value marker. */
195 settabV(ls->L, o, t);
194 } else { 196 } else {
195 lj_assertLS(tp <= BCDUMP_KTAB_TRUE, "bad constant type %d", tp); 197 lj_assertLS(tp <= BCDUMP_KTAB_TRUE, "bad constant type %d", tp);
196 setpriV(o, ~tp); 198 setpriV(o, ~tp);
@@ -207,15 +209,15 @@ static GCtab *bcread_ktab(LexState *ls)
207 MSize i; 209 MSize i;
208 TValue *o = tvref(t->array); 210 TValue *o = tvref(t->array);
209 for (i = 0; i < narray; i++, o++) 211 for (i = 0; i < narray; i++, o++)
210 bcread_ktabk(ls, o); 212 bcread_ktabk(ls, o, NULL);
211 } 213 }
212 if (nhash) { /* Read hash entries. */ 214 if (nhash) { /* Read hash entries. */
213 MSize i; 215 MSize i;
214 for (i = 0; i < nhash; i++) { 216 for (i = 0; i < nhash; i++) {
215 TValue key; 217 TValue key;
216 bcread_ktabk(ls, &key); 218 bcread_ktabk(ls, &key, NULL);
217 lj_assertLS(!tvisnil(&key), "nil key"); 219 lj_assertLS(!tvisnil(&key), "nil key");
218 bcread_ktabk(ls, lj_tab_set(ls->L, t, &key)); 220 bcread_ktabk(ls, lj_tab_set(ls->L, t, &key), t);
219 } 221 }
220 } 222 }
221 return t; 223 return t;
diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c
index de200ef4..ec6f13c8 100644
--- a/src/lj_bcwrite.c
+++ b/src/lj_bcwrite.c
@@ -71,6 +71,8 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
71 *p++ = BCDUMP_KTAB_NUM; 71 *p++ = BCDUMP_KTAB_NUM;
72 p = lj_strfmt_wuleb128(p, o->u32.lo); 72 p = lj_strfmt_wuleb128(p, o->u32.lo);
73 p = lj_strfmt_wuleb128(p, o->u32.hi); 73 p = lj_strfmt_wuleb128(p, o->u32.hi);
74 } else if (tvistab(o)) { /* Write the nil value marker as a nil. */
75 *p++ = BCDUMP_KTAB_NIL;
74 } else { 76 } else {
75 lj_assertBCW(tvispri(o), "unhandled type %d", itype(o)); 77 lj_assertBCW(tvispri(o), "unhandled type %d", itype(o));
76 *p++ = BCDUMP_KTAB_NIL+~itype(o); 78 *p++ = BCDUMP_KTAB_NIL+~itype(o);
@@ -133,7 +135,7 @@ static void bcwrite_ktab_sorted_hash(BCWriteCtx *ctx, Node *node, MSize nhash)
133 TValue **heap = ctx->heap; 135 TValue **heap = ctx->heap;
134 MSize i = nhash; 136 MSize i = nhash;
135 for (;; node--) { /* Build heap. */ 137 for (;; node--) { /* Build heap. */
136 if (!tvisnil(&node->key)) { 138 if (!tvisnil(&node->val)) {
137 bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key); 139 bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key);
138 if (i == 0) break; 140 if (i == 0) break;
139 } 141 }
@@ -163,7 +165,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
163 MSize i, hmask = t->hmask; 165 MSize i, hmask = t->hmask;
164 Node *node = noderef(t->node); 166 Node *node = noderef(t->node);
165 for (i = 0; i <= hmask; i++) 167 for (i = 0; i <= hmask; i++)
166 nhash += !tvisnil(&node[i].key); 168 nhash += !tvisnil(&node[i].val);
167 } 169 }
168 /* Write number of array slots and hash slots. */ 170 /* Write number of array slots and hash slots. */
169 p = lj_strfmt_wuleb128(p, narray); 171 p = lj_strfmt_wuleb128(p, narray);
@@ -184,7 +186,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
184 } else { 186 } else {
185 MSize i = nhash; 187 MSize i = nhash;
186 for (;; node--) 188 for (;; node--)
187 if (!tvisnil(&node->key)) { 189 if (!tvisnil(&node->val)) {
188 bcwrite_ktabk(ctx, &node->key, 0); 190 bcwrite_ktabk(ctx, &node->key, 0);
189 bcwrite_ktabk(ctx, &node->val, 1); 191 bcwrite_ktabk(ctx, &node->val, 1);
190 if (--i == 0) break; 192 if (--i == 0) break;
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c
index 36aacebb..6fdf4566 100644
--- a/src/lj_opt_fold.c
+++ b/src/lj_opt_fold.c
@@ -2217,9 +2217,11 @@ LJFOLD(HREF TDUP KNUM)
2217LJFOLDF(fwd_href_tdup) 2217LJFOLDF(fwd_href_tdup)
2218{ 2218{
2219 TValue keyv; 2219 TValue keyv;
2220 cTValue *val;
2220 lj_ir_kvalue(J->L, &keyv, fright); 2221 lj_ir_kvalue(J->L, &keyv, fright);
2221 if (lj_tab_get(J->L, ir_ktab(IR(fleft->op1)), &keyv) == niltvg(J2G(J)) && 2222 val = lj_tab_get(J->L, ir_ktab(IR(fleft->op1)), &keyv);
2222 lj_opt_fwd_href_nokey(J)) 2223 /* Check for either nil or the nil value marker in the template table. */
2224 if ((tvisnil(val) || tvistab(val)) && lj_opt_fwd_href_nokey(J))
2223 return lj_ir_kkptr(J, niltvg(J2G(J))); 2225 return lj_ir_kkptr(J, niltvg(J2G(J)));
2224 return NEXTFOLD; 2226 return NEXTFOLD;
2225} 2227}
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c
index 8cacfcfe..6f956b37 100644
--- a/src/lj_opt_mem.c
+++ b/src/lj_opt_mem.c
@@ -233,7 +233,9 @@ static TRef fwd_ahload(jit_State *J, IRRef xref)
233 return lj_ir_knum_u64(J, tv->u64); 233 return lj_ir_knum_u64(J, tv->u64);
234 else if (tvisint(tv)) 234 else if (tvisint(tv))
235 return lj_ir_kint(J, intV(tv)); 235 return lj_ir_kint(J, intV(tv));
236 else if (tvisgcv(tv)) 236 else if (tvistab(tv)) /* Template table nil value marker. */
237 return TREF_NIL;
238 else if (tvisstr(tv))
237 return lj_ir_kstr(J, strV(tv)); 239 return lj_ir_kstr(J, strV(tv));
238 } 240 }
239 /* Othwerwise: don't intern as a constant. */ 241 /* Othwerwise: don't intern as a constant. */
diff --git a/src/lj_parse.c b/src/lj_parse.c
index 70097598..f4116380 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -1725,7 +1725,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
1725 FuncState *fs = ls->fs; 1725 FuncState *fs = ls->fs;
1726 BCLine line = ls->linenumber; 1726 BCLine line = ls->linenumber;
1727 GCtab *t = NULL; 1727 GCtab *t = NULL;
1728 int vcall = 0, needarr = 0, fixt = 0; 1728 int vcall = 0, needarr = 0;
1729 uint32_t narr = 1; /* First array index. */ 1729 uint32_t narr = 1; /* First array index. */
1730 uint32_t nhash = 0; /* Number of hash entries. */ 1730 uint32_t nhash = 0; /* Number of hash entries. */
1731 BCReg freg = fs->freereg; 1731 BCReg freg = fs->freereg;
@@ -1769,9 +1769,10 @@ static void expr_table(LexState *ls, ExpDesc *e)
1769 lj_gc_anybarriert(fs->L, t); 1769 lj_gc_anybarriert(fs->L, t);
1770 if (expr_isk_nojump(&val)) { /* Add const key/value to template table. */ 1770 if (expr_isk_nojump(&val)) { /* Add const key/value to template table. */
1771 expr_kvalue(fs, v, &val); 1771 expr_kvalue(fs, v, &val);
1772 } else { /* Otherwise create dummy string key (avoids lj_tab_newkey). */ 1772 /* Mark nil value with table value itself to preserve the key. */
1773 settabV(fs->L, v, t); /* Preserve key with table itself as value. */ 1773 if (key.k == VKSTR && tvisnil(v)) settabV(fs->L, v, t);
1774 fixt = 1; /* Fix this later, after all resizes. */ 1774 } else { /* Preserve the key for the following non-const store. */
1775 settabV(fs->L, v, t);
1775 goto nonconst; 1776 goto nonconst;
1776 } 1777 }
1777 } else { 1778 } else {
@@ -1813,17 +1814,6 @@ static void expr_table(LexState *ls, ExpDesc *e)
1813 } else { 1814 } else {
1814 if (needarr && t->asize < narr) 1815 if (needarr && t->asize < narr)
1815 lj_tab_reasize(fs->L, t, narr-1); 1816 lj_tab_reasize(fs->L, t, narr-1);
1816 if (fixt) { /* Fix value for dummy keys in template table. */
1817 Node *node = noderef(t->node);
1818 uint32_t i, hmask = t->hmask;
1819 for (i = 0; i <= hmask; i++) {
1820 Node *n = &node[i];
1821 if (tvistab(&n->val)) {
1822 lj_assertFS(tabV(&n->val) == t, "bad dummy key in template table");
1823 setnilV(&n->val); /* Turn value into nil. */
1824 }
1825 }
1826 }
1827 lj_gc_check(fs->L); 1817 lj_gc_check(fs->L);
1828 } 1818 }
1829} 1819}
diff --git a/src/lj_tab.c b/src/lj_tab.c
index 2d080552..62e33611 100644
--- a/src/lj_tab.c
+++ b/src/lj_tab.c
@@ -194,6 +194,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
194 Node *next = nextnode(kn); 194 Node *next = nextnode(kn);
195 /* Don't use copyTV here, since it asserts on a copy of a dead key. */ 195 /* Don't use copyTV here, since it asserts on a copy of a dead key. */
196 n->val = kn->val; n->key = kn->key; 196 n->val = kn->val; n->key = kn->key;
197 if (tvistab(&n->val)) setnilV(&n->val); /* Replace nil value marker. */
197 setmref(n->next, next == NULL? next : (Node *)((char *)next + d)); 198 setmref(n->next, next == NULL? next : (Node *)((char *)next + d));
198 } 199 }
199 } 200 }