Browse Source

BUG: luaL_checkudata may show wrong error message

Roberto Ierusalimschy 19 years ago
parent
commit
0238a0b01e
2 changed files with 50 additions and 6 deletions
  1. 38 0
      bugs
  2. 12 6
      lauxlib.c

+ 38 - 0
bugs

@@ -839,3 +839,41 @@ patch = [[
 
 }
 
+
+Bug{
+what = [[luaL_checkudata may produce wrong error message]],
+
+report = [[Greg Falcon, 21/03/2006]],
+
+example = [[
+getmetatable(io.stdin).__gc()
+  --> bad argument #1 to '__gc' (FILE* expected, got table)
+]],
+
+patch = [[
+* lauxlib.c:
+@@ -123,11 +123,17 @@
+
+ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
+   void *p = lua_touserdata(L, ud);
+-  lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */
+-  if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
+-    luaL_typerror(L, ud, tname);
+-  lua_pop(L, 2);  /* remove both metatables */
+-  return p;
++  if (p != NULL) {  /* value is a userdata? */
++    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
++      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */
++      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */
++        lua_pop(L, 2);  /* remove both metatables */
++        return p;
++      }
++    }
++  }
++  luaL_typerror(L, ud, tname);  /* else error */
++  return NULL;  /* to avoid warnings */
+ }
+]]
+
+}
+

+ 12 - 6
lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.157 2005/12/29 15:32:11 roberto Exp roberto $
+** $Id: lauxlib.c,v 1.158 2006/01/16 12:42:21 roberto Exp roberto $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -123,11 +123,17 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
 
 LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
   void *p = lua_touserdata(L, ud);
-  lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */
-  if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
-    luaL_typerror(L, ud, tname);
-  lua_pop(L, 2);  /* remove both metatables */
-  return p;
+  if (p != NULL) {  /* value is a userdata? */
+    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
+      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */
+      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */
+        lua_pop(L, 2);  /* remove both metatables */
+        return p;
+      }
+    }
+  }
+  luaL_typerror(L, ud, tname);  /* else error */
+  return NULL;  /* to avoid warnings */
 }