Нейросети всё больше вливаются в привычный мир, пытаясь упростить нам жизнь. Тот же 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

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Artem Rovenskii. Is ChatGPT good enough at spotting bugs in code?.

Комментарии (27)


  1. gsaw
    00.00.0000 00:00
    +17

    Вижу ChatGPT уже пишет статьи для хабра.

    Есть уже статья как с помощью ChatGPT сгенерировать статью для хабра о том как сгенерировать с помощью ChatGPT статью для хабра, на тему как сгенерировать статью для хабра?


    1. orfelin
      00.00.0000 00:00
      +1

      Только не заказывайте ChatGPT воссоздать самого себя.

      Шекли: «необходимая вещь»


    1. xaosxaos2
      00.00.0000 00:00

      А может пора дать задание уже сгенерировать новый хабр?


  1. panvartan
    00.00.0000 00:00
    -10

    Боту до статистического и динамического анализа один шаг, который несомненно будет сделан, после чего большинство программистов получат выходные пособия.


    1. nobon67
      00.00.0000 00:00
      +12

      Попробуй на нем написать сложную программу с многопоточностью. Ты будешь удивлен, насколько он бывает бесполезен, если прокладка между рулём и сиденьем не шарит.


      1. panvartan
        00.00.0000 00:00

        Правильно - выкидываем прокладку, руль, педали и говорим машине куда ехать и что везти. ChatGPT это не способ написания кода, это и есть код. Бизнес скоро поймет, что подобные системы это не навигация для прокладок, это новая среда исполнения. И "пробовать писать на нем сложную программу с многопоточность" никто не будет - ему будут давать ресурсы, а способ их использования будет выше понимания большинства дающих, что их будет более чем устраивать.


    1. csharpreader
      00.00.0000 00:00
      +4

      «Так-то у меня свой бизнес, я ИИ на упрощёнке. Отвечаю на вопросы людей чисто для души, как хобби по вечерам».


  1. nobon67
    00.00.0000 00:00
    +2

    Уже довольно плотно с ним работаю, и в том числе по отладке кода, написанию кода, написанию контента. Он периодически галлюцинирует, и чем сложнее тема, тем чаще. Например, многопоточность в pyqt5 для это просто стопкран.


    1. rip_m Автор
      00.00.0000 00:00

      Интересно, а что вы подразумеваете под отладкой кода?


      1. nobon67
        00.00.0000 00:00

        Я надеялся, что он поможет мне найти ошибку в моём коде... В некоторых случаях он действительно помогает, но далеко не всегда...


      1. nobon67
        00.00.0000 00:00
        +2

        Мне не стыдно признаться, что я не самый крутой программист, и не мог победить многопоточность в pyqt5/pyside2, с tk всё куда проще. В общем, толку с него было мало. Понял, что проще разобраться самому, и в итоге, так и произлошло.


  1. sla000
    00.00.0000 00:00

    Сконструированный объект не может быть равен null. Поэтому технически багов в первом примере нет, но можно предложить убрать строку с if.


    1. SergVasiliev
      00.00.0000 00:00
      +3

      Нет гарантий, что Foo возвращает ссылку на объект. С таким же успехом метод может вернуть значение null. Проверка намекает, что разработчик допускает такой сценарий.


      1. Meloman19
        00.00.0000 00:00

        Ну если придираться к деталям, то мы ничего не знаем о типе в первом примере. Если это структура, то исправление будет совершенно иным.


        1. SergVasiliev
          00.00.0000 00:00

          Я и не придираюсь — отталкиваюсь от контекста.


          1. Meloman19
            00.00.0000 00:00

            Это я придираюсь. Так-то понятно, что в такого рода задачах подразумевается класс, но всё же тип в данном случае влияет на решение.


        1. vabka
          00.00.0000 00:00

          Если это структура, то тогда проверка на null не имеет смысла и выдаст ошибку компиляции.

          Теперь можно притянуть за уши, что Func2 - это на самом деле метод-расширение.


          1. Meloman19
            00.00.0000 00:00

            В том-то и прикол, что ошибки здесь не будет, будет warning. Такая проверка спокойно скомпилируется и запустится.


            1. vabka
              00.00.0000 00:00

              Я про самый первый пример, который без сопутствующего кода действительно не скомпилируется.

              Где хотябы определение той функции, которая объект должна вернуть?

              Если предположить, что всё-таки где-то это определение есть, то тогда вопрос про csproj. При определённом конфиге оно тоже не скомпилируется, например если включить NRT и кидать ошибку при их нарушении


    1. Ogra
      00.00.0000 00:00
      +2

      А кто вам сказал, что там конструируется объект? Я вот вижу вызов метода, который может вернуть null :)


      1. sla000
        00.00.0000 00:00
        +1

        А, ну да, это же С# и тут методы и функции могут быть с большой буквы, спасибо


      1. Meloman19
        00.00.0000 00:00

        Ну, в задаче не указан тип, так что если там структура, то null быть не может.


  1. vadimr
    00.00.0000 00:00
    +6

    А он не на вашей ли собственной документации, выложенной в онлайне, обучился оценивать примеры из этой документации? Вы ему даёте фрагменты кода, которые легко гуглятся, и он вам сообщает именно то, что в гугле написано, а вы поражаетесь глубине машинного интеллекта.

    Предполагаю, что даже переименование переменных ухудшит результаты.


    1. rip_m Автор
      00.00.0000 00:00
      +1

      Вполне возможно, но примеры из документации использовались и из новых диагностических правил, которые были опубликованы после 2021 года. ChatGPT обучался на информации до 2021 года.

      Предполагаю, что даже переименование переменных ухудшит результаты.

      Интересно, можно попробовать.


  1. Refridgerator
    00.00.0000 00:00
    -2

    А есть ли гарантия, что чат-бот сам НЕ использует статический анализатор? Вот тут нормальный себе списочек. Вряд ли чат-бот находит ошибки опираясь на свой собственный опыт программирования.


    1. vabka
      00.00.0000 00:00

      1. Ему это как минимум не нужно. Языковая модель же

      2. Статические анализаторы обычно не справляются с псевдокодом, а тут именно он.


      1. Refridgerator
        00.00.0000 00:00

        Ну вроде бы исходный код ChatGPT закрыт, равно как и процедура его обучения, чтобы убедиться в этом самостоятельно. Или нет? Каким чудом можно находить ошибки в коде, не имея опыта программирования? Вот тут в соседней теме ChatGPT признался, что имеет встроенный калькулятор. Лично мне это кажется намного более вероятным, чем то, что ChatGPT научился считать из книг по математике. Даже если умение считать обеспечено через натаскивание и запоминание таблицы умножения — сама структура нейросети позволяет складывать и умножать практически естественным образом. А вот Балабола от Яндекса, например, 2 и 2 сложить не может.

        Не вижу причин, по которым ChatGPT не могли натаскивать на типовые ошибки в коде. У меня нет к нему доступа, чтобы проверить лично — а как он там с ассемблером справится, например? Хотя бы в элементарных вещах — mov rax, 0 в .386 контексте.