1 /*
2 * Copyright (c) 2009-2021, Google LLC
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Google LLC nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * require("lua") -- A Lua extension for upb.
30 *
31 * Exposes only the core library
32 * (sub-libraries are exposed in other extensions).
33 *
34 * 64-bit woes: Lua can only represent numbers of type lua_Number (which is
35 * double unless the user specifically overrides this). Doubles can represent
36 * the entire range of 64-bit integers, but lose precision once the integers are
37 * greater than 2^53.
38 *
39 * Lua 5.3 is adding support for integers, which will allow for 64-bit
40 * integers (which can be interpreted as signed or unsigned).
41 *
42 * LuaJIT supports 64-bit signed and unsigned boxed representations
43 * through its "cdata" mechanism, but this is not portable to regular Lua.
44 *
45 * Hopefully Lua 5.3 will come soon enough that we can either use Lua 5.3
46 * integer support or LuaJIT 64-bit cdata for users that need the entire
47 * domain of [u]int64 values.
48 */
49
50 #include "lua/upb.h"
51
52 #include <float.h>
53 #include <math.h>
54 #include <stdint.h>
55 #include <stdlib.h>
56 #include <string.h>
57
58 #include "lauxlib.h"
59 #include "upb/msg.h"
60
61 /* Lua compatibility code *****************************************************/
62
63 /* Shims for upcoming Lua 5.3 functionality. */
lua_isinteger(lua_State * L,int argn)64 static bool lua_isinteger(lua_State* L, int argn) {
65 LUPB_UNUSED(L);
66 LUPB_UNUSED(argn);
67 return false;
68 }
69
70 /* Utility functions **********************************************************/
71
lupb_checkstatus(lua_State * L,upb_Status * s)72 void lupb_checkstatus(lua_State* L, upb_Status* s) {
73 if (!upb_Status_IsOk(s)) {
74 lua_pushstring(L, upb_Status_ErrorMessage(s));
75 lua_error(L);
76 }
77 }
78
79 /* Pushes a new userdata with the given metatable. */
lupb_newuserdata(lua_State * L,size_t size,int n,const char * type)80 void* lupb_newuserdata(lua_State* L, size_t size, int n, const char* type) {
81 #if LUA_VERSION_NUM >= 504
82 void* ret = lua_newuserdatauv(L, size, n);
83 #else
84 void* ret = lua_newuserdata(L, size);
85 lua_createtable(L, 0, n);
86 lua_setuservalue(L, -2);
87 #endif
88
89 /* Set metatable. */
90 luaL_getmetatable(L, type);
91 assert(!lua_isnil(L, -1)); /* Should have been created by luaopen_upb. */
92 lua_setmetatable(L, -2);
93
94 return ret;
95 }
96
97 #if LUA_VERSION_NUM < 504
lua_setiuservalue(lua_State * L,int index,int n)98 int lua_setiuservalue(lua_State* L, int index, int n) {
99 lua_getuservalue(L, index);
100 lua_insert(L, -2);
101 lua_rawseti(L, -2, n);
102 lua_pop(L, 1);
103 return 1;
104 }
105
lua_getiuservalue(lua_State * L,int index,int n)106 int lua_getiuservalue(lua_State* L, int index, int n) {
107 lua_getuservalue(L, index);
108 lua_rawgeti(L, -1, n);
109 lua_replace(L, -2);
110 return 1;
111 }
112 #endif
113
114 /* We use this function as the __index metamethod when a type has both methods
115 * and an __index metamethod. */
lupb_indexmm(lua_State * L)116 int lupb_indexmm(lua_State* L) {
117 /* Look up in __index table (which is a closure param). */
118 lua_pushvalue(L, 2);
119 lua_rawget(L, lua_upvalueindex(1));
120 if (!lua_isnil(L, -1)) {
121 return 1;
122 }
123
124 /* Not found, chain to user __index metamethod. */
125 lua_pushvalue(L, lua_upvalueindex(2));
126 lua_pushvalue(L, 1);
127 lua_pushvalue(L, 2);
128 lua_call(L, 2, 1);
129 return 1;
130 }
131
lupb_register_type(lua_State * L,const char * name,const luaL_Reg * m,const luaL_Reg * mm)132 void lupb_register_type(lua_State* L, const char* name, const luaL_Reg* m,
133 const luaL_Reg* mm) {
134 luaL_newmetatable(L, name);
135
136 if (mm) {
137 lupb_setfuncs(L, mm);
138 }
139
140 if (m) {
141 lua_createtable(L, 0, 0); /* __index table */
142 lupb_setfuncs(L, m);
143
144 /* Methods go in the mt's __index slot. If the user also specified an
145 * __index metamethod, use our custom lupb_indexmm() that can check both. */
146 lua_getfield(L, -2, "__index");
147 if (lua_isnil(L, -1)) {
148 lua_pop(L, 1);
149 } else {
150 lua_pushcclosure(L, &lupb_indexmm, 2);
151 }
152 lua_setfield(L, -2, "__index");
153 }
154
155 lua_pop(L, 1); /* The mt. */
156 }
157
158 /* Scalar type mapping ********************************************************/
159
160 /* Functions that convert scalar/primitive values (numbers, strings, bool)
161 * between Lua and C/upb. Handles type/range checking. */
162
lupb_checkbool(lua_State * L,int narg)163 bool lupb_checkbool(lua_State* L, int narg) {
164 if (!lua_isboolean(L, narg)) {
165 luaL_error(L, "must be true or false");
166 }
167 return lua_toboolean(L, narg);
168 }
169
170 /* Unlike luaL_checkstring(), this does not allow implicit conversion to
171 * string. */
lupb_checkstring(lua_State * L,int narg,size_t * len)172 const char* lupb_checkstring(lua_State* L, int narg, size_t* len) {
173 if (lua_type(L, narg) != LUA_TSTRING) {
174 luaL_error(L, "Expected string");
175 }
176
177 return lua_tolstring(L, narg, len);
178 }
179
180 /* Unlike luaL_checkinteger, these do not implicitly convert from string or
181 * round an existing double value. We allow floating-point input, but only if
182 * the actual value is integral. */
183 #define INTCHECK(type, ctype, min, max) \
184 ctype lupb_check##type(lua_State* L, int narg) { \
185 double n; \
186 if (lua_isinteger(L, narg)) { \
187 return lua_tointeger(L, narg); \
188 } \
189 \
190 /* Prevent implicit conversion from string. */ \
191 luaL_checktype(L, narg, LUA_TNUMBER); \
192 n = lua_tonumber(L, narg); \
193 \
194 /* Check this double has no fractional part and remains in bounds. \
195 * Consider INT64_MIN and INT64_MAX: \
196 * 1. INT64_MIN -(2^63) is a power of 2, so this converts to a double. \
197 * 2. INT64_MAX (2^63 - 1) is not a power of 2, and conversion of \
198 * out-of-range integer values to a double can lead to undefined behavior. \
199 * On some compilers, this conversion can return 0, but it also can return \
200 * the max value. To deal with this, we can first divide by 2 to prevent \
201 * the overflow, multiply it back, and add 1 to find the true limit. */ \
202 double i; \
203 double max_value = (((double)max / 2) * 2) + 1; \
204 if ((modf(n, &i) != 0.0) || n < min || n >= max_value) { \
205 luaL_error(L, "number %f was not an integer or out of range for " #type, \
206 n); \
207 } \
208 return (ctype)n; \
209 } \
210 void lupb_push##type(lua_State* L, ctype val) { \
211 /* TODO: push integer for Lua >= 5.3, 64-bit cdata for LuaJIT. */ \
212 /* This is lossy for some [u]int64 values, which isn't great, but */ \
213 /* crashing when we encounter these values seems worse. */ \
214 lua_pushnumber(L, val); \
215 }
216
INTCHECK(int64,int64_t,INT64_MIN,INT64_MAX)217 INTCHECK(int64, int64_t, INT64_MIN, INT64_MAX)
218 INTCHECK(int32, int32_t, INT32_MIN, INT32_MAX)
219 INTCHECK(uint64, uint64_t, 0, UINT64_MAX)
220 INTCHECK(uint32, uint32_t, 0, UINT32_MAX)
221
222 double lupb_checkdouble(lua_State* L, int narg) {
223 /* If we were being really hard-nosed here, we'd check whether the input was
224 * an integer that has no precise double representation. But doubles aren't
225 * generally expected to be exact like integers are, and worse this could
226 * cause data-dependent runtime errors: one run of the program could work fine
227 * because the integer calculations happened to be exactly representable in
228 * double, while the next could crash because of subtly different input. */
229
230 luaL_checktype(L, narg, LUA_TNUMBER); /* lua_tonumber() auto-converts. */
231 return lua_tonumber(L, narg);
232 }
233
lupb_checkfloat(lua_State * L,int narg)234 float lupb_checkfloat(lua_State* L, int narg) {
235 /* We don't worry about checking whether the input can be exactly converted to
236 * float -- see above. */
237
238 luaL_checktype(L, narg, LUA_TNUMBER); /* lua_tonumber() auto-converts. */
239 return lua_tonumber(L, narg);
240 }
241
lupb_pushdouble(lua_State * L,double d)242 void lupb_pushdouble(lua_State* L, double d) { lua_pushnumber(L, d); }
243
lupb_pushfloat(lua_State * L,float d)244 void lupb_pushfloat(lua_State* L, float d) { lua_pushnumber(L, d); }
245
246 /* Library entry point ********************************************************/
247
luaopen_lupb(lua_State * L)248 int luaopen_lupb(lua_State* L) {
249 #if LUA_VERSION_NUM == 501
250 const struct luaL_Reg funcs[] = {{NULL, NULL}};
251 luaL_register(L, "upb_c", funcs);
252 #else
253 lua_createtable(L, 0, 8);
254 #endif
255 lupb_def_registertypes(L);
256 lupb_msg_registertypes(L);
257 return 1; /* Return package table. */
258 }
259