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
This commit is contained in:
Asher Baker 2022-02-06 16:34:14 +00:00 committed by Your Name
parent c206ac3099
commit 19f1ffa401
2 changed files with 10 additions and 10 deletions

View File

@ -37,7 +37,7 @@
SqResults::SqResults(SqQuery *query) : SqResults::SqResults(SqQuery *query) :
m_pStmt(query->GetStmt()), m_Strings(1024), m_pStmt(query->GetStmt()), m_Strings(1024),
m_RowCount(0), m_MaxRows(0), m_Rows(NULL), 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); m_ColCount = sqlite3_column_count(m_pStmt);
if (m_ColCount) if (m_ColCount)
@ -99,7 +99,7 @@ bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId)
void SqResults::ResetResultCount() void SqResults::ResetResultCount()
{ {
m_RowCount = 0; m_RowCount = 0;
m_CurRow = 0; m_CurRow = -1;
m_NextRow = 0; m_NextRow = 0;
m_pMemory->Reset(); m_pMemory->Reset();
} }
@ -163,7 +163,7 @@ void SqResults::PushResult()
bool SqResults::MoreRows() bool SqResults::MoreRows()
{ {
return (m_CurRow < m_RowCount); return (m_CurRow < 0) ? (m_RowCount > 0) : (m_CurRow < m_RowCount);
} }
IResultRow *SqResults::FetchRow() IResultRow *SqResults::FetchRow()
@ -179,7 +179,7 @@ IResultRow *SqResults::FetchRow()
IResultRow *SqResults::CurrentRow() IResultRow *SqResults::CurrentRow()
{ {
if (!m_RowCount || m_CurRow >= m_RowCount) if (!m_RowCount || m_CurRow < 0 || m_CurRow >= m_RowCount)
{ {
return NULL; return NULL;
} }
@ -188,14 +188,14 @@ IResultRow *SqResults::CurrentRow()
bool SqResults::Rewind() bool SqResults::Rewind()
{ {
m_CurRow = 0; m_CurRow = -1;
m_NextRow = 0; m_NextRow = 0;
return true; return true;
} }
SqField *SqResults::GetField(unsigned int col) 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; return NULL;
} }

View File

@ -90,11 +90,11 @@ private:
unsigned int m_ColCount; /** DOES NOT CHANGE */ unsigned int m_ColCount; /** DOES NOT CHANGE */
BaseStringTable m_Strings; /** DOES NOT CHANGE */ BaseStringTable m_Strings; /** DOES NOT CHANGE */
BaseMemTable *m_pMemory; /** DOES NOT CHANGE */ BaseMemTable *m_pMemory; /** DOES NOT CHANGE */
unsigned int m_RowCount; int m_RowCount;
unsigned int m_MaxRows; int m_MaxRows;
SqField *m_Rows; SqField *m_Rows;
unsigned int m_CurRow; int m_CurRow;
unsigned int m_NextRow; int m_NextRow;
}; };
#endif //_INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_ #endif //_INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_