Before the change the build with `-D_FORTIFY_SOURCE=3` failed as:
In file included from ...-glibc-2.38-27-dev/include/stdio.h:964,
from src/tofu.c:9:
In function 'snprintf',
inlined from 'xt_end_chain' at src/tofu.c:82:3,
inlined from 'xt_end_chain' at src/tofu.c:70:1:
...-glibc-2.38-27-dev/include/bits/stdio2.h:54:10: error: '__builtin___snprintf_chk' specified bound 4 exceeds destination size 3 [-Werror=stringop-overflow]
54 | return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
55 | __glibc_objsize (__s), __fmt,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
56 | __va_arg_pack ());
| ~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
I think it's a legitimate report as last write segment every intends to
write 3 bytes (2 hex values and a null terminator), but `snprintf()`
always gets passed 4 bytes as an available buffers size.
While normally buffer overrun could not happen `-D_FORTIFY_SOURCE=3`
instructs `snprintf()` to always checks if there are enough bytes
available in the destination buffer and `abort()`s if the check fails.
To avoid passing excessively large buffer I made buffer size
conditional.
---
src/tofu.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/tofu.c b/src/tofu.c
index 0923aed..f63d37b 100644
--- a/src/tofu.c+++ b/src/tofu.c
@@ -79,8 +79,15 @@ xt_end_chain(const br_x509_class **ctx)
char fingerprint[512 / 8 * 3];
for (size_t i = 0; i < sizeof(cc->hash); ++i) {
- snprintf(&fingerprint[i * 3], 4, "%02X%s",- cc->hash[i], i + 1 == sizeof(cc->hash) ? "" : ":");+ size_t l = 4;+ const char *trail = ":";+ /* Last entry. */+ if (i + 1 == sizeof(cc->hash)) {+ l = 3;+ trail = "";+ }+ snprintf(&fingerprint[i * 3], l, "%02X%s",+ cc->hash[i], trail); }
enum tofu_error error = TOFU_UNTRUSTED_CERT;
--
2.43.0