diff options
author | Lubomir I. Ivanov <neolit123@gmail.com> | 2018-06-19 03:19:56 +0300 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2018-06-20 09:30:58 +0900 |
commit | 769aca9e956cd4bb7cc97be813968348f5e7f3d2 (patch) | |
tree | 4bd6d0a57efbce1b5b2885cce9993802ce3bbb06 | |
parent | a5380bb741c1081c86353cf5cd7b506b97e02ea9 (diff) | |
download | subsurface-769aca9e956cd4bb7cc97be813968348f5e7f3d2.tar.gz |
equipment: sanitize 'tank_info' loop limits
In a number of places the global 'tank_info' array
is being iterated based on a 'tank_info[idx].name != NULL'
condition.
This is dangerous because if the user has added a lot of tanks,
such loops can reach 'tank_info[MAX_TANK_INFO]'. This is an
out of bounds read and if the 'name' pointer there happens to be
non-NULL, passing that address to a peace of code that tries
to read it (like strlen()) would either SIGSEGV or have undefined
behavior.
Clamp all loops that iterate 'tank_info' to MAX_TANK_INFO.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
-rw-r--r-- | core/planner.c | 2 | ||||
-rw-r--r-- | desktop-widgets/preferences/preferences_defaults.cpp | 2 | ||||
-rw-r--r-- | qt-models/tankinfomodel.cpp | 5 |
3 files changed, 4 insertions, 5 deletions
diff --git a/core/planner.c b/core/planner.c index cb013799d..cc6874c3f 100644 --- a/core/planner.c +++ b/core/planner.c @@ -209,7 +209,7 @@ void fill_default_cylinder(cylinder_t *cyl) if (!cyl_name) return; - while (ti->name != NULL) { + while (ti->name != NULL && ti < tank_info + MAX_TANK_INFO) { if (strcmp(ti->name, cyl_name) == 0) break; ti++; diff --git a/desktop-widgets/preferences/preferences_defaults.cpp b/desktop-widgets/preferences/preferences_defaults.cpp index 4500ecac2..e0a24530a 100644 --- a/desktop-widgets/preferences/preferences_defaults.cpp +++ b/desktop-widgets/preferences/preferences_defaults.cpp @@ -52,7 +52,7 @@ void PreferencesDefaults::refreshSettings() ui->localDefaultFile->setChecked(prefs.default_file_behavior == LOCAL_DEFAULT_FILE); ui->default_cylinder->clear(); - for (int i = 0; tank_info[i].name != NULL; i++) { + for (int i = 0; tank_info[i].name != NULL && i < MAX_TANK_INFO; i++) { ui->default_cylinder->addItem(tank_info[i].name); if (prefs.default_cylinder && strcmp(tank_info[i].name, prefs.default_cylinder) == 0) ui->default_cylinder->setCurrentIndex(i); diff --git a/qt-models/tankinfomodel.cpp b/qt-models/tankinfomodel.cpp index 49e42830c..0a54cd305 100644 --- a/qt-models/tankinfomodel.cpp +++ b/qt-models/tankinfomodel.cpp @@ -91,7 +91,7 @@ TankInfoModel::TankInfoModel() : rows(-1) { setHeaderDataStrings(QStringList() << tr("Description") << tr("ml") << tr("bar")); struct tank_info_t *info = tank_info; - for (info = tank_info; info->name; info++, rows++) { + for (info = tank_info; info->name && info < tank_info + MAX_TANK_INFO; info++, rows++) { QString infoName = gettextFromC::tr(info->name); if (infoName.count() > biggerEntry.count()) biggerEntry = infoName; @@ -111,8 +111,7 @@ void TankInfoModel::update() rows = -1; } struct tank_info_t *info = tank_info; - for (info = tank_info; info->name; info++, rows++) - ; + for (info = tank_info; info->name && info < tank_info + MAX_TANK_INFO; info++, rows++); if (rows > -1) { beginInsertRows(QModelIndex(), 0, rows); |