| 216 | } |
| 217 | |
| 218 | void CheckStlImpl::outOfBoundsError(const Token *tok, const std::string &containerName, const ValueFlow::Value *containerSize, const std::string &index, const ValueFlow::Value *indexValue) |
| 219 | { |
| 220 | // Do not warn if both the container size and index value are possible |
| 221 | if (containerSize && indexValue && containerSize->isPossible() && indexValue->isPossible()) |
| 222 | return; |
| 223 | |
| 224 | const std::string expression = tok ? tok->expressionString() : (containerName+"[x]"); |
| 225 | |
| 226 | std::string errmsg; |
| 227 | if (!containerSize) { |
| 228 | if (indexValue && indexValue->condition) |
| 229 | errmsg = ValueFlow::eitherTheConditionIsRedundant(indexValue->condition) + " or '" + index + |
| 230 | "' can have the value " + indexValueString(*indexValue, containerName) + ". Expression '" + |
| 231 | expression + "' causes access out of bounds."; |
| 232 | else |
| 233 | errmsg = "Out of bounds access in expression '" + expression + "'"; |
| 234 | } else if (containerSize->intvalue == 0) { |
| 235 | if (containerSize->condition) |
| 236 | errmsg = ValueFlow::eitherTheConditionIsRedundant(containerSize->condition) + " or expression '" + expression + "' causes access out of bounds."; |
| 237 | else if (indexValue == nullptr && !index.empty() && tok->valueType() && tok->valueType()->type == ValueType::ITERATOR) |
| 238 | errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty and '" + index + "' may be non-zero."; |
| 239 | else |
| 240 | errmsg = "Out of bounds access in expression '" + expression + "' because '$symbol' is empty."; |
| 241 | } else if (indexValue) { |
| 242 | if (containerSize->condition) |
| 243 | errmsg = ValueFlow::eitherTheConditionIsRedundant(containerSize->condition) + " or size of '$symbol' can be " + MathLib::toString(containerSize->intvalue) + ". Expression '" + expression + "' causes access out of bounds."; |
| 244 | else if (indexValue->condition) |
| 245 | errmsg = ValueFlow::eitherTheConditionIsRedundant(indexValue->condition) + " or '" + index + "' can have the value " + indexValueString(*indexValue) + ". Expression '" + expression + "' causes access out of bounds."; |
| 246 | else |
| 247 | errmsg = "Out of bounds access in '" + expression + "', if '$symbol' size is " + MathLib::toString(containerSize->intvalue) + " and '" + index + "' is " + indexValueString(*indexValue); |
| 248 | } else { |
| 249 | // should not happen |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | ErrorPath errorPath; |
| 254 | if (!indexValue) |
| 255 | errorPath = getErrorPath(tok, containerSize, "Access out of bounds"); |
| 256 | else { |
| 257 | ErrorPath errorPath1 = getErrorPath(tok, containerSize, "Access out of bounds"); |
| 258 | ErrorPath errorPath2 = getErrorPath(tok, indexValue, "Access out of bounds"); |
| 259 | if (errorPath1.size() <= 1) |
| 260 | errorPath = std::move(errorPath2); |
| 261 | else if (errorPath2.size() <= 1) |
| 262 | errorPath = std::move(errorPath1); |
| 263 | else { |
| 264 | errorPath = std::move(errorPath1); |
| 265 | errorPath.splice(errorPath.end(), errorPath2); |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | reportError(std::move(errorPath), |
| 270 | (containerSize && !containerSize->errorSeverity()) || (indexValue && !indexValue->errorSeverity()) ? Severity::warning : Severity::error, |
| 271 | "containerOutOfBounds", |
| 272 | "$symbol:" + containerName +"\n" + errmsg, |
| 273 | CWE398, |
| 274 | (containerSize && containerSize->isInconclusive()) || (indexValue && indexValue->isInconclusive()) ? Certainty::inconclusive : Certainty::normal); |
| 275 | } |
no test coverage detected