Fix segfault by initialization of BaseHolder type

This commit is contained in:
mihacooper 2017-01-23 15:07:20 +03:00
parent ca6ffd040d
commit df871d3c8e
4 changed files with 49 additions and 69 deletions

View File

@ -22,7 +22,8 @@ void SharedTable::set(StoredObject key, StoredObject value) noexcept {
}
void SharedTable::luaSet(sol::stack_object luaKey, sol::stack_object luaValue) noexcept {
assert(luaKey.valid());
if (!luaKey.valid())
throw sol::error("Invalid table index");
StoredObject key(luaKey);
if (luaValue.get_type() == sol::type::nil) {

View File

@ -17,24 +17,19 @@ template<typename StoredType>
class PrimitiveHolder : public BaseHolder {
public:
PrimitiveHolder(sol::stack_object luaObject) noexcept
: data_(luaObject.as<StoredType>()) {}
: BaseHolder(luaObject.get_type()), data_(luaObject.as<StoredType>()) {}
PrimitiveHolder(sol::object luaObject) noexcept
: data_(luaObject.as<StoredType>()) {}
: BaseHolder(luaObject.get_type()), data_(luaObject.as<StoredType>()) {}
PrimitiveHolder(const StoredType& init) noexcept
: data_(init) {}
PrimitiveHolder(sol::type type, const StoredType& init) noexcept
: BaseHolder(type), data_(init) {}
bool rawCompare(const BaseHolder* other) const noexcept final {
assert(type_ == other->type());
return static_cast<const PrimitiveHolder<StoredType>*>(other)->data_ == data_;
}
bool rawLess(const BaseHolder* other) const noexcept final {
assert(type_ == other->type());
return data_ < static_cast<const PrimitiveHolder<StoredType>*>(other)->data_;
}
std::size_t hash() const noexcept final {
return std::hash<StoredType>()(data_);
}
@ -50,7 +45,8 @@ private:
class FunctionHolder : public BaseHolder {
public:
template<typename SolObject>
FunctionHolder(SolObject luaObject) noexcept {
FunctionHolder(SolObject luaObject) noexcept
: BaseHolder(sol::type::function) {
sol::state_view lua(luaObject.lua_state());
sol::function dumper = lua["string"]["dump"];
@ -62,10 +58,6 @@ public:
return function_ == static_cast<const FunctionHolder*>(other)->function_;
}
bool rawLess(const BaseHolder* other) const noexcept final {
return function_ < static_cast<const FunctionHolder*>(other)->function_;
}
std::size_t hash() const noexcept final {
return std::hash<std::string>()(function_);
}
@ -149,7 +141,7 @@ std::unique_ptr<BaseHolder> fromSolObject(SolObject luaObject) {
// SolTableToShared is used to prevent from infinity recursion
// in recursive tables
dumpTable(table, luaTable, visited);
return std::make_unique<PrimitiveHolder<SharedTable*>>(table);
return std::make_unique<PrimitiveHolder<SharedTable*>>(sol::type::userdata, table);
}
default:
ERROR << "Unable to store object of that type: " << (int)luaObject.get_type() << std::endl;
@ -163,7 +155,7 @@ StoredObject::StoredObject(StoredObject&& init) noexcept
: data_(std::move(init.data_)) {}
StoredObject::StoredObject(SharedTable* table) noexcept
: data_(new PrimitiveHolder<SharedTable*>(table)) {
: data_(new PrimitiveHolder<SharedTable*>(sol::type::userdata, table)) {
}
StoredObject::StoredObject(sol::object object) noexcept
@ -204,11 +196,4 @@ bool StoredObject::operator==(const StoredObject& o) const noexcept {
return data_.get() == o.data_.get();
}
bool StoredObject::operator<(const StoredObject& o) const noexcept {
if (data_)
return data_->less(o.data_.get());
else
return data_.get() < o.data_.get();
}
} // effil

View File

@ -9,7 +9,7 @@ namespace effil {
class BaseHolder {
public:
BaseHolder() noexcept : type_(sol::type::nil) {}
BaseHolder(sol::type t) noexcept : type_(t) {}
virtual ~BaseHolder() = default;
sol::type type() const noexcept {
@ -20,13 +20,8 @@ public:
assert(other != nullptr);
return type_ == other->type_ && rawCompare(other);
}
virtual bool less(const BaseHolder* other) const noexcept {
assert(other != nullptr);
return type_ < other->type_ && rawLess(other);
}
virtual bool rawCompare(const BaseHolder* other) const noexcept = 0;
virtual bool rawLess(const BaseHolder* other) const noexcept = 0;
virtual std::size_t hash() const noexcept = 0;
virtual sol::object unpack(sol::this_state state) const noexcept = 0;
@ -53,7 +48,6 @@ public:
sol::object unpack(sol::this_state state) const noexcept;
StoredObject& operator=(StoredObject&& o) noexcept;
bool operator==(const StoredObject& o) const noexcept;
bool operator<(const StoredObject& o) const noexcept;
private:
std::unique_ptr<BaseHolder> data_;

View File

@ -34,12 +34,12 @@ st.del = "secret"
st.del = nil
)");
ASSERT_TRUE(res1.valid()) << "Set res1 failed";
ASSERT_EQ(lua["st"]["fst"], std::string("first"));
ASSERT_EQ(lua["st"]["snd"], (double)2);
ASSERT_EQ(lua["st"]["thr"], true);
ASSERT_EQ(lua["st"]["del"], sol::nil);
ASSERT_EQ(lua["st"]["nex"], sol::nil);
EXPECT_TRUE(res1.valid()) << "Set res1 failed";
EXPECT_EQ(lua["st"]["fst"], std::string("first"));
EXPECT_EQ(lua["st"]["snd"], (double)2);
EXPECT_EQ(lua["st"]["thr"], true);
EXPECT_EQ(lua["st"]["del"], sol::nil);
EXPECT_EQ(lua["st"]["nex"], sol::nil);
auto res2 = lua.script(R"(
st[1] = 3
@ -50,20 +50,20 @@ st[42] = nil
st.deleted = st[42] == nil
)");
ASSERT_TRUE(res2.valid()) << "Set res2 failed";
ASSERT_EQ(lua["st"][1], 3);
ASSERT_EQ(lua["st"][2], std::string("number"));
ASSERT_EQ(lua["st"][-1], false);
ASSERT_EQ(lua["st"]["deleted"], true);
EXPECT_TRUE(res2.valid()) << "Set res2 failed";
EXPECT_EQ(lua["st"][1], 3);
EXPECT_EQ(lua["st"][2], std::string("number"));
EXPECT_EQ(lua["st"][-1], false);
EXPECT_EQ(lua["st"]["deleted"], true);
auto res3 = lua.script(R"(
st[true] = false
st[false] = 9
)");
ASSERT_TRUE(res3.valid()) << "Set res3 failed";
ASSERT_EQ(lua["st"][true], false);
ASSERT_EQ(lua["st"][false], 9);
EXPECT_TRUE(res3.valid()) << "Set res3 failed";
EXPECT_EQ(lua["st"][true], false);
EXPECT_EQ(lua["st"][false], 9);
}
TEST(sharedTable, multipleStates) {
@ -82,9 +82,9 @@ cats.sparky = false
cats.wow = 3
)");
ASSERT_EQ(lua2["dogs"]["fluffy"], std::string("gav"));
ASSERT_EQ(lua2["dogs"]["sparky"], false);
ASSERT_EQ(lua2["dogs"]["wow"], 3);
EXPECT_EQ(lua2["dogs"]["fluffy"], std::string("gav"));
EXPECT_EQ(lua2["dogs"]["sparky"], false);
EXPECT_EQ(lua2["dogs"]["wow"], 3);
}
TEST(sharedTable, multipleThreads) {
@ -126,9 +126,9 @@ st.thr = true)");
for(auto& thread : threads) { thread.join(); }
ASSERT_EQ(lua["st"]["fst"], true);
ASSERT_EQ(lua["st"]["snd"], true);
ASSERT_EQ(lua["st"]["thr"], true);
EXPECT_EQ(lua["st"]["fst"], true);
EXPECT_EQ(lua["st"]["snd"], true);
EXPECT_EQ(lua["st"]["thr"], true);
}
TEST(sharedTable, playingWithSharedTables) {
@ -146,8 +146,8 @@ st1.proxy.value = true
recursive.next = recursive
recursive.val = "yes"
)");
ASSERT_EQ(lua["st2"]["value"], true);
ASSERT_EQ(lua["recursive"]["next"]["next"]["next"]["val"], std::string("yes"));
EXPECT_EQ(lua["st2"]["value"], true);
EXPECT_EQ(lua["recursive"]["next"]["next"]["next"]["val"], std::string("yes"));
}
TEST(sharedTable, playingWithFunctions) {
@ -166,7 +166,7 @@ st.fn()
)");
sol::function sf = lua["st"]["fn"];
ASSERT_TRUE((bool)sf());
EXPECT_TRUE((bool)sf());
sol::state lua2;
bootstrapState(lua2);
@ -180,7 +180,7 @@ end
sol::function sf2 = lua["st"]["fn2"];
ASSERT_EQ(sf2(std::string("SUCCESS")).get<std::string>(), std::string("*SUCCESS*"));
EXPECT_EQ(sf2(std::string("SUCCESS")).get<std::string>(), std::string("*SUCCESS*"));
}
TEST(sharedTable, playingWithTables) {
@ -207,15 +207,15 @@ recursive.val = "recursive"
st.recursive = recursive
)");
ASSERT_TRUE(res.valid());
ASSERT_EQ(lua["st"]["person"]["name"], std::string("John Doe"));
ASSERT_EQ(lua["st"]["person"]["age"], 25);
ASSERT_EQ(lua["st"]["pet"]["type"], std::string("cat"));
ASSERT_EQ(lua["st"]["pet"]["name"], std::string("Tomas"));
ASSERT_EQ(lua["st"]["pet"]["real"], std::string("Яша"));
ASSERT_EQ(lua["st"]["pet"]["spec"]["colour"], std::string("grey"));
ASSERT_EQ(lua["st"]["pet"]["spec"]["legs"], 4);
ASSERT_EQ(lua["st"]["recursive"]["prev"]["next"]["next"]["val"], std::string("recursive"));
EXPECT_TRUE(res.valid());
EXPECT_EQ(lua["st"]["person"]["name"], std::string("John Doe"));
EXPECT_EQ(lua["st"]["person"]["age"], 25);
EXPECT_EQ(lua["st"]["pet"]["type"], std::string("cat"));
EXPECT_EQ(lua["st"]["pet"]["name"], std::string("Tomas"));
EXPECT_EQ(lua["st"]["pet"]["real"], std::string("Яша"));
EXPECT_EQ(lua["st"]["pet"]["spec"]["colour"], std::string("grey"));
EXPECT_EQ(lua["st"]["pet"]["spec"]["legs"], 4);
EXPECT_EQ(lua["st"]["recursive"]["prev"]["next"]["next"]["val"], std::string("recursive"));
defaultPool().clear();
}
@ -233,16 +233,16 @@ for i = 1, 1000000 do
end
)");
ASSERT_TRUE(res1.valid());
ASSERT_TRUE(st.size() == 1'000'000);
EXPECT_TRUE(res1.valid());
EXPECT_TRUE(st.size() == 1'000'000);
auto res2 = lua.script(R"(
for i = 1000000, 1, -1 do
st[i] = nil
end
)");
ASSERT_TRUE(res2.valid());
ASSERT_TRUE(st.size() == 0);
EXPECT_TRUE(res2.valid());
EXPECT_TRUE(st.size() == 0);
}
TEST(sharedTable, stressWithThreads) {
@ -272,6 +272,6 @@ TEST(sharedTable, stressWithThreads) {
bootstrapState(lua);
lua["st"] = &st;
for(size_t i = 0; i < threadCount; i++) {
ASSERT_TRUE(lua["st"][i] == 100'001) << (double)lua["st"][i] << std::endl;
EXPECT_TRUE(lua["st"][i] == 100'001) << (double)lua["st"][i] << std::endl;
}
}