• 0 posts
  • 8 comments
Joined 1 year ago
Cake day: June 6th, 2025
  • (Didn’t read the article.)

    It’s not a secret approach or anything. thiserror gives you that with a simple #[from] attribute annotation on the relevant error variant on your Error enum (which is what your Error type should be).

    In your case, this just works because you’re not attaching custom context to your error. Usually, you would want to attach some context, and in that case, .map_err()would obviously still be needed, and that’s fine. This idea of having to write as little code as possible is stupid.

    Sometimes, attaching context once is sufficient, sometimes it’s not. If it’s the former, then you can still do From in your bigger error enums which have variants from your smaller error enums (e.g. crate-level Error type with variants trivially wrapping module-level Error types).

  • 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.

  • Most tor peers are not relays. So no, tor’s network capacity doesn’t auto-scale with more users, even when you’re sticking to hidden services.

    And you didn’t argue for anonymity from the start. And anonymity is a BIG argument, with bigger design implications than you think.

    Original Freenet (now called Hyphanet) predates both bittorrent and tor. And it’s one early example (and not the only one btw) of how you properly combine anonymous storage with anonymous transport (content addressing too, but that’s more of a jibe against the IPFS meme). It’s also (relatively) slow, and that’s actually intentional, at least in part, because speed can hurt your anonymity (the details are too technical, and that’s not the place to delve into them).

    Bittorrent didn’t lack (native) anonymity because the idea/tech was impossible to imagine. Anonymity didn’t come into the picture because availability and speed were the priorities. The protocol didn’t have encryption from the start either (or sub-piece downloading, or DHT, or PEX, or udp trackers, or uTP transport, but I digress).