Add proper sanitizing for input to SQLite database.

Adds function `ExecuteQueryWithArgs(query, ...)` to allow for queries 
with user input.

There is a known issue, that the funciton does not work with 
std::string. All strings must be converted to c strings.
This commit is contained in:
TheMatt2 2022-01-05 21:52:33 -05:00
parent f7b3a1ef10
commit 590ccc78aa
3 changed files with 137 additions and 119 deletions

View File

@ -40,4 +40,18 @@ namespace CDClientDatabase {
*/ */
CppSQLite3Query ExecuteQuery(const std::string& query); CppSQLite3Query ExecuteQuery(const std::string& query);
//! Queries the CDClient and parses arguments
/*!
\param query The query with formatted arguments
\return the results of the query
*/
// Due to the template, implementation must be in the header.
template <typename... Args>
CppSQLite3Query ExecuteQueryWithArgs(const std::string& query, Args... args) {
CppSQLite3Buffer sqlBuf;
sqlBuf.format(query.c_str(), args...);
std::string safe_query = (const char *) sqlBuf;
return ExecuteQuery(safe_query);
}
}; };

View File

@ -352,19 +352,20 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
} }
} }
std::stringstream query; CppSQLite3Query result;
if (!type.empty()) if (!type.empty())
{ {
query << "SELECT effectName FROM BehaviorEffect WHERE effectType = '" << typeString << "' AND effectID = " << std::to_string(effectId) << ";"; result = CDClientDatabase::ExecuteQueryWithArgs(
"SELECT effectName FROM BehaviorEffect WHERE effectType = %Q AND effectID = %u;",
typeString.c_str(), effectId);
} }
else else
{ {
query << "SELECT effectName, effectType FROM BehaviorEffect WHERE effectID = " << std::to_string(effectId) << ";"; result = CDClientDatabase::ExecuteQueryWithArgs(
"SELECT effectName, effectType FROM BehaviorEffect WHERE effectID = %u;",
effectId);
} }
auto result = CDClientDatabase::ExecuteQuery(query.str());
if (result.eof() || result.fieldIsNull(0)) if (result.eof() || result.fieldIsNull(0))
{ {
return; return;

View File

@ -301,7 +301,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
return; return;
} }
if ((chatCommand == "leave-zone")) { if (chatCommand == "leave-zone") {
const auto currentZone = dZoneManager::Instance()->GetZone()->GetZoneID().GetMapID(); const auto currentZone = dZoneManager::Instance()->GetZone()->GetZoneID().GetMapID();
auto newZone = 1100; auto newZone = 1100;
@ -354,7 +354,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}); });
} }
if ((chatCommand == "join" && !args.empty())) { if (chatCommand == "join" && !args.empty()) {
ChatPackets::SendSystemMessage(sysAddr, u"Requesting private map..."); ChatPackets::SendSystemMessage(sysAddr, u"Requesting private map...");
const auto& password = args[0]; const auto& password = args[0];
@ -1243,8 +1243,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
} }
if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) {
std::string query = "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE '%" + args[0] + "%' OR `name` LIKE '%" + args[0] + "%' OR `description` LIKE '%" + args[0] + "%'"; std::string query = "%" + args[0] + "%";
auto tables = CDClientDatabase::ExecuteQuery(query.c_str()); const char* query_cstr = query.c_str();
auto tables = CDClientDatabase::ExecuteQueryWithArgs(
"SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE %Q OR `name` LIKE %Q OR `description` LIKE %Q LIMIT 50",
query_cstr, query_cstr, query_cstr);
while (!tables.eof()) { while (!tables.eof()) {
std::string message = std::to_string(tables.getIntField(0)) + " - " + tables.getStringField(1); std::string message = std::to_string(tables.getIntField(0)) + " - " + tables.getStringField(1);
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message, message.size())); ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message, message.size()));
@ -2010,4 +2014,3 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std::
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
} }