So I gave the actual code a one minute look (literally).
Picked src/radicle/util.c, since that was the last file touched.
The level of defensive programming doesn't look that good (and I'm trying to be nice here).
Here is an example, and note that I didn't do C in a while:
#include <stdio.h>
#include <string.h>
void rad_rstrip_nl(char* str) {
int len_str = strlen(str);
if (str[len_str-1]=='\n') {
str[len_str-1] = 0;
}
}
bool rad_get_input (char* str, size_t bufsiz) {
if (!fgets(str,bufsiz,stdin)) return false;
rad_rstrip_nl(str);
return true;
}
int main() {
char a[] = {0,0,0,0};
bool i = rad_get_input(a, 4);
printf("%lu\n", strlen(a));
rad_rstrip_nl(a);
return i;
}
The two functions above main() are copy-pasted from that file.
Let's zoom in:
int len_str = strlen(str);
if (str[len_str-1]=='\n') {
Here we're accessing str[len_str-1] without checking len_str first.
But you might be thinking, maybe len_str can't be zero!
Let's compile first with the AddressSanitizer enabled:
# compile
% gcc -Wall -fsanitize=address t.c -o t
Now let's see how easily we can have fun:
% echo -n '\0' | ./t
=================================================================
==2949689==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7ba827af001f at pc 0x56032434d259 bp 0x7fff1d199010 sp 0x7fff1d199000
READ of size 1 at 0x7ba827af001f thread T0
#0 0x56032434d258 in rad_rstrip_nl (/tmp/t+0x1258) (BuildId: 1ee68e4d67960002de80ae290c8811c63f94aa51)
#1 0x56032434d311 in rad_get_input (/tmp/t+0x1311) (BuildId: 1ee68e4d67960002de80ae290c8811c63f94aa51)
#2 0x56032434d3e4 in main (/tmp/t+0x13e4) (BuildId: 1ee68e4d67960002de80ae290c8811c63f94aa51)
#3 0x7fa82a227740 (/usr/lib/libc.so.6+0x27740) (BuildId: 020d6f7c33b2413f4fe10814c4729dce1387f049)
#4 0x7fa82a227878 in __libc_start_main (/usr/lib/libc.so.6+0x27878) (BuildId: 020d6f7c33b2413f4fe10814c4729dce1387f049)
#5 0x56032434d124 in _start (/tmp/t+0x1124) (BuildId: 1ee68e4d67960002de80ae290c8811c63f94aa51)
(The rest of AddressSanitizer output omitted.)
Another function from the same file:
char* rad_strcpy (char* out, const char* inp, int from, int len) {
const char* inp_shifted = inp+from;
int len_inp_shifted = strlen(inp_shifted);
if (len <= len_inp_shifted) {
memcpy(out,inp,len);
out[len] = 0;
}
else {
memcpy(out,inp,len_inp_shifted);
out[len_inp_shifted] = 0;
}
return out;
}
Here, inp is shifted before inp length is checked, which doesn't look safe. But my one minute is up, so I didn't dive into the function callers.
Pretending C is a good choice in 2026, then not being extra vigilant with defensive programming, is not a good look. I remember myself being more vigilant in my wrappers even when I was a beginner.
This is made worse by the developer repeating literal memes like:
One issue I have with rust is that it adds another layer of trusting the compiler isn't backdoored. All UNIX/Linux systems use the gcc toolchain
Maybe such an enlightened developer should know that you can bootstrap rustc from mrustc using GCC.

