diff options
Diffstat (limited to 'src/lj_bcread.c')
-rw-r--r-- | src/lj_bcread.c | 144 |
1 files changed, 62 insertions, 82 deletions
diff --git a/src/lj_bcread.c b/src/lj_bcread.c index b88794eb..1585272f 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "lj_obj.h" | 9 | #include "lj_obj.h" |
10 | #include "lj_gc.h" | 10 | #include "lj_gc.h" |
11 | #include "lj_err.h" | 11 | #include "lj_err.h" |
12 | #include "lj_buf.h" | ||
12 | #include "lj_str.h" | 13 | #include "lj_str.h" |
13 | #include "lj_tab.h" | 14 | #include "lj_tab.h" |
14 | #include "lj_bc.h" | 15 | #include "lj_bc.h" |
@@ -20,6 +21,7 @@ | |||
20 | #include "lj_lex.h" | 21 | #include "lj_lex.h" |
21 | #include "lj_bcdump.h" | 22 | #include "lj_bcdump.h" |
22 | #include "lj_state.h" | 23 | #include "lj_state.h" |
24 | #include "lj_strfmt.h" | ||
23 | 25 | ||
24 | /* Reuse some lexer fields for our own purposes. */ | 26 | /* Reuse some lexer fields for our own purposes. */ |
25 | #define bcread_flags(ls) ls->level | 27 | #define bcread_flags(ls) ls->level |
@@ -38,85 +40,74 @@ static LJ_NOINLINE void bcread_error(LexState *ls, ErrMsg em) | |||
38 | const char *name = ls->chunkarg; | 40 | const char *name = ls->chunkarg; |
39 | if (*name == BCDUMP_HEAD1) name = "(binary)"; | 41 | if (*name == BCDUMP_HEAD1) name = "(binary)"; |
40 | else if (*name == '@' || *name == '=') name++; | 42 | else if (*name == '@' || *name == '=') name++; |
41 | lj_str_pushf(L, "%s: %s", name, err2msg(em)); | 43 | lj_strfmt_pushf(L, "%s: %s", name, err2msg(em)); |
42 | lj_err_throw(L, LUA_ERRSYNTAX); | 44 | lj_err_throw(L, LUA_ERRSYNTAX); |
43 | } | 45 | } |
44 | 46 | ||
45 | /* Resize input buffer. */ | 47 | /* Refill buffer. */ |
46 | static void bcread_resize(LexState *ls, MSize len) | ||
47 | { | ||
48 | if (ls->sb.sz < len) { | ||
49 | MSize sz = ls->sb.sz * 2; | ||
50 | while (len > sz) sz = sz * 2; | ||
51 | lj_str_resizebuf(ls->L, &ls->sb, sz); | ||
52 | /* Caveat: this may change ls->sb.buf which may affect ls->p. */ | ||
53 | } | ||
54 | } | ||
55 | |||
56 | /* Refill buffer if needed. */ | ||
57 | static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need) | 48 | static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need) |
58 | { | 49 | { |
59 | lua_assert(len != 0); | 50 | lua_assert(len != 0); |
60 | if (len > LJ_MAX_MEM || ls->current < 0) | 51 | if (len > LJ_MAX_BUF || ls->c < 0) |
61 | bcread_error(ls, LJ_ERR_BCBAD); | 52 | bcread_error(ls, LJ_ERR_BCBAD); |
62 | do { | 53 | do { |
63 | const char *buf; | 54 | const char *buf; |
64 | size_t size; | 55 | size_t sz; |
65 | if (ls->n) { /* Copy remainder to buffer. */ | 56 | char *p = sbufB(&ls->sb); |
66 | if (ls->sb.n) { /* Move down in buffer. */ | 57 | MSize n = (MSize)(ls->pe - ls->p); |
67 | lua_assert(ls->p + ls->n == ls->sb.buf + ls->sb.n); | 58 | if (n) { /* Copy remainder to buffer. */ |
68 | if (ls->n != ls->sb.n) | 59 | if (sbuflen(&ls->sb)) { /* Move down in buffer. */ |
69 | memmove(ls->sb.buf, ls->p, ls->n); | 60 | lua_assert(ls->pe == sbufP(&ls->sb)); |
61 | if (ls->p != p) memmove(p, ls->p, n); | ||
70 | } else { /* Copy from buffer provided by reader. */ | 62 | } else { /* Copy from buffer provided by reader. */ |
71 | bcread_resize(ls, len); | 63 | p = lj_buf_need(&ls->sb, len); |
72 | memcpy(ls->sb.buf, ls->p, ls->n); | 64 | memcpy(p, ls->p, n); |
73 | } | 65 | } |
74 | ls->p = ls->sb.buf; | 66 | ls->p = p; |
67 | ls->pe = p + n; | ||
75 | } | 68 | } |
76 | ls->sb.n = ls->n; | 69 | setsbufP(&ls->sb, p + n); |
77 | buf = ls->rfunc(ls->L, ls->rdata, &size); /* Get more data from reader. */ | 70 | buf = ls->rfunc(ls->L, ls->rdata, &sz); /* Get more data from reader. */ |
78 | if (buf == NULL || size == 0) { /* EOF? */ | 71 | if (buf == NULL || sz == 0) { /* EOF? */ |
79 | if (need) bcread_error(ls, LJ_ERR_BCBAD); | 72 | if (need) bcread_error(ls, LJ_ERR_BCBAD); |
80 | ls->current = -1; /* Only bad if we get called again. */ | 73 | ls->c = -1; /* Only bad if we get called again. */ |
81 | break; | 74 | break; |
82 | } | 75 | } |
83 | if (size >= LJ_MAX_MEM - ls->sb.n) lj_err_mem(ls->L); | 76 | if (sz >= LJ_MAX_BUF - n) lj_err_mem(ls->L); |
84 | if (ls->sb.n) { /* Append to buffer. */ | 77 | if (n) { /* Append to buffer. */ |
85 | MSize n = ls->sb.n + (MSize)size; | 78 | n += (MSize)sz; |
86 | bcread_resize(ls, n < len ? len : n); | 79 | p = lj_buf_need(&ls->sb, n < len ? len : n); |
87 | memcpy(ls->sb.buf + ls->sb.n, buf, size); | 80 | memcpy(sbufP(&ls->sb), buf, sz); |
88 | ls->n = ls->sb.n = n; | 81 | setsbufP(&ls->sb, p + n); |
89 | ls->p = ls->sb.buf; | 82 | ls->p = p; |
83 | ls->pe = p + n; | ||
90 | } else { /* Return buffer provided by reader. */ | 84 | } else { /* Return buffer provided by reader. */ |
91 | ls->n = (MSize)size; | ||
92 | ls->p = buf; | 85 | ls->p = buf; |
86 | ls->pe = buf + sz; | ||
93 | } | 87 | } |
94 | } while (ls->n < len); | 88 | } while ((MSize)(ls->pe - ls->p) < len); |
95 | } | 89 | } |
96 | 90 | ||
97 | /* Need a certain number of bytes. */ | 91 | /* Need a certain number of bytes. */ |
98 | static LJ_AINLINE void bcread_need(LexState *ls, MSize len) | 92 | static LJ_AINLINE void bcread_need(LexState *ls, MSize len) |
99 | { | 93 | { |
100 | if (LJ_UNLIKELY(ls->n < len)) | 94 | if (LJ_UNLIKELY((MSize)(ls->pe - ls->p) < len)) |
101 | bcread_fill(ls, len, 1); | 95 | bcread_fill(ls, len, 1); |
102 | } | 96 | } |
103 | 97 | ||
104 | /* Want to read up to a certain number of bytes, but may need less. */ | 98 | /* Want to read up to a certain number of bytes, but may need less. */ |
105 | static LJ_AINLINE void bcread_want(LexState *ls, MSize len) | 99 | static LJ_AINLINE void bcread_want(LexState *ls, MSize len) |
106 | { | 100 | { |
107 | if (LJ_UNLIKELY(ls->n < len)) | 101 | if (LJ_UNLIKELY((MSize)(ls->pe - ls->p) < len)) |
108 | bcread_fill(ls, len, 0); | 102 | bcread_fill(ls, len, 0); |
109 | } | 103 | } |
110 | 104 | ||
111 | #define bcread_dec(ls) check_exp(ls->n > 0, ls->n--) | ||
112 | #define bcread_consume(ls, len) check_exp(ls->n >= (len), ls->n -= (len)) | ||
113 | |||
114 | /* Return memory block from buffer. */ | 105 | /* Return memory block from buffer. */ |
115 | static uint8_t *bcread_mem(LexState *ls, MSize len) | 106 | static LJ_AINLINE uint8_t *bcread_mem(LexState *ls, MSize len) |
116 | { | 107 | { |
117 | uint8_t *p = (uint8_t *)ls->p; | 108 | uint8_t *p = (uint8_t *)ls->p; |
118 | bcread_consume(ls, len); | 109 | ls->p += len; |
119 | ls->p = (char *)p + len; | 110 | lua_assert(ls->p <= ls->pe); |
120 | return p; | 111 | return p; |
121 | } | 112 | } |
122 | 113 | ||
@@ -129,25 +120,15 @@ static void bcread_block(LexState *ls, void *q, MSize len) | |||
129 | /* Read byte from buffer. */ | 120 | /* Read byte from buffer. */ |
130 | static LJ_AINLINE uint32_t bcread_byte(LexState *ls) | 121 | static LJ_AINLINE uint32_t bcread_byte(LexState *ls) |
131 | { | 122 | { |
132 | bcread_dec(ls); | 123 | lua_assert(ls->p < ls->pe); |
133 | return (uint32_t)(uint8_t)*ls->p++; | 124 | return (uint32_t)(uint8_t)*ls->p++; |
134 | } | 125 | } |
135 | 126 | ||
136 | /* Read ULEB128 value from buffer. */ | 127 | /* Read ULEB128 value from buffer. */ |
137 | static uint32_t bcread_uleb128(LexState *ls) | 128 | static LJ_AINLINE uint32_t bcread_uleb128(LexState *ls) |
138 | { | 129 | { |
139 | const uint8_t *p = (const uint8_t *)ls->p; | 130 | uint32_t v = lj_buf_ruleb128(&ls->p); |
140 | uint32_t v = *p++; | 131 | lua_assert(ls->p <= ls->pe); |
141 | if (LJ_UNLIKELY(v >= 0x80)) { | ||
142 | int sh = 0; | ||
143 | v &= 0x7f; | ||
144 | do { | ||
145 | v |= ((*p & 0x7f) << (sh += 7)); | ||
146 | bcread_dec(ls); | ||
147 | } while (*p++ >= 0x80); | ||
148 | } | ||
149 | bcread_dec(ls); | ||
150 | ls->p = (char *)p; | ||
151 | return v; | 132 | return v; |
152 | } | 133 | } |
153 | 134 | ||
@@ -161,11 +142,10 @@ static uint32_t bcread_uleb128_33(LexState *ls) | |||
161 | v &= 0x3f; | 142 | v &= 0x3f; |
162 | do { | 143 | do { |
163 | v |= ((*p & 0x7f) << (sh += 7)); | 144 | v |= ((*p & 0x7f) << (sh += 7)); |
164 | bcread_dec(ls); | ||
165 | } while (*p++ >= 0x80); | 145 | } while (*p++ >= 0x80); |
166 | } | 146 | } |
167 | bcread_dec(ls); | ||
168 | ls->p = (char *)p; | 147 | ls->p = (char *)p; |
148 | lua_assert(ls->p <= ls->pe); | ||
169 | return v; | 149 | return v; |
170 | } | 150 | } |
171 | 151 | ||
@@ -213,7 +193,7 @@ static void bcread_ktabk(LexState *ls, TValue *o) | |||
213 | o->u32.hi = bcread_uleb128(ls); | 193 | o->u32.hi = bcread_uleb128(ls); |
214 | } else { | 194 | } else { |
215 | lua_assert(tp <= BCDUMP_KTAB_TRUE); | 195 | lua_assert(tp <= BCDUMP_KTAB_TRUE); |
216 | setitype(o, ~tp); | 196 | setpriV(o, ~tp); |
217 | } | 197 | } |
218 | } | 198 | } |
219 | 199 | ||
@@ -327,25 +307,13 @@ static void bcread_uv(LexState *ls, GCproto *pt, MSize sizeuv) | |||
327 | } | 307 | } |
328 | 308 | ||
329 | /* Read a prototype. */ | 309 | /* Read a prototype. */ |
330 | static GCproto *bcread_proto(LexState *ls) | 310 | GCproto *lj_bcread_proto(LexState *ls) |
331 | { | 311 | { |
332 | GCproto *pt; | 312 | GCproto *pt; |
333 | MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; | 313 | MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; |
334 | MSize ofsk, ofsuv, ofsdbg; | 314 | MSize ofsk, ofsuv, ofsdbg; |
335 | MSize sizedbg = 0; | 315 | MSize sizedbg = 0; |
336 | BCLine firstline = 0, numline = 0; | 316 | BCLine firstline = 0, numline = 0; |
337 | MSize len, startn; | ||
338 | |||
339 | /* Read length. */ | ||
340 | if (ls->n > 0 && ls->p[0] == 0) { /* Shortcut EOF. */ | ||
341 | ls->n--; ls->p++; | ||
342 | return NULL; | ||
343 | } | ||
344 | bcread_want(ls, 5); | ||
345 | len = bcread_uleb128(ls); | ||
346 | if (!len) return NULL; /* EOF */ | ||
347 | bcread_need(ls, len); | ||
348 | startn = ls->n; | ||
349 | 317 | ||
350 | /* Read prototype header. */ | 318 | /* Read prototype header. */ |
351 | flags = bcread_byte(ls); | 319 | flags = bcread_byte(ls); |
@@ -414,9 +382,6 @@ static GCproto *bcread_proto(LexState *ls) | |||
414 | setmref(pt->uvinfo, NULL); | 382 | setmref(pt->uvinfo, NULL); |
415 | setmref(pt->varinfo, NULL); | 383 | setmref(pt->varinfo, NULL); |
416 | } | 384 | } |
417 | |||
418 | if (len != startn - ls->n) | ||
419 | bcread_error(ls, LJ_ERR_BCBAD); | ||
420 | return pt; | 385 | return pt; |
421 | } | 386 | } |
422 | 387 | ||
@@ -430,6 +395,7 @@ static int bcread_header(LexState *ls) | |||
430 | bcread_byte(ls) != BCDUMP_VERSION) return 0; | 395 | bcread_byte(ls) != BCDUMP_VERSION) return 0; |
431 | bcread_flags(ls) = flags = bcread_uleb128(ls); | 396 | bcread_flags(ls) = flags = bcread_uleb128(ls); |
432 | if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0; | 397 | if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0; |
398 | if ((flags & BCDUMP_F_FR2) != LJ_FR2*BCDUMP_F_FR2) return 0; | ||
433 | if ((flags & BCDUMP_F_FFI)) { | 399 | if ((flags & BCDUMP_F_FFI)) { |
434 | #if LJ_HASFFI | 400 | #if LJ_HASFFI |
435 | lua_State *L = ls->L; | 401 | lua_State *L = ls->L; |
@@ -456,19 +422,33 @@ static int bcread_header(LexState *ls) | |||
456 | GCproto *lj_bcread(LexState *ls) | 422 | GCproto *lj_bcread(LexState *ls) |
457 | { | 423 | { |
458 | lua_State *L = ls->L; | 424 | lua_State *L = ls->L; |
459 | lua_assert(ls->current == BCDUMP_HEAD1); | 425 | lua_assert(ls->c == BCDUMP_HEAD1); |
460 | bcread_savetop(L, ls, L->top); | 426 | bcread_savetop(L, ls, L->top); |
461 | lj_str_resetbuf(&ls->sb); | 427 | lj_buf_reset(&ls->sb); |
462 | /* Check for a valid bytecode dump header. */ | 428 | /* Check for a valid bytecode dump header. */ |
463 | if (!bcread_header(ls)) | 429 | if (!bcread_header(ls)) |
464 | bcread_error(ls, LJ_ERR_BCFMT); | 430 | bcread_error(ls, LJ_ERR_BCFMT); |
465 | for (;;) { /* Process all prototypes in the bytecode dump. */ | 431 | for (;;) { /* Process all prototypes in the bytecode dump. */ |
466 | GCproto *pt = bcread_proto(ls); | 432 | GCproto *pt; |
467 | if (!pt) break; | 433 | MSize len; |
434 | const char *startp; | ||
435 | /* Read length. */ | ||
436 | if (ls->p < ls->pe && ls->p[0] == 0) { /* Shortcut EOF. */ | ||
437 | ls->p++; | ||
438 | break; | ||
439 | } | ||
440 | bcread_want(ls, 5); | ||
441 | len = bcread_uleb128(ls); | ||
442 | if (!len) break; /* EOF */ | ||
443 | bcread_need(ls, len); | ||
444 | startp = ls->p; | ||
445 | pt = lj_bcread_proto(ls); | ||
446 | if (ls->p != startp + len) | ||
447 | bcread_error(ls, LJ_ERR_BCBAD); | ||
468 | setprotoV(L, L->top, pt); | 448 | setprotoV(L, L->top, pt); |
469 | incr_top(L); | 449 | incr_top(L); |
470 | } | 450 | } |
471 | if ((ls->n && !ls->endmark) || L->top-1 != bcread_oldtop(L, ls)) | 451 | if ((ls->pe != ls->p && !ls->endmark) || L->top-1 != bcread_oldtop(L, ls)) |
472 | bcread_error(ls, LJ_ERR_BCBAD); | 452 | bcread_error(ls, LJ_ERR_BCBAD); |
473 | /* Pop off last prototype. */ | 453 | /* Pop off last prototype. */ |
474 | L->top--; | 454 | L->top--; |