Index: lauxlib.h
===================================================================
--- lauxlib.h	(revision 19384)
+++ lauxlib.h	(working copy)
@@ -64,6 +64,7 @@
 
 LUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);
 LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
+LUALIB_API void (luaL_checkrawtable) (lua_State *L, int t, const char* modes);
 
 LUALIB_API void (luaL_where) (lua_State *L, int lvl);
 LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
Index: ltm.cxx
===================================================================
--- ltm.cxx	(revision 19384)
+++ ltm.cxx	(working copy)
@@ -29,7 +29,7 @@
 
 void luaT_init (lua_State *L) {
   static const char *const luaT_eventname[] = {  /* ORDER TM */
-    "__index", "__newindex",
+    "__index", "__newindex", "__usedindex", "__rawblock",
     "__gc", "__mode", "__eq",
     "__add", "__sub", "__mul", "__div", "__mod",
     "__pow", "__unm", "__len", "__lt", "__le",
Index: lvm.cxx
===================================================================
--- lvm.cxx	(revision 19384)
+++ lvm.cxx	(working copy)
@@ -138,21 +138,24 @@
     if (ttistable(t)) {  /* `t' is a table? */
       Table *h = hvalue(t);
       TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
-      if (!ttisnil(oldval) ||  /* result is no nil? */
-          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
+      /* oldval is nil=> look for newindex, oldval is not nil => look for usedindex */
+      tm = ttisnil(oldval) ? fasttm(L, h->metatable, TM_NEWINDEX)
+                           : fasttm(L, h->metatable, TM_USEDINDEX);
+      if (tm == NULL) { /* no tag method, set the value */
         setobj2t(L, oldval, val);
         luaC_barriert(L, h, val);
         return;
       }
       /* else will try the tag method */
     }
-    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
+    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) {
       luaG_typeerror(L, t, "index");
+    }
     if (ttisfunction(tm)) {
       callTM(L, tm, t, key, val);
       return;
     }
-    t = tm;  /* else repeat with `tm' */ 
+    t = tm; /* else repeat with `tm' */
   }
   luaG_runerror(L, "loop in settable");
 }
Index: lbaselib.cxx
===================================================================
--- lbaselib.cxx	(revision 19384)
+++ lbaselib.cxx	(working copy)
@@ -20,8 +20,6 @@
 #include "lualib.h"
 
 
-
-
 /*
 ** If your system does not support `stdout', you can just remove this function.
 ** If you need, you can define your own `print' function, following this
@@ -167,7 +165,7 @@
 
 
 static int luaB_rawget (lua_State *L) {
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "g");
   luaL_checkany(L, 2);
   lua_settop(L, 2);
   lua_rawget(L, 1);
@@ -175,7 +173,7 @@
 }
 
 static int luaB_rawset (lua_State *L) {
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "s");
   luaL_checkany(L, 2);
   luaL_checkany(L, 3);
   lua_settop(L, 3);
@@ -224,7 +222,7 @@
 
 
 static int luaB_next (lua_State *L) {
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "g");
   lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
   if (lua_next(L, 1))
     return 2;
@@ -255,7 +253,7 @@
 
 
 static int luaB_ipairs (lua_State *L) {
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "g");
   lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
   lua_pushvalue(L, 1);  /* state, */
   lua_pushinteger(L, 0);  /* and initial value */
@@ -341,7 +339,7 @@
 
 static int luaB_unpack (lua_State *L) {
   int i, e, n;
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "g");
   i = luaL_optint(L, 2, 1);
   e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
   if (i > e) return 0;  /* empty range */
Index: ltm.h
===================================================================
--- ltm.h	(revision 19384)
+++ ltm.h	(working copy)
@@ -18,6 +18,8 @@
 typedef enum {
   TM_INDEX,
   TM_NEWINDEX,
+  TM_USEDINDEX,
+  TM_RAWBLOCK,
   TM_GC,
   TM_MODE,
   TM_EQ,  /* last tag method with `fast' access */
Index: lapi.cxx
===================================================================
--- lapi.cxx	(revision 19384)
+++ lapi.cxx	(working copy)
@@ -1116,3 +1116,23 @@
   }
 }
 
+
+LUA_API int lua_rawblock(lua_State* L, int idx, const char* modes) {
+  Table* t;
+  StkId o = index2adr(L, idx);
+  if (!ttistable(o)) {
+    return 1; /* not a table, always blocked */
+  }
+  t = hvalue(o);
+  const TValue* tm = fasttm(L, t->metatable, TM_RAWBLOCK);
+  if ((tm != NULL) && ttisstring(tm)) {
+    TString* str = rawtsvalue(tm);
+    const char* s = getstr(str);
+    if (strpbrk(s, modes) != NULL) {
+      return 2; /* explicitly blocked */
+    }
+  }
+  return 0; /* not blocked */
+}
+
+
Index: lauxlib.cxx
===================================================================
--- lauxlib.cxx	(revision 19384)
+++ lauxlib.cxx	(working copy)
@@ -149,6 +149,21 @@
 }
 
 
+LUALIB_API void luaL_checkrawtable(lua_State *L, int t, const char* modes)
+{
+  const int retcode = lua_rawblock(L, t, modes);
+  if (retcode == 0) {
+    return;
+  }
+  else if (retcode == 1) {
+    tag_error(L, t, LUA_TTABLE);
+  }
+  else {
+    luaL_argerror(L, t, "raw table access blocked");
+  }
+}
+
+
 LUALIB_API void luaL_checkany (lua_State *L, int narg) {
   if (lua_type(L, narg) == LUA_TNONE)
     luaL_argerror(L, narg, "value expected");
Index: lua.h
===================================================================
--- lua.h	(revision 19384)
+++ lua.h	(working copy)
@@ -256,7 +256,9 @@
 LUA_API int   (lua_setuserdataextra) (lua_State* L, int idx, void* extra);
 LUA_API void* (lua_getuserdataextra) (lua_State* L, int idx);
 
+LUA_API int   (lua_rawblock) (lua_State* L, int idx, const char* modes);
 
+
 /* 
 ** ===============================================================
 ** some useful macros
Index: ltablib.cxx
===================================================================
--- ltablib.cxx	(revision 19384)
+++ ltablib.cxx	(working copy)
@@ -22,6 +22,7 @@
 static int foreachi (lua_State *L) {
   int i;
   int n = aux_getn(L, 1);
+  luaL_checkrawtable(L, 1, "g");
   luaL_checktype(L, 2, LUA_TFUNCTION);
   for (i=1; i <= n; i++) {
     lua_pushvalue(L, 2);  /* function */
@@ -37,7 +38,7 @@
 
 
 static int foreach (lua_State *L) {
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "g");
   luaL_checktype(L, 2, LUA_TFUNCTION);
   lua_pushnil(L);  /* first key */
   while (lua_next(L, 1)) {
@@ -55,7 +56,7 @@
 
 static int maxn (lua_State *L) {
   lua_Number max = 0;
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "g");
   lua_pushnil(L);  /* first key */
   while (lua_next(L, 1)) {
     lua_pop(L, 1);  /* remove value */
@@ -70,13 +71,14 @@
 
 
 static int getn (lua_State *L) {
+  luaL_checkrawtable(L, 1, "g");
   lua_pushinteger(L, aux_getn(L, 1));
   return 1;
 }
 
 
 static int setn (lua_State *L) {
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "gs");
 #ifndef luaL_setn
   luaL_setn(L, 1, luaL_checkint(L, 2));
 #else
@@ -90,6 +92,7 @@
 static int tinsert (lua_State *L) {
   int e = aux_getn(L, 1) + 1;  /* first empty element */
   int pos;  /* where to insert new element */
+  luaL_checkrawtable(L, 1, "gs");
   switch (lua_gettop(L)) {
     case 2: {  /* called with only 2 arguments */
       pos = e;  /* insert new element at the end */
@@ -118,6 +121,7 @@
 static int tremove (lua_State *L) {
   int e = aux_getn(L, 1);
   int pos = luaL_optint(L, 2, e);
+  luaL_checkrawtable(L, 1, "gs");
   if (!(1 <= pos && pos <= e))  /* position is outside bounds? */
    return 0;  /* nothing to remove */
   luaL_setn(L, 1, e - 1);  /* t.n = n-1 */
@@ -146,7 +150,7 @@
   size_t lsep;
   int i, last;
   const char *sep = luaL_optlstring(L, 2, "", &lsep);
-  luaL_checktype(L, 1, LUA_TTABLE);
+  luaL_checkrawtable(L, 1, "g");
   i = luaL_optint(L, 3, 1);
   last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));
   luaL_buffinit(L, &b);
@@ -255,6 +259,7 @@
 
 static int sort (lua_State *L) {
   int n = aux_getn(L, 1);
+  luaL_checkrawtable(L, 1, "gs");
   luaL_checkstack(L, 40, "");  /* assume array is smaller than 2^40 */
   if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */
     luaL_checktype(L, 2, LUA_TFUNCTION);
