Анализатор обнаружил использование данных, полученных извне, без предварительной проверки. Такой сценарий излишнего доверия может привести к различным негативным последствиям, в том числе - стать причиной уязвимостей.
На данный момент диагностическое правило V5009 выявляет ошибки по нескольким паттернам:
Рассмотрим все паттерны более подробно.
Пример подозрительного кода при использовании в индексе недостоверных данных.
size_t index = 0; .... if (scanf("%zu", &index) == 1) { .... DoSomething(arr[index]); // <= }
Данный код может привести к доступу за границу массива 'arr' в случае, если пользователем будет введено значение отрицательное или превышающее максимально допустимый индекс массива 'arr'.
Безопасный код проверяет полученное значение:
if (index < ArraySize) DoSomething(arr[index]);
Пример подозрительного кода при использовании недостоверных данных в аргументе функции.
char buf[1024]; char username [256]; .... if (scanf("%255s", username) == 1) { if (snprintf(buf, sizeof(buf) - 1, commandFormat, username) > 0) { int exitCode = system(buf); // <= .... } .... }
Этот код является уязвимым, т.к. пользовательский ввод передаётся командному интерпретатору без проверки полученных данных. Например, введя "&cmd", на Windows можно получить доступ к командному интерпретатору.
Правильный код должен осуществлять дополнительную проверку считанных данных:
if (IsValid(username)) { if (snprintf(buf, sizeof(buf) - 1, commandFormat, username) > 0) { int exitCode = system(buf); .... } .... } else { printf("Invalid username: %s", username); .... }
Пример подозрительного кода, связанного с порчей указателя.
size_t offset = 0; int *pArr = arr; .... if (scanf("%zu", &offset) == 1) { pArr += offset; // <= .... DoSomething(pArr); }
В данном случае портится значение указателя 'pArr', т.к. в результате прибавления непроверенного значения 'offset' указатель может начать ссылаться за пределы массива. В результате можно испортить какие-то данные (на которые будет ссылаться 'pArr') с непредсказуемыми последствиями.
Правильный код проверяет допустимое смещение:
if (offset <= allowableOffset) { pArr += offset; .... DoSomething(pArr); }
Пример подозрительного кода с делением на недостоверные данные:
if (fscanf(stdin, "%zu", &denominator) == 1) { targetVal /= denominator; }
Этот код может привести к делению на 0, если соответствующее значение будет введено пользователем.
Корректный код выполняет проверку допустимости значений:
if (fscanf(stdin, "%zu", &denominator) == 1) { if (denominator > MinDenominator && denominator < MaxDenominator) { targetVal /= denominator; } }
Данная диагностика классифицируется как: