diff options
Diffstat (limited to 'src/lj_bcread.c')
-rw-r--r-- | src/lj_bcread.c | 139 |
1 files changed, 59 insertions, 80 deletions
diff --git a/src/lj_bcread.c b/src/lj_bcread.c index 2b5ba855..9f025500 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,84 +40,73 @@ 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_MEM || 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 (ls->sb.n) { /* Append to buffer. */ | 76 | if (n) { /* Append to buffer. */ |
84 | MSize n = ls->sb.n + (MSize)size; | 77 | n += (MSize)sz; |
85 | bcread_resize(ls, n < len ? len : n); | 78 | p = lj_buf_need(&ls->sb, n < len ? len : n); |
86 | memcpy(ls->sb.buf + ls->sb.n, buf, size); | 79 | memcpy(sbufP(&ls->sb), buf, sz); |
87 | ls->n = ls->sb.n = n; | 80 | setsbufP(&ls->sb, p + n); |
88 | ls->p = ls->sb.buf; | 81 | ls->p = p; |
82 | ls->pe = p + n; | ||
89 | } else { /* Return buffer provided by reader. */ | 83 | } else { /* Return buffer provided by reader. */ |
90 | ls->n = (MSize)size; | ||
91 | ls->p = buf; | 84 | ls->p = buf; |
85 | ls->pe = buf + sz; | ||
92 | } | 86 | } |
93 | } while (ls->n < len); | 87 | } while (ls->p + len > ls->pe); |
94 | } | 88 | } |
95 | 89 | ||
96 | /* Need a certain number of bytes. */ | 90 | /* Need a certain number of bytes. */ |
97 | static LJ_AINLINE void bcread_need(LexState *ls, MSize len) | 91 | static LJ_AINLINE void bcread_need(LexState *ls, MSize len) |
98 | { | 92 | { |
99 | if (LJ_UNLIKELY(ls->n < len)) | 93 | if (LJ_UNLIKELY(ls->p + len > ls->pe)) |
100 | bcread_fill(ls, len, 1); | 94 | bcread_fill(ls, len, 1); |
101 | } | 95 | } |
102 | 96 | ||
103 | /* Want to read up to a certain number of bytes, but may need less. */ | 97 | /* Want to read up to a certain number of bytes, but may need less. */ |
104 | static LJ_AINLINE void bcread_want(LexState *ls, MSize len) | 98 | static LJ_AINLINE void bcread_want(LexState *ls, MSize len) |
105 | { | 99 | { |
106 | if (LJ_UNLIKELY(ls->n < len)) | 100 | if (LJ_UNLIKELY(ls->p + len > ls->pe)) |
107 | bcread_fill(ls, len, 0); | 101 | bcread_fill(ls, len, 0); |
108 | } | 102 | } |
109 | 103 | ||
110 | #define bcread_dec(ls) check_exp(ls->n > 0, ls->n--) | ||
111 | #define bcread_consume(ls, len) check_exp(ls->n >= (len), ls->n -= (len)) | ||
112 | |||
113 | /* Return memory block from buffer. */ | 104 | /* Return memory block from buffer. */ |
114 | static uint8_t *bcread_mem(LexState *ls, MSize len) | 105 | static LJ_AINLINE uint8_t *bcread_mem(LexState *ls, MSize len) |
115 | { | 106 | { |
116 | uint8_t *p = (uint8_t *)ls->p; | 107 | uint8_t *p = (uint8_t *)ls->p; |
117 | bcread_consume(ls, len); | 108 | ls->p += len; |
118 | ls->p = (char *)p + len; | 109 | lua_assert(ls->p <= ls->pe); |
119 | return p; | 110 | return p; |
120 | } | 111 | } |
121 | 112 | ||
@@ -128,25 +119,15 @@ static void bcread_block(LexState *ls, void *q, MSize len) | |||
128 | /* Read byte from buffer. */ | 119 | /* Read byte from buffer. */ |
129 | static LJ_AINLINE uint32_t bcread_byte(LexState *ls) | 120 | static LJ_AINLINE uint32_t bcread_byte(LexState *ls) |
130 | { | 121 | { |
131 | bcread_dec(ls); | 122 | lua_assert(ls->p < ls->pe); |
132 | return (uint32_t)(uint8_t)*ls->p++; | 123 | return (uint32_t)(uint8_t)*ls->p++; |
133 | } | 124 | } |
134 | 125 | ||
135 | /* Read ULEB128 value from buffer. */ | 126 | /* Read ULEB128 value from buffer. */ |
136 | static uint32_t bcread_uleb128(LexState *ls) | 127 | static LJ_AINLINE uint32_t bcread_uleb128(LexState *ls) |
137 | { | 128 | { |
138 | const uint8_t *p = (const uint8_t *)ls->p; | 129 | uint32_t v = lj_buf_ruleb128(&ls->p); |
139 | uint32_t v = *p++; | 130 | lua_assert(ls->p <= ls->pe); |
140 | if (LJ_UNLIKELY(v >= 0x80)) { | ||
141 | int sh = 0; | ||
142 | v &= 0x7f; | ||
143 | do { | ||
144 | v |= ((*p & 0x7f) << (sh += 7)); | ||
145 | bcread_dec(ls); | ||
146 | } while (*p++ >= 0x80); | ||
147 | } | ||
148 | bcread_dec(ls); | ||
149 | ls->p = (char *)p; | ||
150 | return v; | 131 | return v; |
151 | } | 132 | } |
152 | 133 | ||
@@ -160,11 +141,10 @@ static uint32_t bcread_uleb128_33(LexState *ls) | |||
160 | v &= 0x3f; | 141 | v &= 0x3f; |
161 | do { | 142 | do { |
162 | v |= ((*p & 0x7f) << (sh += 7)); | 143 | v |= ((*p & 0x7f) << (sh += 7)); |
163 | bcread_dec(ls); | ||
164 | } while (*p++ >= 0x80); | 144 | } while (*p++ >= 0x80); |
165 | } | 145 | } |
166 | bcread_dec(ls); | ||
167 | ls->p = (char *)p; | 146 | ls->p = (char *)p; |
147 | lua_assert(ls->p <= ls->pe); | ||
168 | return v; | 148 | return v; |
169 | } | 149 | } |
170 | 150 | ||
@@ -326,25 +306,13 @@ static void bcread_uv(LexState *ls, GCproto *pt, MSize sizeuv) | |||
326 | } | 306 | } |
327 | 307 | ||
328 | /* Read a prototype. */ | 308 | /* Read a prototype. */ |
329 | static GCproto *bcread_proto(LexState *ls) | 309 | GCproto *lj_bcread_proto(LexState *ls) |
330 | { | 310 | { |
331 | GCproto *pt; | 311 | GCproto *pt; |
332 | MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; | 312 | MSize framesize, numparams, flags, sizeuv, sizekgc, sizekn, sizebc, sizept; |
333 | MSize ofsk, ofsuv, ofsdbg; | 313 | MSize ofsk, ofsuv, ofsdbg; |
334 | MSize sizedbg = 0; | 314 | MSize sizedbg = 0; |
335 | BCLine firstline = 0, numline = 0; | 315 | BCLine firstline = 0, numline = 0; |
336 | MSize len, startn; | ||
337 | |||
338 | /* Read length. */ | ||
339 | if (ls->n > 0 && ls->p[0] == 0) { /* Shortcut EOF. */ | ||
340 | ls->n--; ls->p++; | ||
341 | return NULL; | ||
342 | } | ||
343 | bcread_want(ls, 5); | ||
344 | len = bcread_uleb128(ls); | ||
345 | if (!len) return NULL; /* EOF */ | ||
346 | bcread_need(ls, len); | ||
347 | startn = ls->n; | ||
348 | 316 | ||
349 | /* Read prototype header. */ | 317 | /* Read prototype header. */ |
350 | flags = bcread_byte(ls); | 318 | flags = bcread_byte(ls); |
@@ -413,9 +381,6 @@ static GCproto *bcread_proto(LexState *ls) | |||
413 | setmref(pt->uvinfo, NULL); | 381 | setmref(pt->uvinfo, NULL); |
414 | setmref(pt->varinfo, NULL); | 382 | setmref(pt->varinfo, NULL); |
415 | } | 383 | } |
416 | |||
417 | if (len != startn - ls->n) | ||
418 | bcread_error(ls, LJ_ERR_BCBAD); | ||
419 | return pt; | 384 | return pt; |
420 | } | 385 | } |
421 | 386 | ||
@@ -455,19 +420,33 @@ static int bcread_header(LexState *ls) | |||
455 | GCproto *lj_bcread(LexState *ls) | 420 | GCproto *lj_bcread(LexState *ls) |
456 | { | 421 | { |
457 | lua_State *L = ls->L; | 422 | lua_State *L = ls->L; |
458 | lua_assert(ls->current == BCDUMP_HEAD1); | 423 | lua_assert(ls->c == BCDUMP_HEAD1); |
459 | bcread_savetop(L, ls, L->top); | 424 | bcread_savetop(L, ls, L->top); |
460 | lj_str_resetbuf(&ls->sb); | 425 | lj_buf_reset(&ls->sb); |
461 | /* Check for a valid bytecode dump header. */ | 426 | /* Check for a valid bytecode dump header. */ |
462 | if (!bcread_header(ls)) | 427 | if (!bcread_header(ls)) |
463 | bcread_error(ls, LJ_ERR_BCFMT); | 428 | bcread_error(ls, LJ_ERR_BCFMT); |
464 | for (;;) { /* Process all prototypes in the bytecode dump. */ | 429 | for (;;) { /* Process all prototypes in the bytecode dump. */ |
465 | GCproto *pt = bcread_proto(ls); | 430 | GCproto *pt; |
466 | if (!pt) break; | 431 | MSize len; |
432 | const char *startp; | ||
433 | /* Read length. */ | ||
434 | if (ls->p < ls->pe && ls->p[0] == 0) { /* Shortcut EOF. */ | ||
435 | ls->p++; | ||
436 | break; | ||
437 | } | ||
438 | bcread_want(ls, 5); | ||
439 | len = bcread_uleb128(ls); | ||
440 | if (!len) break; /* EOF */ | ||
441 | bcread_need(ls, len); | ||
442 | startp = ls->p; | ||
443 | pt = lj_bcread_proto(ls); | ||
444 | if (ls->p != startp + len) | ||
445 | bcread_error(ls, LJ_ERR_BCBAD); | ||
467 | setprotoV(L, L->top, pt); | 446 | setprotoV(L, L->top, pt); |
468 | incr_top(L); | 447 | incr_top(L); |
469 | } | 448 | } |
470 | if ((int32_t)ls->n > 0 || L->top-1 != bcread_oldtop(L, ls)) | 449 | if (ls->p < ls->pe || L->top-1 != bcread_oldtop(L, ls)) |
471 | bcread_error(ls, LJ_ERR_BCBAD); | 450 | bcread_error(ls, LJ_ERR_BCBAD); |
472 | /* Pop off last prototype. */ | 451 | /* Pop off last prototype. */ |
473 | L->top--; | 452 | L->top--; |