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 { 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); StoredObject key(luaKey);
if (luaValue.get_type() == sol::type::nil) { if (luaValue.get_type() == sol::type::nil) {

View File

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

View File

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

View File

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