diff --git a/src/db/ClientManager.cpp b/src/db/ClientManager.cpp index fff7e06..48b904a 100644 --- a/src/db/ClientManager.cpp +++ b/src/db/ClientManager.cpp @@ -626,17 +626,22 @@ void CClientManager::QUERY_QUEST_SAVE(CPeer * pkPeer, TQuestTable * pTable, DWOR for (int i = 0; i < iSize; ++i, ++pTable) { + const std::string escapedQuestName = CDBManager::instance().EscapeStringCopy( + pTable->szName, strnlen(pTable->szName, sizeof(pTable->szName))); + const std::string escapedQuestState = CDBManager::instance().EscapeStringCopy( + pTable->szState, strnlen(pTable->szState, sizeof(pTable->szState))); + if (pTable->lValue == 0) { snprintf(szQuery, sizeof(szQuery), "DELETE FROM quest%s WHERE dwPID=%d AND szName='%s' AND szState='%s'", - GetTablePostfix(), pTable->dwPID, pTable->szName, pTable->szState); + GetTablePostfix(), pTable->dwPID, escapedQuestName.c_str(), escapedQuestState.c_str()); } else { snprintf(szQuery, sizeof(szQuery), "REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(%d, '%s', '%s', %ld)", - GetTablePostfix(), pTable->dwPID, pTable->szName, pTable->szState, static_cast(pTable->lValue)); + GetTablePostfix(), pTable->dwPID, escapedQuestName.c_str(), escapedQuestState.c_str(), static_cast(pTable->lValue)); } CDBManager::instance().ReturnQuery(szQuery, QID_QUEST_SAVE, pkPeer->GetHandle(), NULL); diff --git a/src/db/ClientManagerPlayer.cpp b/src/db/ClientManagerPlayer.cpp index 001ca92..bd96747 100644 --- a/src/db/ClientManagerPlayer.cpp +++ b/src/db/ClientManagerPlayer.cpp @@ -91,6 +91,7 @@ bool CreateItemTableFromRes(MYSQL_RES * res, std::vector * pVec, DW size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * pkTab) { size_t queryLen; + const std::string escapedIp = CDBManager::instance().EscapeStringCopy(pkTab->ip, strnlen(pkTab->ip, sizeof(pkTab->ip))); queryLen = snprintf(pszQuery, querySize, "UPDATE player%s SET " @@ -164,7 +165,7 @@ size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * p pkTab->skill_point, pkTab->sub_skill_point, pkTab->stat_reset_count, - pkTab->ip, + escapedIp.c_str(), pkTab->parts[PART_MAIN], pkTab->parts[PART_HAIR], pkTab->skill_group, @@ -1206,7 +1207,9 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg) CDBManager::instance().AsyncQuery(queryStr); // END_OF_MYSHOP_PRICE_LIST - snprintf(queryStr, sizeof(queryStr), "DELETE FROM messenger_list%s WHERE account='%s' OR companion='%s'", GetTablePostfix(), szName, szName); + const std::string escapedPlayerName = CDBManager::instance().EscapeStringCopy(szName, strnlen(szName, sizeof(szName))); + snprintf(queryStr, sizeof(queryStr), "DELETE FROM messenger_list%s WHERE account='%s' OR companion='%s'", + GetTablePostfix(), escapedPlayerName.c_str(), escapedPlayerName.c_str()); CDBManager::instance().AsyncQuery(queryStr); peer->EncodeHeader(DG::PLAYER_DELETE_SUCCESS, pi->dwHandle, 1); @@ -1272,7 +1275,8 @@ void CClientManager::QUERY_REMOVE_AFFECT(CPeer * peer, TPacketGDRemoveAffect * p void CClientManager::QUERY_HIGHSCORE_REGISTER(CPeer* peer, TPacketGDHighscore * data) { char szQuery[128]; - snprintf(szQuery, sizeof(szQuery), "SELECT value FROM highscore%s WHERE board='%s' AND pid = %u", GetTablePostfix(), data->szBoard, data->dwPID); + const std::string escapedBoard = CDBManager::instance().EscapeStringCopy(data->szBoard, strnlen(data->szBoard, sizeof(data->szBoard))); + snprintf(szQuery, sizeof(szQuery), "SELECT value FROM highscore%s WHERE board='%s' AND pid = %u", GetTablePostfix(), escapedBoard.c_str(), data->dwPID); sys_log(0, "GD::HIGHSCORE_REGISTER: PID %u", data->dwPID); @@ -1293,6 +1297,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg) char szBoard[21]; strlcpy(szBoard, pi->login, sizeof(szBoard)); + const std::string escapedBoard = CDBManager::instance().EscapeStringCopy(szBoard, strnlen(szBoard, sizeof(szBoard))); int value = (int)pi->account_id; SQLResult * res = msg->Get(); @@ -1301,7 +1306,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg) { // 새로운 하이스코어를 삽입 char buf[256]; - snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value); + snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), escapedBoard.c_str(), pi->player_id, value); CDBManager::instance().AsyncQuery(buf); } else @@ -1323,14 +1328,14 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg) else { char buf[256]; - snprintf(buf, sizeof(buf), "REPLACE INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value); + snprintf(buf, sizeof(buf), "REPLACE INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), escapedBoard.c_str(), pi->player_id, value); CDBManager::instance().AsyncQuery(buf); } } else { char buf[256]; - snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value); + snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), escapedBoard.c_str(), pi->player_id, value); CDBManager::instance().AsyncQuery(buf); } } diff --git a/src/db/DBManager.cpp b/src/db/DBManager.cpp index 35da369..4af8429 100644 --- a/src/db/DBManager.cpp +++ b/src/db/DBManager.cpp @@ -166,6 +166,26 @@ unsigned long CDBManager::EscapeString(void *to, const void *from, unsigned long return mysql_real_escape_string(m_directSQL[iSlot]->GetSQLHandle(), (char *) to, (const char *) from, length); } +std::string CDBManager::EscapeStringCopy(const char* from, unsigned long length, int iSlot) +{ + assert(iSlot < SQL_MAX_NUM); + + if (!from || length == 0) + return {}; + + if (!m_directSQL[iSlot]) + { + sys_err("direct SQL handle is not initialized for slot %d", iSlot); + return {}; + } + + std::string escaped(length * 2 + 1, '\0'); + unsigned long escapedLength = mysql_real_escape_string( + m_directSQL[iSlot]->GetSQLHandle(), escaped.data(), from, length); + escaped.resize(escapedLength); + return escaped; +} + void CDBManager::SetLocale(const char * szLocale) { const std::string stLocale(szLocale); diff --git a/src/db/DBManager.h b/src/db/DBManager.h index ea8aba2..a5e801f 100644 --- a/src/db/DBManager.h +++ b/src/db/DBManager.h @@ -49,6 +49,7 @@ class CDBManager : public singleton SQLMsg * PopResult(eSQL_SLOT slot ); unsigned long EscapeString(void * to, const void * from, unsigned long length, int iSlot = SQL_PLAYER); + std::string EscapeStringCopy(const char* from, unsigned long length, int iSlot = SQL_PLAYER); DWORD CountReturnQuery(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountQuery() : 0; } DWORD CountReturnResult(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountResult() : 0; } diff --git a/src/db/GuildManager.cpp b/src/db/GuildManager.cpp index 4f509c1..1191b9e 100644 --- a/src/db/GuildManager.cpp +++ b/src/db/GuildManager.cpp @@ -1404,12 +1404,13 @@ bool CGuildManager::Bet(DWORD dwID, const char * c_pszLogin, DWORD dwGold, DWORD itertype(m_map_kWarReserve) it = m_map_kWarReserve.find(dwID); char szQuery[1024]; + const std::string escapedLogin = CDBManager::instance().EscapeStringCopy(c_pszLogin, c_pszLogin ? strlen(c_pszLogin) : 0); if (it == m_map_kWarReserve.end()) { sys_log(0, "WAR_RESERVE: Bet: cannot find reserve war by id %u", dwID); snprintf(szQuery, sizeof(szQuery), "INSERT INTO item_award (login, vnum, socket0, given_time) VALUES('%s', %d, %u, NOW())", - c_pszLogin, ITEM_ELK_VNUM, dwGold); + escapedLogin.c_str(), ITEM_ELK_VNUM, dwGold); CDBManager::instance().AsyncQuery(szQuery); return false; } @@ -1418,7 +1419,7 @@ bool CGuildManager::Bet(DWORD dwID, const char * c_pszLogin, DWORD dwGold, DWORD { sys_log(0, "WAR_RESERVE: Bet: cannot bet id %u, login %s, gold %u, guild %u", dwID, c_pszLogin, dwGold, dwGuild); snprintf(szQuery, sizeof(szQuery), "INSERT INTO item_award (login, vnum, socket0, given_time) VALUES('%s', %d, %u, NOW())", - c_pszLogin, ITEM_ELK_VNUM, dwGold); + escapedLogin.c_str(), ITEM_ELK_VNUM, dwGold); CDBManager::instance().AsyncQuery(szQuery); return false; }