From 19f1ffa4018277a8d1f0397a576965b6e3efc267 Mon Sep 17 00:00:00 2001 From: Asher Baker Date: Sun, 6 Feb 2022 16:34:14 +0000 Subject: [PATCH] Stop SQLite results being used before being fetched (#1709) The DB API requires FetchRow to be called before accessing any values from a row, but the SQLite driver did not enforce that requirement and alowed accessing the first row immediately. A plugin developer hit this when developing against SQLite locally but using MySQL in production, where the API misuse threw an error as expected. Resolves #1691 --- extensions/sqlite/driver/SqResults.cpp | 12 ++++++------ extensions/sqlite/driver/SqResults.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/extensions/sqlite/driver/SqResults.cpp b/extensions/sqlite/driver/SqResults.cpp index f4c2215b..3bd0be38 100644 --- a/extensions/sqlite/driver/SqResults.cpp +++ b/extensions/sqlite/driver/SqResults.cpp @@ -37,7 +37,7 @@ SqResults::SqResults(SqQuery *query) : m_pStmt(query->GetStmt()), m_Strings(1024), m_RowCount(0), m_MaxRows(0), m_Rows(NULL), - m_CurRow(0), m_NextRow(0) + m_CurRow(-1), m_NextRow(0) { m_ColCount = sqlite3_column_count(m_pStmt); if (m_ColCount) @@ -99,7 +99,7 @@ bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId) void SqResults::ResetResultCount() { m_RowCount = 0; - m_CurRow = 0; + m_CurRow = -1; m_NextRow = 0; m_pMemory->Reset(); } @@ -163,7 +163,7 @@ void SqResults::PushResult() bool SqResults::MoreRows() { - return (m_CurRow < m_RowCount); + return (m_CurRow < 0) ? (m_RowCount > 0) : (m_CurRow < m_RowCount); } IResultRow *SqResults::FetchRow() @@ -179,7 +179,7 @@ IResultRow *SqResults::FetchRow() IResultRow *SqResults::CurrentRow() { - if (!m_RowCount || m_CurRow >= m_RowCount) + if (!m_RowCount || m_CurRow < 0 || m_CurRow >= m_RowCount) { return NULL; } @@ -188,14 +188,14 @@ IResultRow *SqResults::CurrentRow() bool SqResults::Rewind() { - m_CurRow = 0; + m_CurRow = -1; m_NextRow = 0; return true; } SqField *SqResults::GetField(unsigned int col) { - if (m_CurRow >= m_RowCount || col >= m_ColCount) + if (m_CurRow < 0 || m_CurRow >= m_RowCount || col >= m_ColCount) { return NULL; } diff --git a/extensions/sqlite/driver/SqResults.h b/extensions/sqlite/driver/SqResults.h index afc366a2..1491fb2e 100644 --- a/extensions/sqlite/driver/SqResults.h +++ b/extensions/sqlite/driver/SqResults.h @@ -90,11 +90,11 @@ private: unsigned int m_ColCount; /** DOES NOT CHANGE */ BaseStringTable m_Strings; /** DOES NOT CHANGE */ BaseMemTable *m_pMemory; /** DOES NOT CHANGE */ - unsigned int m_RowCount; - unsigned int m_MaxRows; + int m_RowCount; + int m_MaxRows; SqField *m_Rows; - unsigned int m_CurRow; - unsigned int m_NextRow; + int m_CurRow; + int m_NextRow; }; #endif //_INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_