cybersecurity · beginner · ~12 min
Build a bounded-buffer text formatter with `snprintf` and proper overflow handling.
Turn a single security finding into a Markdown writeup with a bounded, overflow-safe formatter.
Implement int render_finding(const finding_t *f, char *out, size_t cap) over:
typedef struct {
const char *title;
const char *severity;
const char *asset;
const char *evidence;
const char *recommendation;
} finding_t;
It writes f into out (capacity cap) as Markdown and returns the number of bytes written (excluding the trailing NUL), or -1 on failure.
f: a pointer to a fully-populated finding_t the grader passes.out: caller-provided buffer of size cap.Bytes written (excluding NUL), or -1 if f/out is NULL, cap == 0, any field of f is NULL, or the text would not fit. The exact layout (note the blank lines):
## <title>
**Severity:** <severity>
**Asset:** <asset>
### Evidence
<evidence>
### Recommendation
<recommendation>
(a trailing newline follows the recommendation).
title="Missing HSTS header", severity="Medium", ...
-> buffer begins "## Missing HSTS header\n**Severity:** Medium\n..."
return value == strlen(out)
tiny 16-byte buffer -> -1
NULL finding -> -1
finding with a NULL field -> -1
f, NULL out, cap == 0, or any NULL field returns -1.snprintf and check its return: < 0 or >= cap means overflow → return -1.Findings without a writeup don't ship. A bounded snprintf formatter turns a struct into a deliverable.
A pointer to a populated finding_t, an output buffer out, and its capacity cap.
Bytes written excluding the NUL, or -1 on any NULL input, cap==0, NULL field, or overflow.
Use snprintf; treat return <0 or >=cap as overflow; reject any NULL.
#include <stddef.h>
typedef struct {
const char *title;
const char *severity;
const char *asset;
const char *evidence;
const char *recommendation;
} finding_t;
int render_finding(const finding_t *f, char *out, size_t cap) {
/* TODO */
(void)f; (void)out; (void)cap;
return -1;
}
Trusting snprintf's return without checking against cap. Forgetting the blank lines between sections. NULL inputs not rejected.
Tiny buffer → -1. NULL pointer or NULL field → -1. Exact-fit buffer → bytes match strlen(out).
O(n) where n is the sum of input string lengths.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.