|
| 1 | +diff --git a/test/fuzz/luaL_loadbuffer/luaL_loadbuffer_fuzzer.cc b/test/fuzz/luaL_loadbuffer/luaL_loadbuffer_fuzzer.cc |
| 2 | +index 05fb39ceb0..24af9ae216 100644 |
| 3 | +--- a/test/fuzz/luaL_loadbuffer/luaL_loadbuffer_fuzzer.cc |
| 4 | ++++ b/test/fuzz/luaL_loadbuffer/luaL_loadbuffer_fuzzer.cc |
| 5 | +@@ -21,6 +21,74 @@ extern "C" |
| 6 | + << " (" << (val) * 100 / (total) << "%)" \ |
| 7 | + << std::endl |
| 8 | + |
| 9 | ++#define LUA_MEMORY_LIMIT_DEFAULT (2ULL * 1024 * 1024 * 1024) |
| 10 | ++ |
| 11 | ++/** |
| 12 | ++ * Default allocator function which is wrapped into a new one |
| 13 | ++ * with the Lua memory limit checker. |
| 14 | ++ */ |
| 15 | ++static lua_Alloc orig_alloc; |
| 16 | ++/** |
| 17 | ++ * Memory limit for LuaJIT. |
| 18 | ++ */ |
| 19 | ++static size_t memory_limit = LUA_MEMORY_LIMIT_DEFAULT; |
| 20 | ++/** |
| 21 | ++ * Amount of memory used by LuaJIT. |
| 22 | ++ */ |
| 23 | ++static size_t used; |
| 24 | ++ |
| 25 | ++/** |
| 26 | ++ * Lua custom memory allocation function. It extends the original |
| 27 | ++ * one with a memory counter and a limit check. |
| 28 | ++ */ |
| 29 | ++static void * |
| 30 | ++alloc_with_limit(void *ud, void *ptr, size_t osize, size_t nsize) |
| 31 | ++{ |
| 32 | ++ size_t new_used = used + nsize - osize; |
| 33 | ++ if (new_used > memory_limit) { |
| 34 | ++ /* |
| 35 | ++ * Returning NULL results in the "not enough |
| 36 | ++ * memory" error. |
| 37 | ++ */ |
| 38 | ++ return NULL; |
| 39 | ++ } |
| 40 | ++ |
| 41 | ++ void *result = orig_alloc(ud, ptr, osize, nsize); |
| 42 | ++ |
| 43 | ++ if (result != NULL || nsize == 0) |
| 44 | ++ used = new_used; |
| 45 | ++ |
| 46 | ++ /* |
| 47 | ++ * Result may be NULL, in this case "not enough memory" |
| 48 | ++ * is raised. |
| 49 | ++ */ |
| 50 | ++ return result; |
| 51 | ++} |
| 52 | ++ |
| 53 | ++static size_t |
| 54 | ++getgctotal(struct lua_State *L) |
| 55 | ++{ |
| 56 | ++ return (lua_getgccount(L) * 1024ULL) + lua_gc(L, LUA_GCCOUNTB, 0); |
| 57 | ++} |
| 58 | ++ |
| 59 | ++static void |
| 60 | ++lua_initalloc(struct lua_State *L) |
| 61 | ++{ |
| 62 | ++ assert(L != NULL); |
| 63 | ++ |
| 64 | ++ used = getgctotal(L); |
| 65 | ++ |
| 66 | ++ void *orig_ud; |
| 67 | ++ orig_alloc = lua_getallocf(L, &orig_ud); |
| 68 | ++ |
| 69 | ++ assert(orig_alloc != NULL); |
| 70 | ++ |
| 71 | ++ if (::getenv("LUA_MEMMAX")) |
| 72 | ++ memory_limit = std::stoi(::getenv("LUA_MEMMAX")); |
| 73 | ++ |
| 74 | ++ lua_setallocf(L, alloc_with_limit, orig_ud); |
| 75 | ++} |
| 76 | ++ |
| 77 | + struct metrics { |
| 78 | + size_t total_num; |
| 79 | + size_t total_num_with_errors; |
| 80 | +@@ -111,6 +179,7 @@ DEFINE_PROTO_FUZZER(const lua_grammar::Block &message) |
| 81 | + if (!L) |
| 82 | + return; |
| 83 | + |
| 84 | ++ lua_initalloc(L); |
| 85 | + std::string code = luajit_fuzzer::MainBlockToString(message); |
| 86 | + |
| 87 | + if (::getenv("LPM_DUMP_NATIVE_INPUT") && code.size() != 0) { |
| 88 | +@@ -130,6 +199,8 @@ DEFINE_PROTO_FUZZER(const lua_grammar::Block &message) |
| 89 | + |
| 90 | + if (luaL_loadbuffer(L, code.c_str(), code.size(), "fuzz") != LUA_OK) { |
| 91 | + report_error(L, "luaL_loadbuffer()"); |
| 92 | ++ |
| 93 | ++ std::cout << code << std::endl; |
| 94 | + goto end; |
| 95 | + } |
| 96 | + |
| 97 | +@@ -140,8 +211,9 @@ DEFINE_PROTO_FUZZER(const lua_grammar::Block &message) |
| 98 | + * needed to describe Lua semantics for more interesting |
| 99 | + * results and fuzzer tests. |
| 100 | + */ |
| 101 | +- if (lua_pcall(L, 0, 0, 0) != LUA_OK) |
| 102 | ++ if (lua_pcall(L, 0, 0, 0) != LUA_OK) { |
| 103 | + report_error(L, "lua_pcall()"); |
| 104 | ++ } |
| 105 | + |
| 106 | + end: |
| 107 | + metrics.total_num++; |
| 108 | +diff --git a/test/fuzz/luaL_loadbuffer/serializer.cc b/test/fuzz/luaL_loadbuffer/serializer.cc |
| 109 | +index b029ddb8ce..72074dc941 100644 |
| 110 | +--- a/test/fuzz/luaL_loadbuffer/serializer.cc |
| 111 | ++++ b/test/fuzz/luaL_loadbuffer/serializer.cc |
| 112 | +@@ -647,7 +647,7 @@ NESTED_PROTO_TOSTRING(Args, args, FunctionCall) |
| 113 | + case ArgsType::kTableconstructor: |
| 114 | + return TableConstructorToString(args.tableconstructor()); |
| 115 | + case ArgsType::kStr: |
| 116 | +- return "'" + ConvertToStringDefault(args.str()) + "'"; |
| 117 | ++ return "'" + ConvertToStringDefault(args.str(), true) + "'"; |
| 118 | + default: |
| 119 | + /* For more variability. */ |
| 120 | + return TableConstructorToString(args.tableconstructor()); |
| 121 | +@@ -982,7 +982,7 @@ PROTO_TOSTRING(Expression, expr) |
| 122 | + return std::to_string(number); |
| 123 | + } |
| 124 | + case ExprType::kStr: |
| 125 | +- return "'" + ConvertToStringDefault(expr.str()) + "'"; |
| 126 | ++ return "'" + ConvertToStringDefault(expr.str(), true) + "'"; |
| 127 | + case ExprType::kEllipsis: |
| 128 | + if (GetContext().vararg_is_possible()) { |
| 129 | + return " ... "; |
| 130 | +@@ -1004,7 +1004,7 @@ PROTO_TOSTRING(Expression, expr) |
| 131 | + * Arbitrary choice. |
| 132 | + * TODO: Choose "more interesting" defaults. |
| 133 | + */ |
| 134 | +- return "'" + ConvertToStringDefault(expr.str()) + "'"; |
| 135 | ++ return "'" + ConvertToStringDefault(expr.str(), true) + "'"; |
| 136 | + } |
| 137 | + } |
| 138 | + |
0 commit comments