| Line | Count | Source | 
| 1 |  | /* Copyright 2020 Google LLC | 
| 2 |  | Licensed under the Apache License, Version 2.0 (the "License"); | 
| 3 |  | you may not use this file except in compliance with the License. | 
| 4 |  | You may obtain a copy of the License at | 
| 5 |  |  | 
| 6 |  |       http://www.apache.org/licenses/LICENSE-2.0 | 
| 7 |  |  | 
| 8 |  | Unless required by applicable law or agreed to in writing, software | 
| 9 |  | distributed under the License is distributed on an "AS IS" BASIS, | 
| 10 |  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 11 |  | See the License for the specific language governing permissions and | 
| 12 |  | limitations under the License. | 
| 13 |  | */ | 
| 14 |  |  | 
| 15 |  |  | 
| 16 |  | #define lua_c | 
| 17 |  |  | 
| 18 |  | #include "lprefix.h" | 
| 19 |  |  | 
| 20 |  |  | 
| 21 |  | #include <stdio.h> | 
| 22 |  | #include <stdlib.h> | 
| 23 |  | #include <string.h> | 
| 24 |  | #include <stdint.h> | 
| 25 |  |  | 
| 26 |  | #include <signal.h> | 
| 27 |  |  | 
| 28 |  | #include "lua.h" | 
| 29 |  |  | 
| 30 |  | #include "lauxlib.h" | 
| 31 |  | #include "lualib.h" | 
| 32 |  |  | 
| 33 |  |  | 
| 34 |  | #if !defined(LUA_PROGNAME) | 
| 35 |  | #define LUA_PROGNAME            "lua" | 
| 36 |  | #endif | 
| 37 |  |  | 
| 38 |  | #if !defined(LUA_INIT_VAR) | 
| 39 |  | #define LUA_INIT_VAR            "LUA_INIT" | 
| 40 |  | #endif | 
| 41 |  |  | 
| 42 |  | #define LUA_INITVARVERSION      LUA_INIT_VAR LUA_VERSUFFIX | 
| 43 |  |  | 
| 44 |  |  | 
| 45 |  | static lua_State *globalL = NULL; | 
| 46 |  |  | 
| 47 |  | static const char *progname = LUA_PROGNAME; | 
| 48 |  |  | 
| 49 |  |  | 
| 50 |  | /* | 
| 51 |  | ** Hook set by signal function to stop the interpreter. | 
| 52 |  | */ | 
| 53 | 0 | static void lstop (lua_State *L, lua_Debug *ar) { | 
| 54 | 0 |   (void)ar;  /* unused arg. */ | 
| 55 | 0 |   lua_sethook(L, NULL, 0, 0);  /* reset hook */ | 
| 56 | 0 |   luaL_error(L, "interrupted!"); | 
| 57 | 0 | } | 
| 58 |  |  | 
| 59 |  |  | 
| 60 |  | /* | 
| 61 |  | ** Function to be called at a C signal. Because a C signal cannot | 
| 62 |  | ** just change a Lua state (as there is no proper synchronization), | 
| 63 |  | ** this function only sets a hook that, when called, will stop the | 
| 64 |  | ** interpreter. | 
| 65 |  | */ | 
| 66 | 0 | static void laction (int i) { | 
| 67 | 0 |   int flag = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT; | 
| 68 | 0 |   signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */ | 
| 69 | 0 |   lua_sethook(globalL, lstop, flag, 1); | 
| 70 | 0 | } | 
| 71 |  |  | 
| 72 |  | /* | 
| 73 |  | ** Prints an error message, adding the program name in front of it | 
| 74 |  | ** (if present) | 
| 75 |  | */ | 
| 76 | 439 | static void l_message (const char *pname, const char *msg) { | 
| 77 | 439 |   if (pname) fprintf(stderr, "%s: ", pname); | 
| 78 | 439 |   fprintf(stderr, "%s\n", msg); | 
| 79 | 439 | } | 
| 80 |  |  | 
| 81 |  |  | 
| 82 |  | /* | 
| 83 |  | ** Check whether 'status' is not OK and, if so, prints the error | 
| 84 |  | ** message on the top of the stack. It assumes that the error object | 
| 85 |  | ** is a string, as it was either generated by Lua or by 'msghandler'. | 
| 86 |  | */ | 
| 87 | 441 | static int report (lua_State *L, int status) { | 
| 88 | 441 |   if (status != LUA_OK) { | 
| 89 | 439 |     const char *msg = lua_tostring(L, -1); | 
| 90 | 439 |     l_message(progname, msg); | 
| 91 | 439 |     lua_pop(L, 1);  /* remove message */ | 
| 92 | 439 |   } | 
| 93 | 441 |   return status; | 
| 94 | 441 | } | 
| 95 |  |  | 
| 96 |  | /* | 
| 97 |  | ** Message handler used to run all chunks | 
| 98 |  | */ | 
| 99 | 143 | static int msghandler (lua_State *L) { | 
| 100 | 143 |   const char *msg = lua_tostring(L, 1); | 
| 101 | 143 |   if (msg == NULL) {  /* is error object not a string? */ | 
| 102 | 0 |     if (luaL_callmeta(L, 1, "__tostring") &&  /* does it have a metamethod */ | 
| 103 | 0 |         lua_type(L, -1) == LUA_TSTRING)  /* that produces a string? */ | 
| 104 | 0 |       return 1;  /* that is the message */ | 
| 105 | 0 |     else | 
| 106 | 0 |       msg = lua_pushfstring(L, "(error object is a %s value)", | 
| 107 | 0 |                                luaL_typename(L, 1)); | 
| 108 | 0 |   } | 
| 109 | 143 |   luaL_traceback(L, L, msg, 1);  /* append a standard traceback */ | 
| 110 | 143 |   return 1;  /* return the traceback */ | 
| 111 | 143 | } | 
| 112 |  |  | 
| 113 |  |  | 
| 114 |  | /* | 
| 115 |  | ** Interface to 'lua_pcall', which sets appropriate message function | 
| 116 |  | ** and C-signal handler. Used to run all chunks. | 
| 117 |  | */ | 
| 118 | 145 | static int docall (lua_State *L, int narg, int nres) { | 
| 119 | 145 |   int status; | 
| 120 | 145 |   int base = lua_gettop(L) - narg;  /* function index */ | 
| 121 | 145 |   lua_pushcfunction(L, msghandler);  /* push message handler */ | 
| 122 | 145 |   lua_insert(L, base);  /* put it under function and args */ | 
| 123 | 145 |   globalL = L;  /* to be available to 'laction' */ | 
| 124 | 145 |   signal(SIGINT, laction);  /* set C-signal handler */ | 
| 125 | 145 |   status = lua_pcall(L, narg, nres, base); | 
| 126 | 145 |   signal(SIGINT, SIG_DFL); /* reset C-signal handler */ | 
| 127 | 145 |   lua_remove(L, base);  /* remove message handler from the stack */ | 
| 128 | 145 |   return status; | 
| 129 | 145 | } | 
| 130 |  |  | 
| 131 |  |  | 
| 132 | 441 | static int dochunk (lua_State *L, int status) { | 
| 133 | 441 |   if (status == LUA_OK) status = docall(L, 0, 0); | 
| 134 | 441 |   return report(L, status); | 
| 135 | 441 | } | 
| 136 |  |  | 
| 137 |  |  | 
| 138 |  | /* mark in error messages for incomplete statements */ | 
| 139 |  | #define EOFMARK         "<eof>" | 
| 140 |  | #define marklen         (sizeof(EOFMARK)/sizeof(char) - 1) | 
| 141 |  |  | 
| 142 |  | int | 
| 143 | 13.9k | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | 
| 144 | 13.9k |     lua_State *L = luaL_newstate(); | 
| 145 | 13.9k |     if (L == NULL) { | 
| 146 | 0 |         return 0; | 
| 147 | 0 |     } | 
| 148 | 13.9k |     dochunk(L, luaL_loadbufferx(L, (const char *)data, size, "test", "t")); | 
| 149 |  |  | 
| 150 |  |  | 
| 151 | 13.9k |     lua_close(L); | 
| 152 | 13.9k |     return 0; | 
| 153 | 13.9k | } |