comparison OrthancServer/Database/SQLiteDatabaseWrapper.cpp @ 3809:2bf30ef727e3

enforcing SQLiteDatabaseWrapper::GetTableRecordCount() against SQL injection
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 03 Apr 2020 14:47:37 +0200
parents 2a170a8f1faf
children 100fbe970762
comparison
equal deleted inserted replaced
3808:7f083dfae62b 3809:2bf30ef727e3
293 } 293 }
294 294
295 295
296 int64_t SQLiteDatabaseWrapper::GetTableRecordCount(const std::string& table) 296 int64_t SQLiteDatabaseWrapper::GetTableRecordCount(const std::string& table)
297 { 297 {
298 char buf[128]; 298 /**
299 sprintf(buf, "SELECT COUNT(*) FROM %s", table.c_str()); 299 * "Generally one cannot use SQL parameters/placeholders for
300 SQLite::Statement s(db_, buf); 300 * database identifiers (tables, columns, views, schemas, etc.) or
301 301 * database functions (e.g., CURRENT_DATE), but instead only for
302 if (!s.Step()) 302 * binding literal values." => To avoid any SQL injection, we
303 * check that the "table" parameter has only alphabetic
304 * characters.
305 * https://stackoverflow.com/a/1274764/881731
306 **/
307 for (size_t i = 0; i < table.size(); i++)
308 {
309 if (!isalpha(table[i]))
310 {
311 throw OrthancException(ErrorCode_ParameterOutOfRange);
312 }
313 }
314
315 // Don't use "SQLITE_FROM_HERE", otherwise "table" would be cached
316 SQLite::Statement s(db_, "SELECT COUNT(*) FROM " + table);
317
318 if (s.Step())
319 {
320 int64_t c = s.ColumnInt(0);
321 assert(!s.Step());
322 return c;
323 }
324 else
303 { 325 {
304 throw OrthancException(ErrorCode_InternalError); 326 throw OrthancException(ErrorCode_InternalError);
305 } 327 }
306
307 int64_t c = s.ColumnInt(0);
308 assert(!s.Step());
309
310 return c;
311 } 328 }
312 329
313 330
314 SQLiteDatabaseWrapper::SQLiteDatabaseWrapper(const std::string& path) : 331 SQLiteDatabaseWrapper::SQLiteDatabaseWrapper(const std::string& path) :
315 listener_(NULL), 332 listener_(NULL),