9 ms·
Automatically Translating C to Rust
- pizlonator 1y agoThe code I've seen that was autotranslated from C to Rust has an absolutely hopeless number of unsafe statements. You're better off using Fil-C.
- levodelellis 1y agoI find it funny AF that Fil-C is safer than languages with the unsafe keyword. Who knew C could be so safe with a proper compiler
- deleted 1y ago[deleted]
- uecker 1y agoThe memory model of C is intentionally designed to allow safe implementations (still from the time of hardware-segmented methods).
- CoastalCoder 1y agoCould you expand on that?
- aw1621107 1y agoI believe the claim is that there's nothing in the C standard that requires implementations to be unsafe. If they wanted to, they could bounds check pointers, check allocations are still alive when pointers are dereferenced, etc. and still be conformant to the standard.
- uecker 1y agoEven more, certain rules are specifically designed to make such checks possible while being conformant to the standard.
- pornel 1y agoNothing in the C standard requires bytes to have 8 bits either. There's a massive gap between what C allows, and what real C codebases can tolerate. In practice, you don't have room to store lengths along pointers without disturbing sizeof and pointer<>integer casts. Fil-C and ASAN need to smuggle that information out of band.
- timeon 1y ago> proper compiler Not just compiler but GC as sell. So it does note solve same problem as Rust.
- levodelellis 1y agoWould you rather have a gc or unsafe? In just about every language I seen people use .clone rather than deal with problems so I suspect a lot of cases a GC can be just fine or faster. Although I'm comfortable with memory management and rather use C or C++ if I'm writing fast code
- timeon 1y ago> Would you rather have a gc or unsafe? Like in case where you can't use Rust? (ie.: existing codebase). Sure that is what Fil-C is good for. Point is that Fil-C does not solve the problem Rust does. It is more like band-aid. (Maybe my comment was misunderstood because of typo: sell/well) Also I think there is huge difference between GC and fact that some people use .clone() somewhere.
- levodelellis 1y ago[flagged]
- Ar-Curunir 1y agoIt is well known that GC allows you to solve memory safety problems
- Mond_ 1y ago? Putting a program into a safe container or isolation boundary (this is roughly what GC is in this context) causes it to be memory safe. This is not an interesting observation. It also causes it to be significantly slower, to the point of not being competitive anymore.
- ralegh 1y agoWonder if it would be better to auto translate to broken rust, ie forcing the user to fix memory issues. I imagine that would lead to pretty big refactors in some cases though.
- Animats 1y agoNo. What comes out of C2Rust is awful. The Rust that comes out reads like compiler output. Basically, they have a library of unsafe Rust functions that emulate C semantics. Put in C that crashes, get Rust that crashes in the same way. Tried that on a JPEG 2000 decoder.
- stared 1y agoTried Claude Code with explicit instructions to create idiomatic code and avoid unsafe statements?
- jrpelkonen 1y agoFil-C is an innovative approach and a great technical achievement. However, I wouldn't suggest that it is an universal solution without caveats. For instance, the performance penalty of up to 4x is not acceptable in a lot of cases. Also, the c2rust output is rough but not hopeless: There are real world success stories of rust projects that were bootstrapped via c2rust, e.g. https://tweedegolf.nl/en/blog/151/translating-bzip2-with-c2rust https://tweedegolf.nl/en/blog/151/translating-bzip2-with-c2r...
- pizlonator 1y agobzip2 is tiny, has relatively low overhead in Fil-C (forget exactly what it is but not 4x), and last I checked this Rust version still has >100 uses of unsafe.
- galangalalgol 1y agoFil-C doesn't stop the data race problems the borrow checker would catch does it? Has anyone tried pointing an agentic ai at recreating a c utility by looking only at the man page and using differential fuzzing? It isn't a port, so no licensing issues, and the code would use unsafe, and presumably be more idiomatic. I have no idea if it would ever complete, or just get stuck in an endless loop. Or even if it did succeed, how many joules it would use.
- pizlonator 1y ago> data race problems No, Fil-C just makes races memory safe. Also this is sort of changing the topic a bit since bzip is single threaded
- galangalalgol 1y agoEven if it wasn't single threaded, it would probably have been fine grained OMP style multithreaded which runs into far fewer issues. I was just making sure I understood what Fil-C was doing. I hadn't heard of it. It seems like a great thing.
- kevincox 1y agoI would assume that these two use cases are basically completely separate. Auto-translate from C to Rust would serve as a great step to starting a porting project. Now you can incrementally re-write the "basically C" auto-ported code to "proper Rust" without dealing with FFI and other pains that come from function-by-function ports. Fil-C is great for running software that you don't want to port. (Or don't yet have the resources to port.) Interestingly there is probably a gap between the two. When your project is pure C you can use Fil-C. However I don't think Fil-C supports Rust. So assuming that the initial C to Rust translation doesn't produce 100% safe code (I'm not aware of any current tools that do this) you have this middle state where you can no longer compile with Fil-C but have lots of unsafe Rust code. So maybe there is a use case for Fil-Rust where you compile your Rust program so that even unsafe blocks are in fact safe. This could be used until you complete the port.
- procaryote 1y agoThe other direction might be more interesting, in case rust drops in popularity in a couple of years, leaving behind a bunch of "let's rewrite in rust" efforts
- speedgoose 1y agoI am not convinced that anyone would take a working rust project and rewrite it in C. I don’t see any good reason to do so. When rust will lose popularity, it is going to happen eventually, I would bet it’s in favour of a newer and more promising programming language. Not C.
- VBprogrammer 1y agoI think Rust has hit critical mass. It's now basically the default choice for something you want to perform well but want to be reasonably secure. For example, uv in the python ecosystem.
- m00dy 1y agoRust is the clear winner of the LLM era. With code generation being so effortless, why would you write in any other language?
- throawayonthe 1y agoi don't use LLMs, but i've heard people complain current LLMs are not good at writing Rust
- wizzwizz4 1y agoCurrent LLMs are not good at writing any language you actually understand, unless you do so much of the work that you might as well have written the whole program yourself. They're excellent at doing things I'm not an expert at, though! https://en.wikipedia.org/wiki/Gell-Mann_amnesia_effect https://en.wikipedia.org/wiki/Gell-Mann_amnesia_effect
- Animats 1y agoThe article doesn't address the hard problem of figuring out array sizes. There's some work going on as part of the DARPA TRACTOR program to work on that. This area, of course, is the usual cause of buffer overflows. The goal is to convert C pointers to Rust arrays, pointer arithmetic to Rust slices, and array allocations to Vec initialization. The hard problem is figuring out the sizes of arrays, which is going to require global analysis down the call chain. If you're going to publish papers on this, please address that problem.
- uecker 1y agoOf course, one you have identifies the bounds to each pointer you could just do bounds checking in C.
- AlotOfReading 1y agoThat's not actually sufficient in the general case where the pointer may not be the type of the underlying object. You also have to respect strict aliasing even if the bounds are correct. This isn't true in the same way in Rust because memory is untyped. You only need to ensure basic memory validity (range, initialization, alignment, etc).
- uecker 1y agoYes, you also do not want to do random casts, but this is even easier. I do not get your point out memory validity in Rust. What if you write where a pointer is stored, or even a boolean?
- AlotOfReading 1y agoI'm talking about type punning specifically here. There's a lot of old C code out there that stores everything in int * buffers and casts pointers back to the correct type. I'm even aware of one toolchain for a widely used MCU that typedef'd char to int (i16). I believe this would be legal in Rust today if you respected the other rules, with the caveat that it wouldn't be remotely idiomatic or possible without unsafe.
- jurschreuder 1y agoIn a way this is strange because there us a huuuge new area of vulnerabilities caused by LLMs writing code that DWARFS the read/write out of array bounds issues C has.
- cue_the_strings 1y agoI agree. But on the other hand, let's not kid ourselves, array out of bounds, use after free, resource leaks and bad type system, all of this isn't even close to an exhaustive list of C downsides. Beyond its direct limitations, C inspires an approach that is vastly inferior even if you follow all the best practices. Even compared to (modern) C++ it's much worse. I say this and I kind of like C. If the approaches described in the article save us 30% of the effort of translating C codebases to Rust, it's still worth trying; we're unfortunately not very close to complete automation, but that's something worthy of pursuit.
- tmountain 1y agoI understand the issues related to LLM leaking and re-distributing "private" information, but I'm curious which category of concerns you're referring to. Would you mind giving some context (genuinely curious) ?
- jurschreuder 1y agoYou can look at the vulnerabilities found graph of github. It stays about the same for years and then skyrockets up at around the time LLMs were invented. And they are all pretty simple vulnerabilities, exploitable even to people knowing nothing about how to get root access from a binary that has an out of bounds condition somewhere in randomly shuffled memory layout in a specific version if a C program.
- pornel 1y agoThe code needs to pass integrity checks of the safe Rust subset, which is a different challenge than writing dangerous code without feedback.
- veltas 1y agoAutomatically translating C to unsafe Rust is pointless, the resultant code is harder to read and there's no improvement in understanding how to get the code maintainable and safe, that requires tons of manual work by someone with a deep understanding of the codebase. Generally the Rust community as well don't seem to have an answer on how to do this incrementally. In business terms we have no idea how to do work slices with demonstrable value, so no way to keep this on track and cut losses if it becomes too much work. This also strongly indicates you're 'stuck' with Rust when you're done, maybe a better and less unidiomatic C++ killer comes later and sounds like you're either going to have to rewrite the whole thing or give up. I'm definitely open to wisdom on this if anyone disagrees because it is valuable to me and probably most of the readers of this comment section.
- zozbot234 1y ago> Generally the Rust community as well don't seem to have an answer on how to do this incrementally. You can very much translate C to Rust on a function-by-function basis, the only issue is at the boundary where you're either left with unsafe interfaces or a "safe" but slow interop. But this is inherent since soundness is a global property, even a tiny bit of wrong unsafe code can spoil it all unless you do things like placing your untrusted code in a separate sandbox. So you can do the work incrementally, but much of the advantage accrues at the end.
- pizza234 1y ago> You can very much translate C to Rust on a function-by-function basis, the only issue is at the boundary Absolutely not. There are many restrictions of Rust that will prevent that. Lifetimes, global state come to mind first. Think about returning pointer to some owned by the caller - this can require massive cascading changes all over the codebase to be fixed.
- zozbot234 1y agoThese are restrictions of idiomatic Safe Rust. You can use either unsafe Rust or, in many cases, less idiomatic but still Safe Rust to sidestep them. (For instance, "aliasable mutable" but otherwise valid references which can often be expressed as &Cell<T>, etc.) You might still need a "massive cascading change" later on to make the code properly idiomatic once you have Rust on both sides of the boundary, but that's just a one-time thing and quite manageable.
- deleted 1y ago[deleted]
- alkonaut 1y agoThe key invention here would be to translate from idiomatic C to idiomatic - safe - Rust. That also sounds exactly like the kind of invention that would make me fear for my job and claim AGI has all but arrived. Just syntactically translating C code to mostly unsafe or non-idiomatic Rust seems like a pretty pointless excercise?
- pantalaimon 1y agoI just upgraded my Ubuntu to the new version with Rust written Coreutils - this is insane % size /usr/bin/ls text data bss dec hex filename 10086795 731540 2104 10820439 a51b57 /usr/bin/ls % ls -sh /usr/lib/cargo/bin/coreutils/ls 11M /usr/lib/cargo/bin/coreutils/ls % du -sh /usr/bin 1.5G /usr/bin
- gpm 1y agoThe entire rust coreutils package, as installed, is 12 MB https://packages.ubuntu.com/questing/rust-coreutils https://packages.ubuntu.com/questing/rust-coreutils Which is nearly double the gnu coreutils package but still a complete nothing burger: https://packages.ubuntu.com/questing/gnu-coreutils https://packages.ubuntu.com/questing/gnu-coreutils I think what's happening here is that they've all been compiled into one binary, and then that one binary hardlinked to a variety of names like /usr/bin/ls. Since they all show as having the same inode and the same size. The other 1.5G of your 1.5G /usr/bin is unrelated to rust coreutils.
- pantalaimon 1y agoYou are absolutely right! % du -sh /usr/lib/cargo/bin/ 13M /usr/lib/cargo/bin/ Just a bit odd they went for hard links instead of soft links, makes it harder to tell that it's all the same file.