mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
Planner: Fix Warning from Coverity.
Fix an interger overflow warning when parsing setpoints. @bstoeger: In the end it turned out that this parser was only used in one place in the planner UI, and it was simplest to switch this to using `QVariant.toFloat()` in the model itself, which is consistent how the rest of the input values is parsed and validated. Signed-off-by: Michael Keller <github@ike.ch>
This commit is contained in:
parent
cc55c442a3
commit
33bb39f1ca
3 changed files with 22 additions and 148 deletions
128
core/planner.cpp
128
core/planner.cpp
|
@ -1102,131 +1102,3 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
|||
|
||||
return decodive;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a value with a given number of decimals:
|
||||
* - get_decimals("10.2", &"10.2", 1) == 102
|
||||
* - get_decimals("9", &"9", 1) = 90
|
||||
* - get_decimals("1.35", &"1.35", 2) == 135))
|
||||
*
|
||||
* Return negative for errors.
|
||||
*/
|
||||
static int get_decimals(const char *begin, const char **endp, const unsigned decimals)
|
||||
{
|
||||
char *end;
|
||||
int value = strtol(begin, &end, 10);
|
||||
|
||||
if (begin == end)
|
||||
return -1;
|
||||
|
||||
/* Fraction? We only look at the first digit */
|
||||
if (*end == '.')
|
||||
end++;
|
||||
|
||||
unsigned fraction = 0;
|
||||
for (unsigned i = 0; i < decimals; i++) {
|
||||
value *= 10;
|
||||
|
||||
unsigned digit = 0;
|
||||
if (isdigit(*end)) {
|
||||
digit = *end - '0';
|
||||
|
||||
end++;
|
||||
} else if (*end != '\0') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fraction = 10 * fraction + digit;
|
||||
|
||||
}
|
||||
value += fraction;
|
||||
|
||||
do {
|
||||
end++;
|
||||
} while (isdigit(*end));
|
||||
|
||||
*endp = end;
|
||||
return value;
|
||||
}
|
||||
|
||||
static int get_permille(const char *begin, const char **end)
|
||||
{
|
||||
int value = get_decimals(begin, end, 1);
|
||||
if (value >= 0) {
|
||||
/* Allow a percentage sign */
|
||||
if (**end == '%')
|
||||
++*end;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int validate_gas(const char *text, struct gasmix *gas)
|
||||
{
|
||||
int o2, he;
|
||||
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
|
||||
if (!*text)
|
||||
return 0;
|
||||
|
||||
if (!strcasecmp(text, translate("gettextFromC", "air"))) {
|
||||
o2 = O2_IN_AIR;
|
||||
he = 0;
|
||||
text += strlen(translate("gettextFromC", "air"));
|
||||
} else if (!strcasecmp(text, translate("gettextFromC", "oxygen"))) {
|
||||
o2 = 1000;
|
||||
he = 0;
|
||||
text += strlen(translate("gettextFromC", "oxygen"));
|
||||
} else if (!strncasecmp(text, translate("gettextFromC", "ean"), 3)) {
|
||||
o2 = get_permille(text + 3, &text);
|
||||
he = 0;
|
||||
} else {
|
||||
o2 = get_permille(text, &text);
|
||||
he = 0;
|
||||
if (*text == '/')
|
||||
he = get_permille(text + 1, &text);
|
||||
}
|
||||
|
||||
/* We don't want any extra crud */
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
if (*text)
|
||||
return 0;
|
||||
|
||||
/* Validate the gas mix */
|
||||
if (*text || o2 < 1 || o2 > 1000 || he < 0 || o2 + he > 1000)
|
||||
return 0;
|
||||
|
||||
/* Let it rip */
|
||||
gas->o2.permille = o2;
|
||||
gas->he.permille = he;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int validate_po2(const char *text, int *mbar_po2)
|
||||
{
|
||||
int po2;
|
||||
|
||||
if (!text)
|
||||
return 0;
|
||||
|
||||
po2 = get_decimals(text, &text, 2);
|
||||
if (po2 < 0)
|
||||
return 0;
|
||||
|
||||
while (isspace(*text))
|
||||
text++;
|
||||
if (*text)
|
||||
return 0;
|
||||
|
||||
*mbar_po2 = po2 * 10;
|
||||
|
||||
if (*mbar_po2 < 160)
|
||||
*mbar_po2 = 160;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,6 @@ typedef enum {
|
|||
PLAN_ERROR_INAPPROPRIATE_GAS,
|
||||
} planner_error_t;
|
||||
|
||||
extern int validate_gas(const char *text, struct gasmix *gas);
|
||||
extern int validate_po2(const char *text, int *mbar_po2);
|
||||
extern int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_t time);
|
||||
extern bool diveplan_empty(struct diveplan *diveplan);
|
||||
extern void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, planner_error_t error);
|
||||
|
|
|
@ -357,13 +357,15 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v
|
|||
if (role == Qt::EditRole) {
|
||||
divedatapoint &p = divepoints[index.row()];
|
||||
switch (index.column()) {
|
||||
case DEPTH:
|
||||
if (value.toInt() >= 0) {
|
||||
p.depth = units_to_depth(value.toInt());
|
||||
case DEPTH: {
|
||||
int depth = value.toInt();
|
||||
if (depth >= 0) {
|
||||
p.depth = units_to_depth(depth);
|
||||
if (updateMaxDepth())
|
||||
cylinders.updateBestMixes();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RUNTIME: {
|
||||
int secs = value.toInt() * 60;
|
||||
i = index.row();
|
||||
|
@ -380,23 +382,25 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v
|
|||
break;
|
||||
}
|
||||
case DURATION: {
|
||||
int secs = value.toInt() * 60;
|
||||
if (!secs)
|
||||
secs = 10;
|
||||
i = index.row();
|
||||
if (i)
|
||||
shift = divepoints[i].time - divepoints[i - 1].time - secs;
|
||||
else
|
||||
shift = divepoints[i].time - secs;
|
||||
while (i < divepoints.size())
|
||||
divepoints[i++].time -= shift;
|
||||
break;
|
||||
int secs = value.toInt() * 60;
|
||||
if (secs < 0)
|
||||
secs = 10;
|
||||
i = index.row();
|
||||
if (i)
|
||||
shift = divepoints[i].time - divepoints[i - 1].time - secs;
|
||||
else
|
||||
shift = divepoints[i].time - secs;
|
||||
while (i < divepoints.size())
|
||||
divepoints[i++].time -= shift;
|
||||
break;
|
||||
}
|
||||
case CCSETPOINT: {
|
||||
int po2 = 0;
|
||||
QByteArray gasv = value.toByteArray();
|
||||
if (validate_po2(gasv.data(), &po2))
|
||||
p.setpoint = po2;
|
||||
bool ok;
|
||||
int po2 = round(value.toFloat(&ok) * 100) * 10;
|
||||
|
||||
if (ok)
|
||||
p.setpoint = std::max(po2, 160);
|
||||
|
||||
break;
|
||||
}
|
||||
case GAS:
|
||||
|
|
Loading…
Reference in a new issue