2025-07-23 _FORTIFY_SOURCE
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:
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:
strlcpy (suffix, "000", 5); // TODO: should have proper size
and indeed, it turned out what was being passed as suffix
was:
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!