>
>
Хорошо ли ChatGPT ищет ошибки в коде?

Артём Ровенский
Статей: 15

Хорошо ли ChatGPT ищет ошибки в коде?

Нейросети всё больше вливаются в привычный мир, пытаясь упростить нам жизнь. Тот же ChatGPT вызвал бурю обсуждений в интернете. Чат бот способен писать тексты, код, рефераты и песни. Он даже умеет искать ошибки в коде, но... хорошо ли он с этим справляется?

Тестируем 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