2025-07-23 _FORTIFY_SOURCE ========================== .. feed-entry:: :date: 2025-07-23 As a software engineer and operator, I really like it when computers automagically help me find problems. But sometimes it can be a bit surprising when you're not expecting it, and when it's not clear that has happened! `I'm currently porting a ~50kloc codebase from C to Go `_. It's a great piece of software, but it's a little light on automated testing and test infrastructure. `When porting a recent set of tests `__, everything was absolutely fine on my local machine, but my GitHub Actions tests failed with a slightly enigmatic ``*** buffer overflow detected ***: terminated``. Unfortunately, searching online for that message led to a series of false leads, until I finally discovered ``_FORTIFY_SOURCE``! From https://www.gnu.org/software/libc/manual/html_node/Source-Fortification.html: .. code:: none When the _FORTIFY_SOURCE macro is defined, it enables code that validates inputs passed to some functions in the GNU C Library to determine if they are safe. [..] At runtime, if any of those safety checks fail, the program will terminate with a SIGABRT signal. It turns out that `Ubuntu 24.04 LTS started using FORTIFY_SOURCE=3 `__ while `Debian is still using 2 `__. And my local machine (where I saw no issue) runs Debian, while my GitHub Actions run on Ubuntu latest. Digging into the traceback led me to some slightly suspicious-looking C code that was called by some of the code I'd ported: .. code:: strlcpy (suffix, "000", 5); // TODO: should have proper size and indeed, it turned out what was being passed as ``suffix`` was: .. code:: char digit_suffix[3+1]; /* Suffix abbreviation as 3 digits. */ So although the hardcoded string being passed was only 4 bytes (length 3 plus terminating null) and would fit, giving ``strlcpy`` a ``dstsize`` of 5 and a ``dst`` of size 4 was enough to trigger the enhanced ``_FORTIFY_SOURCE=3`` checks. `One (somewhat inelegant, but adequate) patch later to pass a proper destination size `__ and `all was resolved `__! It is nice to spend most of my time with languages where details like this are handled for me, but it's great to learn about the evolving protections for when they're not!