Some more error checking for class names and tangible IDs
This commit is contained in:
@@ -10,6 +10,10 @@ LuaSpecial LuaRegistry(LUA_REGISTRYINDEX);
|
||||
LuaNilMarker LuaNil;
|
||||
LuaNewTableMarker LuaNewTable;
|
||||
|
||||
inline bool ascii_islower(char c) { return (c >= 'a') && (c <= 'z'); }
|
||||
inline bool ascii_isupper(char c) { return (c >= 'A') && (c <= 'Z'); }
|
||||
inline bool ascii_isdigit(char c) { return (c >= '0') && (c <= '9'); }
|
||||
|
||||
LuaFunctionReg::LuaFunctionReg(const char *n, const char *a, const char *d, bool s, lua_CFunction f) {
|
||||
name_ = n;
|
||||
args_ = a;
|
||||
@@ -220,12 +224,30 @@ lua_State *LuaCoreStack::newthread(LuaSlot target) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LuaCoreStack::validclassname(std::string_view cname) {
|
||||
if (cname.empty()) return false;
|
||||
if (cname == "_G") return false;
|
||||
bool LuaCoreStack::valididentifier(std::string_view str) {
|
||||
if (str.size() == 0) return false;
|
||||
char c=str[0];
|
||||
if ((!ascii_islower(c)) && (!ascii_isupper(c)) && (c!='_')) return false;
|
||||
for (int i = 1; i < int(str.size()); i++) {
|
||||
char c = str[i];
|
||||
if ((!ascii_islower(c)) && (!ascii_isupper(c)) && (!ascii_isdigit(c)) && (c!='_')) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaCoreStack::validint64(int64_t value) {
|
||||
return (value <= MAXINT) && (value >= -MAXINT);
|
||||
}
|
||||
|
||||
bool LuaCoreStack::validpositiveint64(int64_t value) {
|
||||
return (value <= MAXINT) && (value >= 1);
|
||||
}
|
||||
|
||||
bool LuaCoreStack::validclassname(std::string_view cname) {
|
||||
if (cname == "_G") return false;
|
||||
return valididentifier(cname);
|
||||
}
|
||||
|
||||
bool LuaCoreStack::validclassname(LuaSlot slot) const {
|
||||
if (!isstring(slot)) return false;
|
||||
return validclassname(ckstring(slot));
|
||||
@@ -352,6 +374,8 @@ void LuaCoreStack::makeclass(LuaSlot tab, std::string_view name) const {
|
||||
}
|
||||
|
||||
void LuaCoreStack::maketan(LuaSlot tab, int64_t id) const {
|
||||
assert(validpositiveint64(id));
|
||||
|
||||
LuaVar tangibles, metatab;
|
||||
LuaExtStack LS(L_, tangibles, metatab);
|
||||
|
||||
@@ -412,6 +436,20 @@ int64_t LuaCoreStack::tanid(LuaSlot tab) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LuaCoreStack::tangetclass(LuaSlot classobj, LuaSlot tab) {
|
||||
if (istable(tab) && (gettabletype(tab) == LUA_TT_TANGIBLE) && lua_getmetatable(L_, tab.index())) {
|
||||
lua_pushstring(L_, "__index");
|
||||
lua_rawget(L_, -2);
|
||||
lua_replace(L_, classobj);
|
||||
lua_pop(L_, 1);
|
||||
if (istable(classobj) && (gettabletype(classobj) == LUA_TT_CLASS)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
set(classobj, LuaNil);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LuaCoreStack::issortablekey(LuaSlot s) const {
|
||||
int type = lua_type(L_, s);
|
||||
return (type == LUA_TBOOLEAN) || (type == LUA_TNUMBER) || (type == LUA_TSTRING);
|
||||
|
||||
@@ -417,6 +417,15 @@ public:
|
||||
|
||||
int next(LuaSlot tab, LuaSlot key, LuaSlot value) const;
|
||||
|
||||
// Return true if the string is a valid lua identifier.
|
||||
static bool valididentifier(std::string_view id);
|
||||
|
||||
// Return true if the int64 can be stored losslessly in a lua_Number.
|
||||
static bool validint64(int64_t value);
|
||||
|
||||
// Return true if the int64 is storable in lua and is positive.
|
||||
static bool validpositiveint64(int64_t value);
|
||||
|
||||
// Return true if the classname is legal.
|
||||
bool validclassname(LuaSlot value) const;
|
||||
static bool validclassname(std::string_view cname);
|
||||
@@ -446,6 +455,9 @@ public:
|
||||
// stub into a full blown tangible, and World::tangible_delete to turn
|
||||
// a full-blown tangible back into a stub. A stub doesn't have a
|
||||
// class or a thread table.
|
||||
//
|
||||
// Assert-fails if the tangible ID is not a validpositiveint64.
|
||||
//
|
||||
void maketan(LuaSlot tab, int64_t id) const;
|
||||
|
||||
// Return true if a tangible is empty (deleted or not yet created).
|
||||
@@ -454,6 +466,9 @@ public:
|
||||
// Get the ID of a tangible.
|
||||
int64_t tanid(LuaSlot tab) const;
|
||||
|
||||
// Get the class of a tangible.
|
||||
bool tangetclass(LuaSlot classobj, LuaSlot tan);
|
||||
|
||||
// Return true if the value is a sortable key (string, number, or boolean).
|
||||
bool issortablekey(LuaSlot s) const;
|
||||
|
||||
|
||||
@@ -80,11 +80,19 @@ class Deserializer {
|
||||
return;
|
||||
}
|
||||
case LUA_TT_TANGIBLE: {
|
||||
LS_.maketan(target, sb_->read_int64());
|
||||
int64_t tanid = sb_->read_int64();
|
||||
if (!LS_.validpositiveint64(tanid)) {
|
||||
throw DeserializeError();
|
||||
}
|
||||
LS_.maketan(target, tanid);
|
||||
return;
|
||||
}
|
||||
case LUA_TT_CLASS: {
|
||||
LS_.makeclass(target, sb_->read_string());
|
||||
eng::string name = sb_->read_string();
|
||||
if (!LS_.validclassname(name)) {
|
||||
throw DeserializeError();
|
||||
}
|
||||
LS_.makeclass(target, name);
|
||||
return;
|
||||
}
|
||||
case LUA_PK_REFERENCE: {
|
||||
|
||||
@@ -21,9 +21,6 @@ LuaDefine(makeclass, "classname", "create a class if it doesn't already exist")
|
||||
LuaArg classname;
|
||||
LuaRet classtab;
|
||||
LuaDefStack LS(L, classname, classtab);
|
||||
if (!LS.isstring(classname)) {
|
||||
luaL_error(L, "class name must be a string");
|
||||
}
|
||||
if (!LS.validclassname(classname)) {
|
||||
luaL_error(L, "invalid class name: %s", LS.ckstring(classname).c_str());
|
||||
};
|
||||
|
||||
@@ -178,14 +178,7 @@ int common_prefix_length(string_view a, string_view b) {
|
||||
}
|
||||
|
||||
bool is_lua_id(string_view str) {
|
||||
if (str.size() == 0) return false;
|
||||
char c=str[0];
|
||||
if ((!ascii_isalpha(c)) && (c!='_')) return false;
|
||||
for (int i = 1; i < int(str.size()); i++) {
|
||||
char c = str[i];
|
||||
if ((!ascii_isalpha(c)) && (!ascii_isdigit(c)) && (c!='_')) return false;
|
||||
}
|
||||
return true;
|
||||
return LuaCoreStack::valididentifier(str);
|
||||
}
|
||||
|
||||
bool is_lua_comment(string_view s) {
|
||||
|
||||
@@ -227,13 +227,12 @@ LuaDefine(tangible_getclass, "tan",
|
||||
"|The return value is a string, the class name, not"
|
||||
"|the class table.") {
|
||||
LuaArg tanobj;
|
||||
LuaVar mt, classtab;
|
||||
LuaVar classtab;
|
||||
LuaRet classname;
|
||||
LuaDefStack LS(L, tanobj, mt, classtab, classname);
|
||||
LuaDefStack LS(L, tanobj, classtab, classname);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
w->tangible_get(LS, tanobj, false);
|
||||
LS.getmetatable(mt, tanobj);
|
||||
LS.rawget(classtab, mt, "__index");
|
||||
LS.tangetclass(classtab, tanobj);
|
||||
eng::string name = LS.classname(classtab);
|
||||
if (name == "") {
|
||||
LS.set(classname, LuaNil);
|
||||
|
||||
@@ -141,7 +141,7 @@ Tangible *World::tangible_get(const LuaCoreStack &LS, LuaSlot tab, bool allowdel
|
||||
}
|
||||
|
||||
Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_t id) {
|
||||
assert(id != 0);
|
||||
assert(LS0.validpositiveint64(id));
|
||||
LuaVar metatab;
|
||||
LuaExtStack LS(LS0.state(), metatab);
|
||||
|
||||
|
||||
@@ -58,11 +58,17 @@ eng::string World::tangible_ids_debug_string() const {
|
||||
}
|
||||
|
||||
eng::string World::tangibles_near_debug_string(int64_t actor, int64_t distance) {
|
||||
assert(stack_is_clear());
|
||||
lua_State *L = state();
|
||||
LuaVar tangibles, database, mt;
|
||||
LuaExtStack LS(L, tangibles, database);
|
||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||
eng::ostringstream result;
|
||||
util::IdVector tans;
|
||||
get_near(actor, distance, true, false, true, &tans);
|
||||
for (int64_t id : tans) {
|
||||
const Tangible *tan = tangible_get(id);
|
||||
LS.rawget(database, tangibles, id);
|
||||
AnimState state = tan->anim_queue_.get_final_everything();
|
||||
result << id << ": " << state.debug_string() << std::endl;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user