Share good ideas and conversation.   Login, Join Us, or Take a Tour!
comment

For example, in C or C++, you can write the following:

  int array[5] = {1,2,3,4,5};

printf("%d", array[10]);

It will compile fine and probably run fine...and spit out some value from some place in memory that you "ought" not to access.

In Rust, however,

  let array = [1,2,3,4,5];

println!("{}", array[10]);

results in a runtime panic--the program quits, rather than performing an illegal memory access.

A better example here is how Rust eliminates use-after-free bugs at compile time because it has very strict semantics about who owns what. For example, in C, you could write this:

  void do_stuff(int* thing) {

// do something to thing

delete [] thing;

}

  // elsewhere

int* x = new int[5];

do_stuff(x);

printf("%d", x[0]);

That would compile and maybe it would run fine and spit out junk memory or maybe it would segfault. The equivalent rust would look like this:

  fn do_stuff(thing : [i32; 5]) {

// do something to thing

// Rust deallocates thing at the end of this function

}

  let x = [1,2,3,4,5];

do_stuff(x);

println!("{}", x[0]); // COMPILE ERROR!

This is because Rust is really really picky about who "owns" what thing, and when I call do_stuff on x, I give do_stuff ownership of x. Once I give away that ownership, I can't use x anymore since it's not mine!

For an example of where that can be a security issue, just this week Linux had a double-free bug (that easily turns into a use-after-free bug) that let any user become root.

Other languages get memory safety by using a garbage collector. I could talk your ear off about other bugs that can be caught at compile time by languages with very strong type systems (like Haskell) but I will spare you =]

The tools I have in mind are languages like Agda or Idris, which are basically proof engines that happen to also produce executable code. At this point they are not very user friendly or easy to write big programs in, though.