diff options
| author | Mike Pall <mike> | 2025-03-11 23:04:30 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2025-03-11 23:04:30 +0100 |
| commit | 538a82133ad6fddfd0ca64de167c4aca3bc1a2da (patch) | |
| tree | 22fd80543291b6b51ba9a6f841719bab7ed7b3bd | |
| parent | 84cb21ffaf648b472ff3884556e2c413e8abe179 (diff) | |
| download | luajit-538a82133ad6fddfd0ca64de167c4aca3bc1a2da.tar.gz luajit-538a82133ad6fddfd0ca64de167c4aca3bc1a2da.tar.bz2 luajit-538a82133ad6fddfd0ca64de167c4aca3bc1a2da.zip | |
Change handling of nil value markers in template tables.
Reported by Bernhard M. Wiedemann. #1348 #1155
Fixes from Peter Cawley, Christian Clason, Lewis Russell.
| -rw-r--r-- | src/lj_bcread.c | 10 | ||||
| -rw-r--r-- | src/lj_bcwrite.c | 8 | ||||
| -rw-r--r-- | src/lj_opt_fold.c | 6 | ||||
| -rw-r--r-- | src/lj_opt_mem.c | 4 | ||||
| -rw-r--r-- | src/lj_parse.c | 20 | ||||
| -rw-r--r-- | src/lj_tab.c | 1 |
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. */ |
| 182 | static void bcread_ktabk(LexState *ls, TValue *o) | 182 | static 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) | |||
| 2217 | LJFOLDF(fwd_href_tdup) | 2217 | LJFOLDF(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 | } |
