I get your point.
After initiating the thread, I conducted a thorough examination of all the call sites for the two wrapper functions of `touserdata`, namely `lua_touserdata` and `lua_topointer`, across the project. As a result, I detected three more null pointer dereferences that are similar in nature (I will present them later).
Furthermore, I observed that some of the call sites handled the return value of these functions appropriately, while others did not, including the `resizebox` function, regardless of whether the call site was static or not.
Considering these inconsistencies, it is likely that the software will become harder to maintain and could potentially lead to crashes. Therefore, I suggest addressing these two potential null pointer dereferences by properly checking the return value of the functions, as has been done at other call sites. (An example fix for the similar issue is provided.)
Three more NPD were caused by calling `lua_touserdata`
First:
Call `lua_touserdata` at lmathlib.c:560. The return value is directly dereferenced at lmathlib.c:561
static int math_random (lua_State *L) {
lua_Integer low, up;
lua_Unsigned p;
RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); line 560
Rand64 rv = nextrand(state->s); /* next pseudo-random value */ line 561
...
}
Second:
Call `lua_touserdata` at lmathlib.c:619. The return value is directly dereferenced in lmathlib.c:621
static int math_randomseed (lua_State *L) {
RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); //619
if (lua_isnone(L, 1)) {
randseed(L, state); // 621
}
...
}
Third:
Call `lua_touserdata` at lstrlib.c:839. The return value is directly dereferenced at 841
static int gmatch_aux (lua_State *L) {
GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); // line 839
const char *src;
gm->ms.L = L; // line 841
for (src = "" src <= gm->ms.src_end; src++) {
const char *e;
reprepstate(&gm->ms);
...
}
I also list an example fix in a static method for the wrapper `lua_topointer` for your reference:
1. Return null from lapi.c:480 and lapi.c:485
LUA_API const void *lua_topointer (lua_State *L, int idx) {
const TValue *o = index2value(L, idx);
switch (ttypetag(o)) {
case LUA_VLCF: return cast_voidp(cast_sizet(fvalue(o)));
case LUA_VUSERDATA: case LUA_VLIGHTUSERDATA:
return touserdata(o); // line 480 return null
default: {
if (iscollectable(o))
return gcvalue(o);
else
return NULL; // line 485 return null
}
}
}
2. `lua_topointer` is called at lstrlib.c:1334 and the return value is checked at lstrlib.c:1336
static int str_format (lua_State *L) {
...
case 'p': {
const void *p = lua_topointer(L, arg); // line 1334
checkformat(L, form, L_FMTFLAGSC, 0);
if (p == NULL) { /* avoid calling 'printf' with argument NULL */ // line 1336
p = "(null)"; /* result */
form[strlen(form) - 1] = 's'; /* format it as a string */
}
nb = l_sprintf(buff, maxitem, form, p);
break;
}
...
}
Best regards
Yongchao