/src/interface.c

http://lbcv.googlecode.com/ · C · 331 lines · 271 code · 20 blank · 40 comment · 59 complexity · f99bd580c171cfc8b9decb6bb77bb25e MD5 · raw file

  1. /* Copyright (c) 2010 Peter Cawley
  2. Permission is hereby granted, free of charge, to any person obtaining a copy of
  3. this software and associated documentation files (the "Software"), to deal in
  4. the Software without restriction, including without limitation the rights to
  5. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  6. of the Software, and to permit persons to whom the Software is furnished to do
  7. so, subject to the following conditions:
  8. The above copyright notice and this permission notice shall be included in all
  9. copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  14. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  15. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  16. SOFTWARE.
  17. Based in part on code from lbaselib.c in Lua 5.2, which is:
  18. Copyright (C) 1994-2010 Lua.org, PUC-Rio. All rights reserved.
  19. */
  20. #define LUA_LIB
  21. #include "decoder.h"
  22. #include "verifier.h"
  23. #include <lauxlib.h>
  24. #include <string.h>
  25. static int l_cleanup_decode_state(lua_State* L)
  26. {
  27. decoded_prototype_t* proto;
  28. decode_state_t* ds = *(decode_state_t**)lua_touserdata(L, 1);
  29. if(ds)
  30. {
  31. proto = decode_bytecode_finish(ds);
  32. if(proto)
  33. {
  34. void* allocud;
  35. lua_Alloc alloc = lua_getallocf(L, &allocud);
  36. free_prototype(proto, alloc, allocud);
  37. }
  38. }
  39. return 0;
  40. }
  41. static int decode_fail(lua_State* L, int status)
  42. {
  43. lua_pushnil(L);
  44. switch(status)
  45. {
  46. case DECODE_UNSAFE:
  47. lua_pushliteral(L, "verification failed during decode");
  48. break;
  49. case DECODE_ERROR:
  50. lua_pushliteral(L, "unknown decoding error");
  51. break;
  52. case DECODE_ERROR_MEM:
  53. lua_pushliteral(L, "insufficient memory");
  54. break;
  55. default:
  56. lua_pushliteral(L, "unable to load bytecode");
  57. break;
  58. }
  59. return 2;
  60. }
  61. static int verify_fail(lua_State* L)
  62. {
  63. lua_pushnil(L);
  64. lua_pushliteral(L, "verification failed");
  65. return 2;
  66. }
  67. static int not_string_err(lua_State* L)
  68. {
  69. lua_pushliteral(L, "reader function must return a string");
  70. return lua_error(L);
  71. }
  72. static int l_verify(lua_State* L)
  73. {
  74. decoded_prototype_t* proto = NULL;
  75. void* allocud;
  76. lua_Alloc alloc = lua_getallocf(L, &allocud);
  77. decode_state_t* ds = NULL;
  78. decode_state_t** pds = &ds;
  79. int status = DECODE_YIELD;
  80. size_t len;
  81. const char* str;
  82. if(lua_type(L, 1) != LUA_TSTRING)
  83. {
  84. if(lua_getctx(L, NULL) == LUA_OK)
  85. {
  86. /* If the reader function throws an error, then the decode state
  87. should still get cleaned. This is achieved by creating a userdata
  88. whose garbage collection metamethod cleans up the decode state.
  89. This also allows the decode state to be maintained if the reader
  90. function yields. */
  91. lua_settop(L, 1);
  92. pds = (decode_state_t**)lua_newuserdata(L, sizeof(decode_state_t*));
  93. lua_createtable(L, 0, 1);
  94. lua_pushcfunction(L, l_cleanup_decode_state);
  95. lua_setfield(L, 3, "__gc");
  96. lua_setmetatable(L, 2);
  97. }
  98. else
  99. {
  100. pds = (decode_state_t**)lua_touserdata(L, 2);
  101. ds = *pds;
  102. goto resume_continuation;
  103. }
  104. }
  105. ds = decode_bytecode_init(alloc, allocud);
  106. *pds = ds;
  107. if(lua_type(L, 1) == LUA_TSTRING)
  108. {
  109. str = lua_tolstring(L, 1, &len);
  110. status = decode_bytecode_pump(ds, (const unsigned char*)str, len);
  111. }
  112. else
  113. {
  114. luaL_checktype(L, 1, LUA_TFUNCTION);
  115. while(status == DECODE_YIELD)
  116. {
  117. lua_settop(L, 2);
  118. lua_pushvalue(L, 1);
  119. lua_callk(L, 0, 1, 1, l_verify);
  120. resume_continuation:
  121. str = lua_tolstring(L, 3, &len);
  122. if(str == NULL || len == 0)
  123. {
  124. if(str == NULL && lua_type(L, 3) != LUA_TNIL)
  125. return not_string_err(L);
  126. break;
  127. }
  128. status = decode_bytecode_pump(ds, (const unsigned char*)str, len);
  129. }
  130. }
  131. proto = decode_bytecode_finish(ds);
  132. *pds = NULL;
  133. if(proto == NULL)
  134. {
  135. return decode_fail(L, status);
  136. }
  137. else
  138. {
  139. bool good = verify(proto, alloc, allocud);
  140. free_prototype(proto, alloc, allocud);
  141. if(good)
  142. {
  143. lua_pushboolean(L, 1);
  144. return 1;
  145. }
  146. else
  147. {
  148. lua_pushnil(L);
  149. lua_pushliteral(L, "verification failed");
  150. return 2;
  151. }
  152. }
  153. }
  154. static const char *checkrights(lua_State *L, const char *mode, const char *s)
  155. {
  156. if(strchr(mode, 'b') == NULL && *s == LUA_SIGNATURE[0])
  157. return lua_pushliteral(L, "attempt to load a binary chunk");
  158. if(strchr(mode, 't') == NULL && *s != LUA_SIGNATURE[0])
  159. return lua_pushliteral(L, "attempt to load a text chunk");
  160. return NULL; /* chunk in allowed format */
  161. }
  162. #define RESERVEDSLOT 5
  163. /*
  164. ** Reader for generic `load' function: `lua_load' uses the
  165. ** stack for internal stuff, so the reader cannot change the
  166. ** stack top. Instead, it keeps its resulting string in a
  167. ** reserved slot inside the stack.
  168. */
  169. typedef struct { /* reader state */
  170. int f; /* position of reader function on stack */
  171. const char *mode; /* allowed modes (binary/text) */
  172. decode_state_t *ds; /* for binary chunks, the decode state */
  173. int decode_status; /* for binary chunks, result of decode_bytecode_pump */
  174. } Readstat;
  175. static const char *generic_reader(lua_State *L, void *ud, size_t *size)
  176. {
  177. const char *s;
  178. size_t len;
  179. Readstat *stat = (Readstat *)ud;
  180. luaL_checkstack(L, 2, "too many nested functions");
  181. lua_pushvalue(L, stat->f); /* get function */
  182. lua_call(L, 0, 1); /* call it */
  183. if(lua_isnil(L, -1))
  184. {
  185. *size = 0;
  186. return NULL;
  187. }
  188. else if((s = lua_tolstring(L, -1, &len)) != NULL)
  189. {
  190. if(stat->mode != NULL) /* first time? */
  191. {
  192. if(checkrights(L, stat->mode, s)) /* check mode */
  193. lua_error(L);
  194. stat->mode = NULL; /* to avoid further checks */
  195. if(s[0] == LUA_SIGNATURE[0])
  196. {
  197. void* allocud;
  198. lua_Alloc alloc = lua_getallocf(L, &allocud);
  199. stat->ds = decode_bytecode_init(alloc, allocud);
  200. }
  201. }
  202. if(stat->ds)
  203. {
  204. int status = decode_bytecode_pump(stat->ds, (const unsigned char*)s, len);
  205. if(status != DECODE_YIELD)
  206. {
  207. lua_pop(L, 1);
  208. decode_fail(L, status);
  209. lua_error(L);
  210. }
  211. }
  212. lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
  213. return lua_tolstring(L, RESERVEDSLOT, size);
  214. }
  215. else
  216. {
  217. not_string_err(L);
  218. return NULL; /* to avoid warnings */
  219. }
  220. }
  221. static int check_ds(lua_State *L, Readstat* stat)
  222. {
  223. bool verified;
  224. void* allocud;
  225. lua_Alloc alloc = lua_getallocf(L, &allocud);
  226. decoded_prototype_t* proto = decode_bytecode_finish(stat->ds);
  227. if(proto == NULL)
  228. return decode_fail(L, stat->decode_status);
  229. verified = verify(proto, alloc, allocud);
  230. free_prototype(proto, alloc, allocud);
  231. if(!verified)
  232. return verify_fail(L);
  233. return 0;
  234. }
  235. static int l_load(lua_State *L)
  236. {
  237. Readstat stat;
  238. size_t len;
  239. const char *str;
  240. void* allocud;
  241. lua_Alloc alloc = lua_getallocf(L, &allocud);
  242. int status;
  243. int top = lua_gettop(L);
  244. stat.f = 1;
  245. stat.mode = luaL_optstring(L, 3, "bt");
  246. stat.ds = NULL;
  247. stat.decode_status = DECODE_YIELD;
  248. str = lua_tolstring(L, stat.f, &len);
  249. if(str == NULL)
  250. {
  251. /* Load from a reader function. */
  252. const char *chunkname = luaL_optstring(L, stat.f + 1, "=(load)");
  253. luaL_checktype(L, stat.f, LUA_TFUNCTION);
  254. lua_settop(L, RESERVEDSLOT);
  255. status = lua_load(L, generic_reader, (void*)&stat, chunkname);
  256. if(stat.ds)
  257. {
  258. if(check_ds(L, &stat) && status == LUA_OK)
  259. return 2;
  260. }
  261. }
  262. else
  263. {
  264. /* Load from a single string. */
  265. const char *chunkname = luaL_optstring(L, stat.f + 1, str);
  266. /* First check that mode is respected. */
  267. if(checkrights(L, stat.mode, str))
  268. {
  269. lua_pushnil(L);
  270. lua_insert(L, -2);
  271. return 2;
  272. }
  273. /* If it is bytecode, verify the bytecode before loading it. */
  274. if(str[0] == LUA_SIGNATURE[0])
  275. {
  276. stat.ds = decode_bytecode_init(alloc, allocud);
  277. stat.decode_status = decode_bytecode_pump(stat.ds, (const unsigned char*)str, len);
  278. if(check_ds(L, &stat))
  279. return 2;
  280. }
  281. /* Do the actual loading. */
  282. status = luaL_loadbuffer(L, str, len, chunkname);
  283. }
  284. if (status == LUA_OK) {
  285. if (top >= 4) { /* is there an 'env' argument */
  286. lua_pushvalue(L, 4); /* environment for loaded function */
  287. lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */
  288. }
  289. return 1;
  290. } else {
  291. lua_pushnil(L);
  292. lua_insert(L, -2); /* put before error message */
  293. return 2; /* return nil plus error message */
  294. }
  295. }
  296. const luaL_Reg lib[] = {
  297. {"verify", l_verify},
  298. {"load", l_load},
  299. {NULL, NULL}
  300. };
  301. LUAMOD_API int luaopen_lbcv(lua_State* L)
  302. {
  303. lua_createtable(L, 0, sizeof(lib)/sizeof(*lib));
  304. luaL_setfuncs(L, lib, 0);
  305. return 1;
  306. }