aboutsummaryrefslogtreecommitdiff
path: root/src/lj_bcread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_bcread.c')
-rw-r--r--src/lj_bcread.c139
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. */
46static 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. */
57static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need) 48static 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. */
97static LJ_AINLINE void bcread_need(LexState *ls, MSize len) 91static 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. */
104static LJ_AINLINE void bcread_want(LexState *ls, MSize len) 98static 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. */
114static uint8_t *bcread_mem(LexState *ls, MSize len) 105static 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. */
129static LJ_AINLINE uint32_t bcread_byte(LexState *ls) 120static 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. */
136static uint32_t bcread_uleb128(LexState *ls) 127static 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. */
329static GCproto *bcread_proto(LexState *ls) 309GCproto *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)
455GCproto *lj_bcread(LexState *ls) 420GCproto *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--;