~sircmpwn/gmni-devel

gmni: src/tofu.c: fix build on `-D_FORTIFY_SOURCE=3` v1 PROPOSED

Sergei Trofimovich: 1
 gmni: src/tofu.c: fix build on `-D_FORTIFY_SOURCE=3`

 1 files changed, 9 insertions(+), 2 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/gmni-devel/patches/49277/mbox | git am -3
Learn more about email & git

[PATCH] gmni: src/tofu.c: fix build on `-D_FORTIFY_SOURCE=3` Export this patch

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