Нейросети всё больше вливаются в привычный мир, пытаясь упростить нам жизнь. Тот же ChatGPT вызвал бурю обсуждений в интернете. Чат бот способен писать тексты, код, рефераты и песни. Он даже умеет искать ошибки в коде, но... хорошо ли он с этим справляется?
Проверим возможности ChatGPT на некоторых примерах из документации статического анализатора PVS-Studio. Документация каждого диагностического правила содержит примеры ошибочного кода (где PVS-Studio выдаёт предупреждение) и исправленного. Для каждого примера из статьи будет ссылка на соответствующую документацию. Кроме того, рассмотрим несколько примеров из реальных проектов.
В этой статье код будет на C#, но статья подойдёт и разработчикам на других языках программирования.
Начнём с привычного всем C# разработчикам – NullReferenceException.
Диагностика V3125. В данном случае ChatGPT вполне правильно нашёл ошибку в маленьком куске кода. Он понял, что obj.Func2() следует поместить внутрь проверки obj на null. Попробуем слегка усложнить задачу и добавим межпроцедурного анализа.
И он действительно справился. Впечатляет. Уточню, что PVS-Studio на данном коде так же выдаст предупреждение.
Вот ещё один пример:
Диагностика V3179. Здесь ChatGPT тоже смог найти ошибку, хоть и не написал, что будет выброшено исключение. Также замечу, что иногда он выдавал вот такой ответ:
В этом ответе бот написал, что условие if невозможно и переменной itemForComparison никогда не присвоится значение. Естественно, список в метод может прийти любой и вывод ошибочный.
Также ChatGPT может не находить даже простые ошибки, хотя они могут быть не для всех очевидны. Например, вот в таком случае:
Диагностика V3186. В данном случае бот не нашёл ошибку. Переданные в метод аргументы некорректны. В массиве 4 элемента, стартовый индекс равен 2, количество элементов для просмотра равно 3, получили выход за границу массива.
Возможно, ChatGPT не нашёл данную ошибку, так как она не распространена, и у него просто не было нужной информации для обучения. Правда это не значит, что такую ошибку нельзя допустить, и её не нужно искать.
Cлучаются и промахи, когда ChatGPT говорит об ошибке, которой нет.
Диагностика V3178. На этом корректном коде ChatGPT смог найти ошибку, которой нет. По его словам, с помощью Console.WriteLine пытаются писать в файл, что является проблемой. Однако ничего такого здесь нет.
PVS-Studio также умеет проверять код на наличие потенциальных уязвимостей. А умеет ли ChatGPT? Попросим его найти уязвимость SQL-инъекция.
Диагностика V5608. И бот справился. Он верно распознал уязвимость и подсказал, что для защиты от SQL injection нужно использовать параметризованные запросы.
Теперь попросим проанализировать код, в котором уже защитились от уязвимости.
ChatGPT посчитал, что этот код безопасен, и это действительно так. Вот только он не всегда правильно обрабатывает корректный код. Рассмотрим пример LDAP injection, в котором уже защитились от этой уязвимости.
Диагностика V5620. Хм, ChatGPT нашёл атаку типа LDAP injection. По его мнению, пользовательский ввод никак не проверяется и не кодируется. Однако мы вызвали метод Encoder.LdapFilterEncode, который как раз кодирует внешние данные.
Весь код, который мы просили ИИ посмотреть, являлся синтетическим. Что же будет на реальном проекте? В прошлом году мы выпускали статью про XXE уязвимости: "Уязвимости из-за обработки XML-файлов: XXE в C# приложениях в теории и на практике". В ней был пример воспроизводимой уязвимости на проекте BlogEngine.NET, которую обнаруживает PVS-Studio.
Возьмём код, указанный в данной статье, и попросим найти ошибку.
public XMLRPCRequest(HttpContext input)
{
var inputXml = ParseRequest(input);
// LogMetaWeblogCall(inputXml);
this.LoadXmlRequest(inputXml); // Loads Method Call
// and Associated Variables
}
private static string ParseRequest(HttpContext context)
{
var buffer = new byte[context.Request.InputStream.Length];
context.Request.InputStream.Position = 0;
context.Request.InputStream.Read(buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}
private void LoadXmlRequest(string xml)
{
var request = new XmlDocument();
try
{
if (!(xml.StartsWith("<?xml") || xml.StartsWith("<method")))
{
xml = xml.Substring(xml.IndexOf("<?xml"));
}
request.LoadXml(xml);
}
catch (Exception ex)
{
throw new MetaWeblogException("01",
$"Invalid XMLRPC Request. ({ex.Message})");
}
....
}
На просьбу найти в данном коде уязвимость, анализатор ChatGPT выдал предположение, что здесь присутствует уязвимость переполнения буфера.
Увы, размерность массива buffer в точности такая, какая и требуется для содержимого потока. В теории возможна ситуация получения исключения System.OverflowException при выделении памяти под массив, если длина потока будет больше максимальной размерности массива. На практике при попытке получения входного потока будет выброшено исключение System.Web.HttpException с сообщением "Maximum request length exceeded". Далее это исключение будет определённым образом обработано. Выделения памяти под массив не произойдёт.
После этого мы задали вопрос про существование других уязвимостей в данном коде.
На этот вопрос бот дал довольно общий ответ о том, что в программах возможны уязвимости и нужно регулярно проводить анализ безопасности для выявления потенциальных уязвимостей. Хм, не могу не согласиться, но это не то, что ожидалось.
При этом PVS-Studio выдаст на данный код следующее предупреждение:
V5614 [CWE-611, OWASP-5.5.2] Potential XXE vulnerability inside method. Insecure XML parser is used to process potentially tainted data from the first argument: 'inputXml'. BlogEngine.Core XMLRPCRequest.cs 41
Стоит сказать, что у моего коллеги ChatGPT всё-таки смог найти эту уязвимость. Сказывается непостоянность его ответов.
Примечание. Кстати, результат, который может быть получен только с некоторой вероятностью, не очень подходит для инструментария программиста. Например, представьте, вы чуть поправили код и предупреждение исчезло. Что это значит? Вы исправили ошибку? Или просто теперь о ней не сообщают?
А как бот справляется с ошибками copy-paste? Пример ошибки из статьи, где мы с помощью PVS-Studio искали ошибки в веб-проектах, использующих ASP.NET Core. На 7 строке того рейтинга из статьи как раз была copy-paste ошибка из проекта Piranha CMS.
public override async Task InitializeAsync()
{
using (var api = CreateApi())
{
....
// Add archive
var blog = await BlogArchive.CreateAsync(api);
blog.Id = BLOG_ID;
blog.SiteId = SITE_ID;
blog.Title = "Blog";
blog.EnableComments = true;
blog.Published = DateTime.Now;
await api.Pages.SaveAsync(blog);
var news = await BlogArchive.CreateAsync(api);
news.Id = NEWS_ID;
news.SiteId = SITE_ID;
news.Title = "News";
blog.EnableComments = true; // <=
news.Published = DateTime.Now;
await api.Pages.SaveAsync(news);
....
}
}
Перед выводом хочется добавить немного размышлений.
При использовании подобных систем искусственного интеллекта возникает вопрос сохранности исходного кода, ведь его придётся куда-то отправлять. Сегодня ты отправляешь свой код ИИ, а завтра этот код кто-то получает в качестве ответа на свой вопрос. Со всеми уязвимостями твоего проекта или продукта компании. Уже известно, что сотрудников Amazon и Microsoft попросили не делиться с ChatGPT конфиденциальной информацией.
Стоит помнить, что всю информацию, которую выдаёт любой искусственный интеллект в качестве ответа, нужно проверять. Хорошо, когда вы разбираетесь в теме и можете оценить корректность выдаваемой информации. Но может быть и так, что человек не разбирается в вопросе, и ИИ выдаёт неправильный ответ. Если пользователь не станет проверять полученную информацию, то это может привести к различным ошибкам и проблемам, а может и человеческим жертвам (в различных областях).
Несмотря на вышесказанное, я был сильно удивлён возможностями ChatGPT. Мы один раз в шутку попросили найти его ошибку в первом примере статьи и выдать ответ в формате SARIF. Не описать словами наше удивление, когда он это правда сделал.
Я думаю, что подобные модели искусственного интеллекта могут дополнить статический анализ, но никак не заменить его. ИИ можно было бы использовать для:
Важно помнить, что ничего не заменит глубокое понимание и опыт разработчика.
Я считаю, что ChatGPT это неплохое подспорье, которое может стать отправной точкой для дальнейшей работы. Например, составить текст для ответа клиенту, накидать небольшую заметку или даже кусок для этой статьи :).
Конечно, данное сравнение было сделано скорее ради человеческого любопытства и забавы, а не реального сравнения статического анализатора PVS-Studio и ChatGPT. Понятно, что ChatGPT не обладает полной информацией о программе. Статическому анализу с этим проще, у него есть более полное представление кода и различная семантическая информация. Можно сказать, что статический анализатор просто обладает большими знаниями о происходящем. Это помогает ему находить довольно сложные проблемы, которые не всегда видны с первого взгляда.
Плюс поиск ошибок – это не только сам анализ и выдача сообщения, а ещё и идущая в комплекте инфраструктура. Плагины для IDE с удобной навигацией и фильтрацией, встраивание в CI, поддержка игровых движков, лёгкое использование в проектах с legacy и многое другое, идёт в комплекте с анализатором. Боту, например, тяжело сказать, что он ошибся (он ещё может не соглашаться), а в плагине можно просто отметить предупреждение как ложное.
Спасибо за прочтение, надеюсь, вы утолили свой интерес :). Всем интересующимся данной темой предлагаю также почитать статью "Использование машинного обучения в статическом анализе исходного кода программ" про нюансы совмещения искусственного интеллекта и методологии статического анализа. На данный момент приведённые в ней аргументы всё ещё в силе. ИИ для поиска ошибок и уязвимостей выглядит пока больше как игрушка в сравнении с классическими статическими анализаторами кода.
Goodbye to all the readers of the article! Thank you for taking the time to read this. I hope the information provided was helpful and informative. If you have any further questions, feel free to ask. Have a great day!
– ChatGPT
0