Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

Compiler Bug Causes Compiler Bug: How a 12-Year-Old G++ Bug Took Down Solidity- 1715

Kiprey - OtterSecPosted 7 Months Ago
  • The post starts with a small amount of Solidity that crashes the compiler:
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.25;
    
    contract A {
        function a() public pure returns (uint256) {
            return 1 ** 2;
        }
    }
    
  • Eventually, they traced it down to a line of C++ code on the G++ compiler backend that leads to infinite recursion. This turns out to be a 12 year old bug in G++, an outdated comparison operation in Boost and a small rewrite in C++20 that led to this crash.
  • In C++, there is functionality called overloading where the compiler can choose implementations for operations like equality. A member function has priority over a non-member function to overwrite this. G++ doesn't always follow this rule though. Clang would choose the member function and the G++ issue was reported 12 years ago.
  • In C++20, the spaceship operator (<=>) was introduced. This allows for comparisons to be done via overloading as before but will also do the reverse check as well. a=b and code>b=a. This rewrite becomes recursive to do the comparison over and over again if you're not careful.
  • The Boost rational class implemented both a member and a non-member function for operator==. Under C++17, this was safe because of the member vs. non member bug was fixed. However, with C++20 and G++ < 14, G++ would incorrectly choose the non-member operation first. This leads to an infinite recursion bug!
  • The Solidity codebase uses boost::rational to represent some compile-time constant expressions. Because of this, Solidity inherited the bug mentioned above. To have this happen you had to be using G++ < 14, Boost < 1.75 and C++ enabled for Solidity builds. This crash occurs with any compile-time rational comparisons.
  • Although it's not a security vulnerability, it does show how fragile modern stacks can be. A bug from 2012 led to a broken compiler. Neat!