Анализ потока данных (data-flow analysis) — это метод получения информации о потенциальном диапазоне значений, которые могут быть вычислены в различных точках компьютерной программы.
Статические анализаторы используют анализ потока данных для углублённого поиска различных проблем в коде. К числу таких проблем относятся: SQL-инъекция, выход за границу массива, недостижимый код, возможный доступ по нулевой ссылке и многие другие.
Для лучшего понимания возможностей анализа потока данных рассмотрим примеры кода и применение данного механизма на них.
Ошибка в коде проекта ScreenToGif, найденная статическим анализатором PVS-Studio:
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
....
if (Text.Length > 8) // <=
{
e.Handled = true;
return;
}
if (Text.Length == 1){....}
else if (Text.Length == 4) {....}
else if (Text.Length == 7) {....}
else if (Text.Length == 10) // <=
Text = Text.Substring(0, 9) + Text.Substring(6, 1).PadLeft(3, '0');
....
}
Предупреждение анализатора PVS-Studio:
V3022. Expression 'Text.Length == 10' is always false.
Благодаря механизму анализа потока данных найдено условие, которое всегда ложно. Работает это следующим образом.
Выражение if(Text.Length > 8)
с return
в теле ограничивает возможные значения Text.Length
после выполнения блока if
интервалом [int.MinValue, 7]. Затем при проверке Text.Length == 10
полученная ранее информация указывает на ложность условия, так как значение 10
не входит в указанный выше диапазон. Кроме того, все остальные проверки Text.Length
также учитываются, и значения 1
, 4
, 7
будут исключены из возможных.
Пример с потенциальным разыменованием нулевой ссылки:
int ExampleOfNullDereference(bool flag)
{
string potentiallyNullStr = flag ? "not null" : null;
return potentiallyNullStr.GetHashCode();
}
Сначала анализ потока данных получит информацию о возможных значениях переменной potentiallyNullStr
из выражения flag ? "not null" : null
. Поскольку среди этих значений есть null
, в момент вызова GetHashCode()
возможно разыменование нулевой ссылки, что вызовет исключение. Используя информацию, полученную от анализа потока данных, анализаторы могут обнаружить эту проблему.
Предупреждение анализатора PVS-Studio:
V3080. Possible null dereference. Consider inspecting 'potentiallyNullStr'.
Пример анализа потока данных с bool
:
void ExampleOfAlwaysFalseExpression(bool flag)
{
if (flag)
{
Console.WriteLine("Positive");
if (!flag)
{
Console.WriteLine("Negative");
}
}
}
Анализ потока данных, исходя из оператора if
, получает информацию, что в блоке then
условие оператора принимает значение true
. Таким образом, для блока then
из выражения if(flag)
становится известно, что переменная flag
может иметь только одно значение — true
. Используя эту информацию, статический анализатор может определить, что выражение !flag
внутри данного блока then
всегда будет ложным.
Сообщение PVS-Studio, выданное при анализе данного кода:
V3022. Expression '!flag' is always false.
Приведённые выше примеры являются простыми случаями использования анализа потока данных. Используя комбинации данного подхода с другими механизмами, например, межмодульным анализом, статический анализатор способен выявлять сложные цепочки изменений данных и использовать их при поиске потенциальных уязвимостей и ошибок.
ГОСТ Р 71207-2024 — Статический анализ программного обеспечения. В разделе терминов дано следующее определение межмодульного анализа:
Анализ потока данных — статический анализ, при котором определяются свойства обрабатываемых программой данных. Могут определяться возможные значения переменных и констант, точки программы, в которых используются определённые переменные, и прочее.
Дополнительные ссылки
1. Технологии, используемые в PVS-Studio (соответствует ГОСТ Р 71207—2024)
2. Андрей Карпов, Павел Еремеев. Технологии статического анализа кода PVS-Studio
3. Андрей Карпов. Как работает статический анализ?
4. Никита Липилин. Эволюция PVS-Studio: анализ потока данных для связанных переменных
Français
17