Live data from Hacker News

Comparative unsafety

flak.tedunangst.com

71–80 of 99 posts

Re: Comparative unsafety

#71
post #58
post #56

Earlier quoted context omitted.

If you want to know whether your writes are getting out, you will get a much more reliable indication from fsync(). So, instead of exhorting people to check close()'s result, you should exhort them to fsync() first and check that result. A very old programming principle says, "Never check for any failure you are not equipped to act on." It is sometimes used as a reminder to ensure you are always so equipped.

My understanding is fsync() will tell you more than close() only when a flush of the OS cache fails to make it to disk. Is there anything else? The problem with calling fsync() is that you have to wait for it to finish. There are many scenarios where the extra data integrity guarantees you get from calling fsync() aren't important.

close() will fail to report a wide variety of failures.

But Cesar is right, you can't re-try it. And fsync() can be very slow on most commonly-used file systems. We are fortunate that now SSDs are fast.

Re: Comparative unsafety

#72
post #68
post #59

Earlier quoted context omitted.

I wonder what a good approach to safe pointer arithmetic would be.

Rust's actually-safe pointer arithmetic is done via slices (because it's necessary to track the length): slice = &slice[1..]; It compiles to roughly `ptr++; len--;` and a bounds check if necessary. `1234 as *const u8` and `ptr.offset(n)` are also safe, because Rust allows invalid/dangling pointers to exist if they're never dereferenced.

This answer addresses the letter of jdc's musing, but not the gist. The code that you've supplied may be "safe", but the issue is that there's no way to constrain pointer arithmetic such that the result always points at a valid location which can withstand dereferencing.

Re: Comparative unsafety

#75
post #70

Earlier quoted context omitted.

> Take for instance malloc. It can return NULL but you don't check for it, because that's just the way it's done. malloc is worth null-checking, if only to assert/panic/breakpoint/fatal early and cleanly. Even on linux with overcommit, it'll return null on memory space exhaustion, which can easily happen even in a 64-bit processes if someone feeds your program maliciously crafted data with an oddball size. A crash du…

That's a very interesting idea for exploitation, I bet a lot of things are vulnerable to that. But anyway I doubt that people do it even though they should.

> But anyway I doubt that people do it even though they should.

A lot of codebases certainly skip such checks.

But it's also fairly common to at least have a wrapper function that mallocs + triggers a fatal error if it returned null - and then to use that wrapper throughout the codebase. Gamedev tends to roll it's own allocators anyways, or need oddball system allocators for some resources, so they typically have a decent place to stick such checks already.

Re: Comparative unsafety

#76
post #19

Earlier quoted context omitted.

I'm pretty sure it's explicitly intended solely as punishment for people who have javascript enabled.

Fwiw I think it's pretty hilarious. Also I warmly recommend to view-source, the makeprogress() function is a true delight.

Abstractly it’s sort of funny as a joke against JavaScript, but it’s really not funny at all when the butt of the joke is people who have JS enabled on their browsers. It’s just elitist and obnoxious.

I like jazz and think rock/pop generally sucks. If I prefaced every blog post with “people who like rock are too dumb to understand the following” I wouldn’t be making a funny joke about music. I’d just be an asshole.

Re: Comparative unsafety

#77
post #43

Earlier quoted context omitted.

> From my perspective as someone who knows Rust but primarily works with high-level languages like JavaScript, some developers who from a background of unsafe languages (particularly C and C++) seem incredibly cavalier around `unsafe` blocks in Rust code. It's like they're desensitised to the unsafety. That's true. If you are used to 100% of your code being within the equivalent of a Rust "unsafe" block, having over…

> Even if one in ten lines are marked as "unsafe", that's already many times less "unsafe" than what they are used to in their C or C++ code. As a Rust programmer who's written safe code and some unsafe abstractions, one in ten lines being unsafe means that the remaining 90% of your lines need to be written with the same care as your unsafe code, to avoid feeding invalid arguments into unsafe operations which cause U…

I'm baffled by why this answer is downvoted. It matches my experience precisely, and articulates the proper approach for isolating `unsafe` code so that the safe code around isn't so tricky to write.

Re: Comparative unsafety

#78
What a great blog post.

This happens in garbage collected languages too. I've been bitten by this in Java (JNI).

Yes, this needs to be caught by the compiler, damn it. And linters shouldn't complain about style either. Style checking should be a separate and very configurable tool.

Re: Comparative unsafety

#79

> Why am I using my own ffi version of chown instead of the libc crate? The libc crate prototypes chown with unsigned uid_t and gid_t types, and I want to pass -1 because I'm not interested in changing the group. I'll spare you the long rant about how one should never redeclare system interfaces if you can't take the time to do so properly, because it turns out if you dig into it, uid_t boils down to uint32_t , but e…

If you read the POSIX specification for chown you'll see that the "leave unchanged" sentinel value is, for UIDs, defined to be (uid_t) -1 . I can't be bothered to try it myself but I'm fairly sure the author could just have written (-1i32) as uid_t and gotten some of their life back.

Yes. Specifically, POSIX does not specify whether id_t, uid_t, gid_t, or pid_t are signed or unsigned, so whenever it refers to the "default"/"leave alone"/"unspecified" value, it always does it as a cast of -1.

Re: Comparative unsafety

#80

> Why am I using my own ffi version of chown instead of the libc crate? The libc crate prototypes chown with unsigned uid_t and gid_t types, and I want to pass -1 because I'm not interested in changing the group. I'll spare you the long rant about how one should never redeclare system interfaces if you can't take the time to do so properly, because it turns out if you dig into it, uid_t boils down to uint32_t , but e…

Although `~0` assumes twos-complement signed numbers. Which, well, is probably a safe assumption, but still.
Post reply on HN