mudgangster

Tiny, scriptable MUD client
Log | Files | Refs | README

lundump.cc (6179B)


      1 /*
      2 ** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 roberto Exp $
      3 ** load precompiled Lua chunks
      4 ** See Copyright Notice in lua.h
      5 */
      6 
      7 #define lundump_c
      8 #define LUA_CORE
      9 
     10 #include "lprefix.h"
     11 
     12 
     13 #include <string.h>
     14 
     15 #include "lua.h"
     16 
     17 #include "ldebug.h"
     18 #include "ldo.h"
     19 #include "lfunc.h"
     20 #include "lmem.h"
     21 #include "lobject.h"
     22 #include "lstring.h"
     23 #include "lundump.h"
     24 #include "lzio.h"
     25 
     26 
     27 #if !defined(luai_verifycode)
     28 #define luai_verifycode(L,b,f)  /* empty */
     29 #endif
     30 
     31 
     32 typedef struct {
     33   lua_State *L;
     34   ZIO *Z;
     35   const char *name;
     36 } LoadState;
     37 
     38 
     39 static l_noret error(LoadState *S, const char *why) {
     40   luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
     41   luaD_throw(S->L, LUA_ERRSYNTAX);
     42 }
     43 
     44 
     45 /*
     46 ** All high-level loads go through LoadVector; you can change it to
     47 ** adapt to the endianness of the input
     48 */
     49 #define LoadVector(S,b,n)	LoadBlock(S,b,(n)*sizeof((b)[0]))
     50 
     51 static void LoadBlock (LoadState *S, void *b, size_t size) {
     52   if (luaZ_read(S->Z, b, size) != 0)
     53     error(S, "truncated");
     54 }
     55 
     56 
     57 #define LoadVar(S,x)		LoadVector(S,&x,1)
     58 
     59 
     60 static lu_byte LoadByte (LoadState *S) {
     61   lu_byte x;
     62   LoadVar(S, x);
     63   return x;
     64 }
     65 
     66 
     67 static int LoadInt (LoadState *S) {
     68   int x;
     69   LoadVar(S, x);
     70   return x;
     71 }
     72 
     73 
     74 static lua_Number LoadNumber (LoadState *S) {
     75   lua_Number x;
     76   LoadVar(S, x);
     77   return x;
     78 }
     79 
     80 
     81 static lua_Integer LoadInteger (LoadState *S) {
     82   lua_Integer x;
     83   LoadVar(S, x);
     84   return x;
     85 }
     86 
     87 
     88 static TString *LoadString (LoadState *S) {
     89   size_t size = LoadByte(S);
     90   if (size == 0xFF)
     91     LoadVar(S, size);
     92   if (size == 0)
     93     return NULL;
     94   else if (--size <= LUAI_MAXSHORTLEN) {  /* short string? */
     95     char buff[LUAI_MAXSHORTLEN];
     96     LoadVector(S, buff, size);
     97     return luaS_newlstr(S->L, buff, size);
     98   }
     99   else {  /* long string */
    100     TString *ts = luaS_createlngstrobj(S->L, size);
    101     LoadVector(S, getstr(ts), size);  /* load directly in final place */
    102     return ts;
    103   }
    104 }
    105 
    106 
    107 static void LoadCode (LoadState *S, Proto *f) {
    108   int n = LoadInt(S);
    109   f->code = luaM_newvector(S->L, n, Instruction);
    110   f->sizecode = n;
    111   LoadVector(S, f->code, n);
    112 }
    113 
    114 
    115 static void LoadFunction(LoadState *S, Proto *f, TString *psource);
    116 
    117 
    118 static void LoadConstants (LoadState *S, Proto *f) {
    119   int i;
    120   int n = LoadInt(S);
    121   f->k = luaM_newvector(S->L, n, TValue);
    122   f->sizek = n;
    123   for (i = 0; i < n; i++)
    124     setnilvalue(&f->k[i]);
    125   for (i = 0; i < n; i++) {
    126     TValue *o = &f->k[i];
    127     int t = LoadByte(S);
    128     switch (t) {
    129     case LUA_TNIL:
    130       setnilvalue(o);
    131       break;
    132     case LUA_TBOOLEAN:
    133       setbvalue(o, LoadByte(S));
    134       break;
    135     case LUA_TNUMFLT:
    136       setfltvalue(o, LoadNumber(S));
    137       break;
    138     case LUA_TNUMINT:
    139       setivalue(o, LoadInteger(S));
    140       break;
    141     case LUA_TSHRSTR:
    142     case LUA_TLNGSTR:
    143       setsvalue2n(S->L, o, LoadString(S));
    144       break;
    145     default:
    146       lua_assert(0);
    147     }
    148   }
    149 }
    150 
    151 
    152 static void LoadProtos (LoadState *S, Proto *f) {
    153   int i;
    154   int n = LoadInt(S);
    155   f->p = luaM_newvector(S->L, n, Proto *);
    156   f->sizep = n;
    157   for (i = 0; i < n; i++)
    158     f->p[i] = NULL;
    159   for (i = 0; i < n; i++) {
    160     f->p[i] = luaF_newproto(S->L);
    161     LoadFunction(S, f->p[i], f->source);
    162   }
    163 }
    164 
    165 
    166 static void LoadUpvalues (LoadState *S, Proto *f) {
    167   int i, n;
    168   n = LoadInt(S);
    169   f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
    170   f->sizeupvalues = n;
    171   for (i = 0; i < n; i++)
    172     f->upvalues[i].name = NULL;
    173   for (i = 0; i < n; i++) {
    174     f->upvalues[i].instack = LoadByte(S);
    175     f->upvalues[i].idx = LoadByte(S);
    176   }
    177 }
    178 
    179 
    180 static void LoadDebug (LoadState *S, Proto *f) {
    181   int i, n;
    182   n = LoadInt(S);
    183   f->lineinfo = luaM_newvector(S->L, n, int);
    184   f->sizelineinfo = n;
    185   LoadVector(S, f->lineinfo, n);
    186   n = LoadInt(S);
    187   f->locvars = luaM_newvector(S->L, n, LocVar);
    188   f->sizelocvars = n;
    189   for (i = 0; i < n; i++)
    190     f->locvars[i].varname = NULL;
    191   for (i = 0; i < n; i++) {
    192     f->locvars[i].varname = LoadString(S);
    193     f->locvars[i].startpc = LoadInt(S);
    194     f->locvars[i].endpc = LoadInt(S);
    195   }
    196   n = LoadInt(S);
    197   for (i = 0; i < n; i++)
    198     f->upvalues[i].name = LoadString(S);
    199 }
    200 
    201 
    202 static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
    203   f->source = LoadString(S);
    204   if (f->source == NULL)  /* no source in dump? */
    205     f->source = psource;  /* reuse parent's source */
    206   f->linedefined = LoadInt(S);
    207   f->lastlinedefined = LoadInt(S);
    208   f->numparams = LoadByte(S);
    209   f->is_vararg = LoadByte(S);
    210   f->maxstacksize = LoadByte(S);
    211   LoadCode(S, f);
    212   LoadConstants(S, f);
    213   LoadUpvalues(S, f);
    214   LoadProtos(S, f);
    215   LoadDebug(S, f);
    216 }
    217 
    218 
    219 static void checkliteral (LoadState *S, const char *s, const char *msg) {
    220   char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
    221   size_t len = strlen(s);
    222   LoadVector(S, buff, len);
    223   if (memcmp(s, buff, len) != 0)
    224     error(S, msg);
    225 }
    226 
    227 
    228 static void fchecksize (LoadState *S, size_t size, const char *tname) {
    229   if (LoadByte(S) != size)
    230     error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
    231 }
    232 
    233 
    234 #define checksize(S,t)	fchecksize(S,sizeof(t),#t)
    235 
    236 static void checkHeader (LoadState *S) {
    237   checkliteral(S, LUA_SIGNATURE + 1, "not a");  /* 1st char already checked */
    238   if (LoadByte(S) != LUAC_VERSION)
    239     error(S, "version mismatch in");
    240   if (LoadByte(S) != LUAC_FORMAT)
    241     error(S, "format mismatch in");
    242   checkliteral(S, LUAC_DATA, "corrupted");
    243   checksize(S, int);
    244   checksize(S, size_t);
    245   checksize(S, Instruction);
    246   checksize(S, lua_Integer);
    247   checksize(S, lua_Number);
    248   if (LoadInteger(S) != LUAC_INT)
    249     error(S, "endianness mismatch in");
    250   if (LoadNumber(S) != LUAC_NUM)
    251     error(S, "float format mismatch in");
    252 }
    253 
    254 
    255 /*
    256 ** load precompiled chunk
    257 */
    258 LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
    259   LoadState S;
    260   LClosure *cl;
    261   if (*name == '@' || *name == '=')
    262     S.name = name + 1;
    263   else if (*name == LUA_SIGNATURE[0])
    264     S.name = "binary string";
    265   else
    266     S.name = name;
    267   S.L = L;
    268   S.Z = Z;
    269   checkHeader(&S);
    270   cl = luaF_newLclosure(L, LoadByte(&S));
    271   setclLvalue(L, L->top, cl);
    272   luaD_inctop(L);
    273   cl->p = luaF_newproto(L);
    274   LoadFunction(&S, cl->p, NULL);
    275   lua_assert(cl->nupvalues == cl->p->sizeupvalues);
    276   luai_verifycode(L, buff, cl->p);
    277   return cl;
    278 }
    279