9 comments

  • EPWN3D 3 hours ago
    Author here, I posted this in Show HN but someone clearly beat me to it. So I'll repost my blurb from there.

    Various patterns for safer C programming have been cargo-culting around the industry for decades. Because the language evolves intentionally slowly, these patterns rarely get folded into the language as first-class constructs and are passed down through the generations in a sort of oral tradition of programming.

    lib0xc leverages GNUC extensions and C11 features to codify safer C practices and patterns into real APIs with real documentation and real testing. Reduce your casts to and from `void *` with the `context_t` tagged pointer type. Enable type-checked, deferred function invocation with `call_t`. Interrogate structure descriptors with `struct_field_t`. Stop ignoring `-Wint-conversion` and praying you won't regret it when you assign a signed integer to an unsigned integer and use `__cast_signed_unsigned`. These are just a few of lib0xc's standard-library-adjacent offerings.

    lib0xc also provides a basic systems programming toolkit that includes logging, unit tests, a buffer object designed to deal with types, a unified Mach-O and ELF linker set, and more.

    Everything in lib0xc works with clang's bounds-safety extensions if they are enabled. Both gcc and clang are supported. Porting to another environment is a relatively trivial effort.

    It's not Rust, and it's not type safety, but it's not supposed to be. It's supposed to help you make your existing C codebase significantly safer than it was yesterday.

    My employer holds the copyright and has permitted its release under the MIT license.

    • valorzard 2 hours ago
      This might be a dumb question, but using this + clang bounds-safety, whats the difference between this and something like Zig or Odin.

      What do you think C would need in order to reach the user experience of those languages?

      • EPWN3D 1 hour ago
        > This might be a dumb question, but using this + clang bounds-safety, whats the difference between this and something like Zig or Odin.

        I really need to learn more about Zig, but from what I know, there are still worlds of possibilities that a modern, well-designed language offers over something like lib0xc. Zig's ability to evaluate any expression at compile-time is one such example.

        But generally, lib0xc gives you bounds-safety everywhere it can. Languages like Zig and Rust give you type-safety to their own degrees, which I think is a superset.

        > What do you think C would need in order to reach the user experience of those languages?

        Not really having direct user experience, it's hard for me to say. But if I what I can give you is a list of features that would make large parts of lib0xc irrelevant:

        1. Protocols/traits

        2. Allocating from a caller's stack frame (think, returning the result of `alloca` to the caller)

        3. printf format specifiers for stdint.h types and for octet strings

        4. Ability to express function parameter lists as structures

        5. New sprintf family that returns a value which is always less than or equal to the size passed (no negative values)

        Basically, I think that the C standard should be working aggressively to cut down on the use cases for heap allocation and `void *`. And I think that the bounds safety annotations should become first-class language features.

        • anthk 39 minutes ago
          Wouldn't the last case (void *) hurt embedded C development, or retrogaming with direct memory access and pointers?
  • raggi 3 hours ago
    there are no good reasons we don't do this in the standards themselves, C, C++, and POSIX should all be working on editions that add safer APIs and mark unsafe APIs as deprecated, to start a long term migration. we know how to do this, we've had a lot of success with this. there are real engineering concerns, sure, but they're not reasons to not do it. compilers and library chains can retain support for less safe variants for plenty of time.
    • zbentley 3 hours ago
      There are only two kinds of standards: ones that prioritize stability and backwards compatibility over usefulness and security, and ones nobody uses.
    • AlotOfReading 3 hours ago
      The reason this wasn't done by the standards committees is that they spent decades refusing to admit there was even a problem they could help fix. And if there was a problem, it was easily avoided by just writing better code. And if writing better code wasn't enough, well it was certainly too expensive to provide as a debug option. And if it wasn't too expensive to provide as a debug option, the implementors should really lead the way first. And on and on.

      The C committee at least seems to get it now. The C++ committee still doesn't, led in large part by Bjarne.

    • anthk 40 minutes ago
      C and POSIX aren't related to C++ at all.
  • jabl 3 hours ago
    Unfortunate naming. I thought this was about https://libxc.gitlab.io/ but there's an extra '0' in the name here.
  • nxobject 3 hours ago
    I'm curious – is MSFT using this in production, or is this a "20% time" project? I'm not sure MSVC could compile the GNU extensions used.
    • EPWN3D 3 hours ago
      Author here. It is not currently in production, but it is part of a project in Azure which will go to production at some point. I'm actually leaving Microsoft next week and fully intend to keep working on it if I can reach an agreement to do so with my new employer.
  • matheusmoreira 4 hours ago
    Interesting. I'll be studying this later tonight so I can apply it to my C projects. Especially clang's -fbounds-safety.
  • atilimcetin 3 hours ago
    The title looks very promising. I’ve added this library to my to-do list to take a deeper look at it. Using this standart library within restricted safe subset of C++ can be a strong opponent for Zig (at least for myself).
    • EPWN3D 3 hours ago
      Haven't really verified that it works with C++, but I tried my best to guard the stuff I knew would be problematic with #if __cplusplus. Happy to have a PR that makes C++ happier with it.
  • andrefelipeafos 2 hours ago
    Quick question for those who've tried it — does this play with existing C codebases incrementally, or is it more of a "new project only" situation? The README didn't make that obvious to me.
    • EPWN3D 1 hour ago
      It's designed to be incremental. For example, you can do a search for `sprintf` and replace it with `ssprintf`. The function signature is the same. Any instance of printing to a character array just works. Think of the APIs as "the stuff you usually do by hand, but safer".

      If you get compiler errors, it means you were printing to a heap-allocated buffer (or a buffer whose bounds you did not know), and you should be propagating bounds and using `snprintf`.

      Integer conversion is the same way. If you have something like

      int v1; uint64_t v2;

      <stuff happens>

      v2 = (uint64_t)v1;

      Then you can replace it with

      v2 = __cast_signed_unsigned(uint64_t, v1);

      and you'll get a runtime trap when v1 is a negative value, meaning you can both enable -Wint-conversion and have defined behavior for when the value in a certain integer type is not representable in another.

  • platinumrad 5 hours ago
    I truly hope something like this catches on. There is so much low hanging fruit in both the C and C++ standard libraries. Spatial memory could be 90% solved in both languages by mandating the use of safe interfaces.
  • bananaboy 2 hours ago
    This is very cool!