From e401cc1c5533061e266314e6bc36055a106de678 Mon Sep 17 00:00:00 2001 From: server Date: Mon, 13 Apr 2026 23:04:35 +0200 Subject: [PATCH] game: escape highscore and award inputs --- src/game/db.cpp | 16 +++++++++++++++- src/game/db.h | 1 + src/game/questlua.cpp | 8 ++++++-- src/game/questlua_pc.cpp | 35 +++++++++++++++++++++++------------ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/game/db.cpp b/src/game/db.cpp index f452597..b39c962 100644 --- a/src/game/db.cpp +++ b/src/game/db.cpp @@ -625,8 +625,11 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg) } if (bQuery) + { + const std::string escapedBoard = EscapeStringCopy(info->szBoard, strnlen(info->szBoard, sizeof(info->szBoard))); Query("REPLACE INTO highscore%s VALUES('%s', %u, %d)", - get_table_postfix(), info->szBoard, info->dwPID, info->iValue); + get_table_postfix(), escapedBoard.c_str(), info->dwPID, info->iValue); + } M2_DELETE(info); } @@ -684,6 +687,17 @@ size_t DBManager::EscapeString(char* dst, size_t dstSize, const char *src, size_ return m_sql_direct.EscapeString(dst, dstSize, src, srcSize); } +std::string DBManager::EscapeStringCopy(const char* src, size_t srcSize) +{ + if (!src || srcSize == 0) + return {}; + + std::string escaped(srcSize * 2 + 1, '\0'); + size_t escapedSize = m_sql_direct.EscapeString(escaped.data(), escaped.size(), src, srcSize); + escaped.resize(escapedSize); + return escaped; +} + // // Common SQL // diff --git a/src/game/db.h b/src/game/db.h index 1f870da..54ab722 100644 --- a/src/game/db.h +++ b/src/game/db.h @@ -98,6 +98,7 @@ class DBManager : public singleton template void FuncAfterQuery(Functor f, const char * c_pszFormat, ...); // 끝나고 나면 f가 호출됨 void f(void) 형태 size_t EscapeString(char* dst, size_t dstSize, const char *src, size_t srcSize); + std::string EscapeStringCopy(const char* src, size_t srcSize); private: SQLMsg * PopResult(); diff --git a/src/game/questlua.cpp b/src/game/questlua.cpp index 290c75a..9115adf 100644 --- a/src/game/questlua.cpp +++ b/src/game/questlua.cpp @@ -209,12 +209,14 @@ namespace quest { CQuestManager & q = CQuestManager::instance(); const char * pszBoardName = lua_tostring(L, 1); + const std::string escapedBoardName = DBManager::instance().EscapeStringCopy( + pszBoardName ? pszBoardName : "", pszBoardName ? strlen(pszBoardName) : 0); DWORD mypid = q.GetCurrentCharacterPtr()->GetPlayerID(); bool bOrder = (int) lua_tonumber(L, 2) != 0 ? true : false; DBManager::instance().ReturnQuery(QID_HIGHSCORE_SHOW, mypid, NULL, "SELECT h.pid, p.name, h.value FROM highscore%s as h, player%s as p WHERE h.board = '%s' AND h.pid = p.id ORDER BY h.value %s LIMIT 10", - get_table_postfix(), get_table_postfix(), pszBoardName, bOrder ? "DESC" : ""); + get_table_postfix(), get_table_postfix(), escapedBoardName.c_str(), bOrder ? "DESC" : ""); return 0; } @@ -228,9 +230,11 @@ namespace quest qi->dwPID = q.GetCurrentCharacterPtr()->GetPlayerID(); qi->iValue = (int) lua_tonumber(L, 2); qi->bOrder = (int) lua_tonumber(L, 3); + const std::string escapedBoard = DBManager::instance().EscapeStringCopy( + qi->szBoard, strnlen(qi->szBoard, sizeof(qi->szBoard))); DBManager::instance().ReturnQuery(QID_HIGHSCORE_REGISTER, qi->dwPID, qi, - "SELECT value FROM highscore%s WHERE board='%s' AND pid=%u", get_table_postfix(), qi->szBoard, qi->dwPID); + "SELECT value FROM highscore%s WHERE board='%s' AND pid=%u", get_table_postfix(), escapedBoard.c_str(), qi->dwPID); return 1; } diff --git a/src/game/questlua_pc.cpp b/src/game/questlua_pc.cpp index 34a7c09..e183e5f 100644 --- a/src/game/questlua_pc.cpp +++ b/src/game/questlua_pc.cpp @@ -2784,16 +2784,20 @@ teleport_area: DWORD dwVnum = (int) lua_tonumber(L, 1); int icount = (int) lua_tonumber(L, 2); + const char* login = ch->GetDesc()->GetAccountTable().login; + const char* why = lua_tostring(L, 3); + const std::string escapedLogin = DBManager::instance().EscapeStringCopy(login ? login : "", login ? strlen(login) : 0); + const std::string escapedWhy = DBManager::instance().EscapeStringCopy(why ? why : "", why ? strlen(why) : 0); sys_log(0, "QUEST [award] item %d to login %s", dwVnum, ch->GetDesc()->GetAccountTable().login); DBManager::instance().Query("INSERT INTO item_award (login, vnum, count, given_time, why, mall)select '%s', %d, %d, now(), '%s', 1 from DUAL where not exists (select login, why from item_award where login = '%s' and why = '%s') ;", - ch->GetDesc()->GetAccountTable().login, + escapedLogin.c_str(), dwVnum, icount, - lua_tostring(L,3), - ch->GetDesc()->GetAccountTable().login, - lua_tostring(L,3)); + escapedWhy.c_str(), + escapedLogin.c_str(), + escapedWhy.c_str()); lua_pushnumber (L, 0); return 1; @@ -2812,19 +2816,26 @@ teleport_area: DWORD dwVnum = (int) lua_tonumber(L, 1); int icount = (int) lua_tonumber(L, 2); + const char* login = ch->GetDesc()->GetAccountTable().login; + const char* why = lua_tostring(L, 3); + long socket0 = strtol(lua_tostring(L, 4), nullptr, 10); + long socket1 = strtol(lua_tostring(L, 5), nullptr, 10); + long socket2 = strtol(lua_tostring(L, 6), nullptr, 10); + const std::string escapedLogin = DBManager::instance().EscapeStringCopy(login ? login : "", login ? strlen(login) : 0); + const std::string escapedWhy = DBManager::instance().EscapeStringCopy(why ? why : "", why ? strlen(why) : 0); sys_log(0, "QUEST [award] item %d to login %s", dwVnum, ch->GetDesc()->GetAccountTable().login); - DBManager::instance().Query("INSERT INTO item_award (login, vnum, count, given_time, why, mall, socket0, socket1, socket2)select '%s', %d, %d, now(), '%s', 1, %s, %s, %s from DUAL where not exists (select login, why from item_award where login = '%s' and why = '%s') ;", - ch->GetDesc()->GetAccountTable().login, + DBManager::instance().Query("INSERT INTO item_award (login, vnum, count, given_time, why, mall, socket0, socket1, socket2)select '%s', %d, %d, now(), '%s', 1, %ld, %ld, %ld from DUAL where not exists (select login, why from item_award where login = '%s' and why = '%s') ;", + escapedLogin.c_str(), dwVnum, icount, - lua_tostring(L,3), - lua_tostring(L,4), - lua_tostring(L,5), - lua_tostring(L,6), - ch->GetDesc()->GetAccountTable().login, - lua_tostring(L,3)); + escapedWhy.c_str(), + socket0, + socket1, + socket2, + escapedLogin.c_str(), + escapedWhy.c_str()); lua_pushnumber (L, 0); return 1;