TODO: returns a single value at most - no need for std::vector
| 7519 | |
| 7520 | // TODO: returns a single value at most - no need for std::vector |
| 7521 | static std::vector<ValueFlow::Value> isOutOfBoundsImpl(const ValueFlow::Value& size, |
| 7522 | const Token* indexTok, |
| 7523 | bool condition) |
| 7524 | { |
| 7525 | if (!indexTok) |
| 7526 | return {}; |
| 7527 | const ValueFlow::Value* indexValue = indexTok->getMaxValue(condition, size.path); |
| 7528 | if (!indexValue) |
| 7529 | return {}; |
| 7530 | if (indexValue->intvalue >= size.intvalue) |
| 7531 | return {*indexValue}; |
| 7532 | if (!condition) |
| 7533 | return {}; |
| 7534 | // TODO: Use a better way to decide if the variable in unconstrained |
| 7535 | if (!indexTok->variable() || !indexTok->variable()->isArgument()) |
| 7536 | return {}; |
| 7537 | if (std::any_of(indexTok->values().cbegin(), indexTok->values().cend(), [&](const ValueFlow::Value& v) { |
| 7538 | return v.isSymbolicValue() && v.isPossible() && v.bound == ValueFlow::Value::Bound::Upper; |
| 7539 | })) |
| 7540 | return {}; |
| 7541 | if (indexValue->bound != ValueFlow::Value::Bound::Lower) |
| 7542 | return {}; |
| 7543 | if (size.bound == ValueFlow::Value::Bound::Lower) |
| 7544 | return {}; |
| 7545 | // Checking for underflow doesn't mean it could be out of bounds |
| 7546 | if (indexValue->intvalue == 0) |
| 7547 | return {}; |
| 7548 | ValueFlow::Value value = inferCondition(">=", indexTok, indexValue->intvalue); |
| 7549 | if (!value.isKnown()) |
| 7550 | return {}; |
| 7551 | if (value.intvalue == 0) |
| 7552 | return {}; |
| 7553 | value.intvalue = size.intvalue; |
| 7554 | value.bound = ValueFlow::Value::Bound::Lower; |
| 7555 | return {std::move(value)}; |
| 7556 | } |
| 7557 | |
| 7558 | // TODO: return single value at most - no need for std::vector |
| 7559 | std::vector<ValueFlow::Value> ValueFlow::isOutOfBounds(const Value& size, const Token* indexTok, bool possible) |
no test coverage detected