Fix hang/crash when requesting ZPOOL with incorrect backing device
[grub2/phcoder.git] / script / lua / grub_main.c
blob03f890a9a4b9aee69116672a34c63f15436b975a
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include "lua.h"
20 #include "lauxlib.h"
21 #include "lualib.h"
22 #include "grub_lib.h"
24 #include <grub/dl.h>
25 #include <grub/parser.h>
27 static lua_State *state;
29 /* Call `grub_error' to report a Lua error. The error message string must be
30 on the top of the Lua stack (at index -1). The error message is popped off
31 the Lua stack before this function returns. */
32 static void
33 handle_lua_error (const char *error_type)
35 const char *error_msg;
36 error_msg = lua_tostring (state, -1);
37 if (error_msg == NULL)
38 error_msg = "(error message not a string)";
39 grub_error (GRUB_ERR_BAD_ARGUMENT, "%s: %s", error_type, error_msg);
40 /* Pop the error message. */
41 lua_pop (state, 1);
44 static grub_err_t
45 grub_lua_parse_line (char *line, grub_reader_getline_t getline)
47 int r;
48 char *old_line = 0;
50 lua_settop(state, 0);
51 while (1)
53 r = luaL_loadbuffer (state, line, grub_strlen (line), "=grub");
54 if (! r)
56 /* No error: Execute the statement. */
57 r = lua_pcall (state, 0, 0, 0);
58 if (r)
60 handle_lua_error ("Lua");
61 break;
63 else
65 grub_free (old_line);
66 return grub_errno;
70 if (r == LUA_ERRSYNTAX)
72 /* Check whether the syntax error is a result of an incomplete
73 statement. If it is, then try to complete the statement by
74 reading more lines. */
75 size_t lmsg;
76 const char *msg = lua_tolstring (state, -1, &lmsg);
77 const char *tp = msg + lmsg - (sizeof (LUA_QL ("<eof>")) - 1);
78 if (grub_strstr (msg, LUA_QL ("<eof>")) == tp)
80 char *n, *t;
81 int len;
83 /* Discard the error message. */
84 lua_pop (state, 1);
85 /* Try to read another line to complete the statement. */
86 if ((getline (&n, 1)) || (! n))
88 grub_error (GRUB_ERR_BAD_ARGUMENT, "incomplete command");
89 break;
92 /* More input was available: Add it to the current statement
93 contents. */
94 len = grub_strlen (line);
95 t = grub_malloc (len + grub_strlen (n) + 2);
96 if (! t)
97 break;
99 grub_strcpy (t, line);
100 t[len] = '\n';
101 grub_strcpy (t + len + 1, n);
102 grub_free (old_line);
103 line = old_line = t;
104 /* Try again to execute the statement now that more input has
105 been appended. */
106 continue;
108 /* The syntax error was not the result of an incomplete line. */
109 handle_lua_error ("Lua syntax error");
111 else
113 /* Handle errors other than syntax errors (out of memory, etc.). */
114 handle_lua_error ("Lua parser failed");
117 break;
120 grub_free (old_line);
121 lua_gc (state, LUA_GCCOLLECT, 0);
123 return grub_errno;
126 static struct grub_parser grub_lua_parser =
128 .name = "lua",
129 .parse_line = grub_lua_parse_line
132 GRUB_MOD_INIT(lua)
134 (void) mod;
136 state = lua_open ();
137 if (state)
139 lua_gc (state, LUA_GCSTOP, 0);
140 luaL_openlibs (state);
141 luaL_register (state, "grub", grub_lua_lib);
142 lua_gc (state, LUA_GCRESTART, 0);
143 grub_parser_register ("lua", &grub_lua_parser);
147 GRUB_MOD_FINI(lua)
149 if (state)
151 grub_parser_unregister (&grub_lua_parser);
152 lua_close (state);