diff options
author | Max Kellermann <max@musicpd.org> | 2019-02-20 20:31:08 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2019-02-20 20:50:28 +0100 |
commit | cc28a7b67fcfe006b49171343eaf37f5862014da (patch) | |
tree | 8ec76f4a82e22f688ee83db70cb81b964063d656 /src/Main.cxx | |
parent | 8b5c33cecdb1e41b08d8141222f6dba50a836889 (diff) |
Main: create Database on stack, move to Instance after Open() succeeded
This fixes use-after-free bug in SimpleDatabase::Close(), accessing
the `root` object which was already freed by the `catch` block in
Open().
By having the Database on the stack first, we can avoid calling
Close() on the failed-to-open Database from Instance's destructor.
Closes #482
Diffstat (limited to 'src/Main.cxx')
-rw-r--r-- | src/Main.cxx | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/src/Main.cxx b/src/Main.cxx index 87bda1734..686813c1c 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -185,18 +185,16 @@ InitStorage(const ConfigData &config, EventLoop &event_loop) static bool glue_db_init_and_load(const ConfigData &config) { - instance->database = - CreateConfiguredDatabase(config, instance->event_loop, - instance->io_thread.GetEventLoop(), - *instance); - if (instance->database == nullptr) + auto db = CreateConfiguredDatabase(config, instance->event_loop, + instance->io_thread.GetEventLoop(), + *instance); + if (!db) return true; - if (instance->database->GetPlugin().RequireStorage()) { + if (db->GetPlugin().RequireStorage()) { InitStorage(config, instance->io_thread.GetEventLoop()); if (instance->storage == nullptr) { - instance->database.reset(); LogDefault(config_domain, "Found database setting without " "music_directory - disabling database"); @@ -210,22 +208,24 @@ glue_db_init_and_load(const ConfigData &config) } try { - instance->database->Open(); + db->Open(); } catch (...) { std::throw_with_nested(std::runtime_error("Failed to open database plugin")); } - auto *db = dynamic_cast<SimpleDatabase *>(instance->database.get()); - if (db == nullptr) + instance->database = std::move(db); + + auto *sdb = dynamic_cast<SimpleDatabase *>(instance->database.get()); + if (sdb == nullptr) return true; instance->update = new UpdateService(config, - instance->event_loop, *db, + instance->event_loop, *sdb, static_cast<CompositeStorage &>(*instance->storage), *instance); /* run database update after daemonization? */ - return db->FileExists(); + return sdb->FileExists(); } static bool |