Compiler Bug Causes Compiler Bug: How a 12-Year-Old G++ Bug Took Down Solidity
Краткий обзор
- Проблема: компилятор Solidity (solc) падает на Ubuntu 22.04 при компиляции корректного кода.
- Причина: сочетание трёх факторов
- 12-летний баг G++ (< 14) в разрешении перегрузок.
- Устаревший паттерн сравнения в Boost.
- Новые правила симметричных сравнений C++20.
Цепочка событий
- Баг G++ (2012, GCC-53499): при
boost::rational<T> == 0
компилятор до 14-й версии выбирает нечлен-шаблон вместо член-шаблона. - C++20 добавляет автоматическую перестановку аргументов:
0 == rational<T>
→rational<T> == 0
. - Boost 1.74 предоставляет обе версии оператора, что приводит к бесконечной рекурсии и переполнению стека.
Минимальный пример
template<typename T>
struct rational {
template<class U>
bool operator==(const U&) const { return true; }
};
template<class U, class T>
bool operator==(const rational<T>&, const U&) { return false; }
int main() {
rational<int> r;
return r == 0; // g++11 выбирает free-функцию
}
Как починить
- Обновить GCC ≥ 14 или Clang, или
- Собрать Solidity без C++20 (
-std=c++17
), или - Патч Boost/использовать свежий Boost ≥ 1.82.
Итог
Ни один компонент по отдельности не «сломан», но их комбинация приводит к крашу компилятора на валидном коде.