Найти в Дзене
Протестировал

Любите ли вы отладку так, как люблю её я

? Время от времени от непрерывного фаззинга появляются срабатывания, которые надо разбирать, многие из них вызваны настоящими багами, но не все. Обычно мы стараемся все срабатывания разобрать как можно скорее и отрепортить их разработчикам LuaJIT и PUC Rio Lua, но иногда бывают "тяжелые" случаи и такой разбор задерживается. В начале декабря было два срабатывания для PUC Rio Lua: утечка памяти и целочисленное переполнение. Обе проблемы не получилось разобрать сразу, а тем временем в PUC Rio Lua один за другим выпускали RC для новой версии 5.5.0 и было желание как можно быстрее разобрать срабатывания. Чтобы разобрать каждое такое срабатывание надо научиться воспроизводить локально, без использования инфраструктуры OSS Fuzz, и потом минимизировать репро. По желанию можно сделать бисект по коммитам, чтобы понять когда проблема появилась. Проблема с утечкой была странной. В PUC Rio Lua утечки памяти если и бывают, то очень редко, обычно все наши срабатывания в фаззинге заключались в наруш

Любите ли вы отладку так, как люблю её я?

Время от времени от непрерывного фаззинга появляются срабатывания, которые надо разбирать, многие из них вызваны настоящими багами, но не все. Обычно мы стараемся все срабатывания разобрать как можно скорее и отрепортить их разработчикам LuaJIT и PUC Rio Lua, но иногда бывают "тяжелые" случаи и такой разбор задерживается. В начале декабря было два срабатывания для PUC Rio Lua: утечка памяти и целочисленное переполнение. Обе проблемы не получилось разобрать сразу, а тем временем в PUC Rio Lua один за другим выпускали RC для новой версии 5.5.0 и было желание как можно быстрее разобрать срабатывания. Чтобы разобрать каждое такое срабатывание надо научиться воспроизводить локально, без использования инфраструктуры OSS Fuzz, и потом минимизировать репро. По желанию можно сделать бисект по коммитам, чтобы понять когда проблема появилась.

Проблема с утечкой была странной. В PUC Rio Lua утечки памяти если и бывают, то очень редко, обычно все наши срабатывания в фаззинге заключались в нарушении инварианта в assert(). Ещё казался странным файл с входными данными, который воспроизводил проблему. Потому что он был похож на кашу из символов и токенов, похожих на ключевые слова Lua. Минимизировать такой файл было тяжело: creduce совсем не помог, а удаление любого символа ломало воспроизведение проблемы. У меня получилось только немного уменьшить репродьюсер, я не стал тянуть время, описал шаги по воспроизведению и отправил в рассылку. Один из пользователей посмотрел на репро и стал намекать, что входные данные похожи на бинарные, Lua интерпретирует их как байткод и если это так, то это ложноположительный репорт (FP). Я проверил загрузку входных данных с помощью другой функции из Lua C API, которая входные данные интерпретирует только как текст, и воспроизведение потерялось. Я отписал, что похоже это действительно FP. В ответ пишет Роберту Иерузалимски что это не FP и у него получилось воспроизвести проблему. Спустя день он минимизировал репро и превратил его в обычный скрипт на Lua:

collectgarbage'generational'

print(10, xpcall({}, function(msg)

print("1", load'A')

print(" 2", load'A.A')

print(" 3", load'A.A')

io.write(" 4 ", msg, "\n")

assert(string.gsub('....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................', 'X', '') == '')

end))

А чуть позднее описал и причину:

I found the issue. Some calls to the finalizers that should free that slot are failing due to (C) stack overflow. Because warnings were off (by default), we do not see any message.

The leak is tricky because it only appears when a finalizer is called at very specific points during the program. Any change in the rhythm of the garbage collector affects it.

Probably the garbage collector should defer calling a finalizer when there is no stack space to run it.

Исправление попало в версию 5.5.0.