Live data from Hacker News

Secure Rust Guidelines

anssi-fr.github.io

21–30 of 61 posts

Re: Secure Rust Guidelines

#21
post #18

I'm having problems fulfilling this requirement in my libs: "Crates providing libraries should never use functions or instructions that can fail and cause the code to panic." The Rust standard library Vec, HashMap etc. can cause a panic in Rust, if the device (such as a mobile phone with a small memory) runs out of memory. C and C++ standard libraries (malloc, std::vector, std::map..) can handle those situations by r…

Oh, I never even considered this... But how would Rust ever be able to signal allocation failures in such cases?

Same as any other failure; functions that may try to allocate memory and fail will return a Result instead of just a T.

Re: Secure Rust Guidelines

#22

I'm having problems fulfilling this requirement in my libs: "Crates providing libraries should never use functions or instructions that can fail and cause the code to panic." The Rust standard library Vec, HashMap etc. can cause a panic in Rust, if the device (such as a mobile phone with a small memory) runs out of memory. C and C++ standard libraries (malloc, std::vector, std::map..) can handle those situations by r…

https://www.youtube.com/watch?v=ARYP83yNAWk mentioned that the notion that C++ could handle out-of-memory was a purely theoretical wishful thinking. In practice it could not.

Re: Secure Rust Guidelines

#23
post #18

I'm having problems fulfilling this requirement in my libs: "Crates providing libraries should never use functions or instructions that can fail and cause the code to panic." The Rust standard library Vec, HashMap etc. can cause a panic in Rust, if the device (such as a mobile phone with a small memory) runs out of memory. C and C++ standard libraries (malloc, std::vector, std::map..) can handle those situations by r…

Oh, I never even considered this... But how would Rust ever be able to signal allocation failures in such cases?

Eg. with Vec, every operation that may trigger reallocation should return Result.

Re: Secure Rust Guidelines

#24
post #16

Earlier quoted context omitted.

You're skipping half the recommendation though: > Array indexing must be properly tested, or the get method should be used to return an Option. Fwiw, for anyone who’s dabbled with Haskell this is SOP. Any result that could be undefined is returned as a Maybe (Haskell’s version of Option). If this seems odd to anyone, understanding it in Haskell will probably help understand it better in Rust too: http://learnyouahask…

Er, don't Haskell's head and (!!) functions default to throwing an exception? $ ghci Prelude> let a = [3, 4, 5] Prelude> a !! 0 3 Prelude> a !! 3 *** Exception: Prelude.(!!): index too large Prelude> head [] *** Exception: Prelude.head: empty list I don't think Haskell is really different from Rust in this respect. Both have a wrapper type for optional values with good syntax, but in both, there's still some syntax s…

This was posted on /r/rust a couple days ago: https://notes.iveselov.info/cheatsheet-rust-option-vs-haskel...

Re: Secure Rust Guidelines

#25

I personally strongly disagree with: Functions or instructions that can cause the code to panic at runtime must not be used. First of all, they kind of dodge this later by saying "Array indexing must be properly tested" (else it can panic) -- everyone thinks they write code which is "properly tested". Personally, I often write panicing code -- if the code gets in a state where I have no idea how to fix it, I panic. F…

Panicking is, in many ways, the best-case scenario for code that contains a bug. A bug that causes a panic is much easier to find through fuzzing, property testing, even static analysis or analyzing failures in production. It also prevents the bug from "infecting" other code by allowing the program to proceed in an invalid state.

If you don't want a panic to take down the whole system, you can isolate the code in a thread and use a supervision tree, or use `catch_unwind` to let the thread perform cleanup and then continue from a known state.

Using `slice.get()` and returning `Option` or `Result` for failures that should never happen in correct code is not an improvement. It leads to the same unwinding behavior, as the failure gets passed up the call stack, but with more manually-written code, and more error-handling paths that are hard or impossible to test (because if the program is correct then they are unreachable). It infects calling functions and changes public APIs.

Clearly, the best practice is "don't write code with bugs." If your code is bug-free, then it is also panic-free. But we don't really have the tools and techniques to do that all the time in general. The second-best option may be to write code that panics when there is a bug. (People saying "write code that can't panic" are often really just saying "don't write bugs.")

(See also "crash-only software," from the Erlang school of reliability engineering.)

Re: Secure Rust Guidelines

#26
post #7

I personally strongly disagree with: Functions or instructions that can cause the code to panic at runtime must not be used. First of all, they kind of dodge this later by saying "Array indexing must be properly tested" (else it can panic) -- everyone thinks they write code which is "properly tested". Personally, I often write panicing code -- if the code gets in a state where I have no idea how to fix it, I panic. F…

> First of all, they kind of dodge this later by saying "Array indexing must be properly tested" (else it can panic) -- everyone thinks they write code which is "properly tested". You're skipping half the recommendation though: > Array indexing must be properly tested, or the get method should be used to return an Option . emphasis mine > Also, in rust if we don't want to panic we need to never use array indexing and…

Saying "properly tested" doesn't seem useful to me. What is "properly tested"? I'm sure people thing most array overflows in C libraries are "properly tested", as noone wants to cause memory corruption.

Re: Secure Rust Guidelines

#27
post #7

Earlier quoted context omitted.

> First of all, they kind of dodge this later by saying "Array indexing must be properly tested" (else it can panic) -- everyone thinks they write code which is "properly tested". You're skipping half the recommendation though: > Array indexing must be properly tested, or the get method should be used to return an Option . emphasis mine > Also, in rust if we don't want to panic we need to never use array indexing and…

Saying "properly tested" doesn't seem useful to me. What is "properly tested"? I'm sure people thing most array overflows in C libraries are "properly tested", as noone wants to cause memory corruption.

> Saying "properly tested" doesn't seem useful to me. I'm sure people thing most array overflows in C libraries are "properly tested"

It is useful in the sense that it's for a restricted set of constructs, in the same sense that `unsafe` blocks are not outright forbidden but they should be justified and because they're restricted in span they can be more easily tested than your entire C codebase.

Since array indexing would be recommended against by default (and either iterators or `get` would be the normal way to handle it), the number of places where it is used should be small and thus easy to check for, and test extensively if not exhaustively.

Re: Secure Rust Guidelines

#28
post #16

Earlier quoted context omitted.

Er, don't Haskell's head and (!!) functions default to throwing an exception? $ ghci Prelude> let a = [3, 4, 5] Prelude> a !! 0 3 Prelude> a !! 3 *** Exception: Prelude.(!!): index too large Prelude> head [] *** Exception: Prelude.head: empty list I don't think Haskell is really different from Rust in this respect. Both have a wrapper type for optional values with good syntax, but in both, there's still some syntax s…

> Hoogle doesn't seem to find me a function like Rust's .get() in the standard library In practice, you don't really need one - the safe alternative to "xs !! n" is pattern-matching on the result of "drop n xs", as that's [] if xs has ≤n elements: https://www.haskell.org/onlinereport/standard-prelude.html#$...

> In practice, you don't really need one - the safe alternative to "xs !! n" is pattern-matching on the result of "drop n xs", as that's [] if xs has ≤n elements:

Great so instead of `xs !! n` you're supposed to write

    case drop n xs of
        [] -> …
        x :: _ -> …
that seems… less than likely?

Re: Secure Rust Guidelines

#29
post #7

Earlier quoted context omitted.

> First of all, they kind of dodge this later by saying "Array indexing must be properly tested" (else it can panic) -- everyone thinks they write code which is "properly tested". You're skipping half the recommendation though: > Array indexing must be properly tested, or the get method should be used to return an Option . emphasis mine > Also, in rust if we don't want to panic we need to never use array indexing and…

You're skipping half the recommendation though: > Array indexing must be properly tested, or the get method should be used to return an Option. Fwiw, for anyone who’s dabbled with Haskell this is SOP. Any result that could be undefined is returned as a Maybe (Haskell’s version of Option). If this seems odd to anyone, understanding it in Haskell will probably help understand it better in Rust too: http://learnyouahask…

> Fwiw, for anyone who’s dabbled with Haskell this is SOP. Any result that could be undefined is returned as a Maybe (Haskell’s version of Option).

It would be nice if that were true but that ain't exactly the case is it?

AFAIK exhaustive pattern matching still isn't enabled by default, and the prelude is full of partial functions, especially on lists (to such an extent that GHC has a utility function just for blowing up on empty lists: https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-L...)

Re: Secure Rust Guidelines

#30
post #18

Earlier quoted context omitted.

Oh, I never even considered this... But how would Rust ever be able to signal allocation failures in such cases?

Same as any other failure; functions that may try to allocate memory and fail will return a Result instead of just a T.

Which would be pretty painful for everyone not working in a memory-constrained environment (at a guess, that's most developers). Much like std:println! panicking instead of returning an error, ergonomics are important too a lot of the time.
Post reply on HN