
Pointers Gone Wild - lelf
http://goto.ucsd.edu/~rjhala/liquid/haskell/blog/blog/2014/05/28/pointers-gone-wild.lhs/
======
tomp
Shameless plug: I just implemented a simple refined type-checking algorithm.
It can statically prevent division by 0 and Heartbleed (if functions are given
the correct contracts) and is much simpler than I expected. It uses Z3 to
prove that the code is correct.

[https://github.com/tomprimozic/type-
systems/tree/master/refi...](https://github.com/tomprimozic/type-
systems/tree/master/refined_types)

Edit: I submitted it as a separate story here:
[https://news.ycombinator.com/item?id=7826175](https://news.ycombinator.com/item?id=7826175)

------
jeorgun
I have to admit, the more I look into Haskell the less enamored I am of its
syntax. Sure, it's wonderful in the common case, but when it comes to things
like vectors or (apparently) unsafe pointer manipulation, it's practically
unreadable. Something like Lisp or Python— or even C++— syntax is rarely
optimal, but at least it never degenerates this totally into symbol soup.

~~~
IsTom
You won't see (#a,b#) in client code, that's hidden behind the facade of a
library, unless you are very desperate. Nor will you use pointers.

~~~
Nursie
So... this is somebody else's problem and smarter people will take care of it
for me?

I've never found that answer very satisfying...

~~~
freyrs3
Do you assemble your own machine code as well or do you trust that someone
else has taken care of the gritty details of the assembler so that you can
work at a level of abstraction higher than that?

~~~
bronson
Assembling a program into machine language is simple enough that it's easy to
trust someone else to get it right.

I imagine it depends on the difficulty of the problem being outsourced.

~~~
SoftwareMaven
Have you seen what optimizing compilers do? I'd hardly call that simple!

~~~
bronson
Thought it was clear the OP was talking about assembly?

Which, thanks to pipeline stalls and out-of-order execution is no walk in the
park these days, but it's not TOO bad.

------
nkurz
I'm not a Haskell programmer, but I'm having trouble understanding how this is
applicable to Heartbleed type bugs. While it's nice to flag invalid constant
indexes at compile time, the real problems occur with variable indexes that a
potential attacker can control.

And the solution for those seems to be the equivalent of "Don't use
'array[i]', always 'if (i < len) ? array[i] : BOOM'". Or am I misinterpreting
_we have passed the burden of proof onto users of charAt_? I guess the
difference is that the check only needs to be done once for each 'i' at the
time it is assigned/created? But then how does one guarantee that a given
AValidI is used with array for which is intended, and not for a shorter one?

~~~
ranjitjhala
We only used the constant indexes for illustration. The system checks, at
compile time, that values that are controlled by the attacker (e.g. inputs)
are properly sanitized. See this:

[http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F14014...](http://goto.ucsd.edu:8090/index.html#?demo=permalink%2F1401418498.hs)

that uses Lists instead of pointers, for a short example.

------
CJefferson
This shows me some surprising information -- Haskell is susceptible to
heartbleed-like problems like C!

Of course, you can write your own safe wrapper which checks deference, but one
could just as easily (in fact, I think more easily) write such a thing in C...

~~~
jacquesm
The problem with 'silver bullets' is that they are relatively untested. Once
you get mass deployments of Haskell in the hostile environment that is the web
these days it will become apparent whether or not the safety argument is as
strong in practice as it is in theory. That is assuming that it will see such
mass deployment which is not a foregone conclusion.

That does not mean that it isn't good there are people trying to give us safer
languages, but there is something disconcerting about the ease with which
presumably bullet-proof Haskell can be made to do unsafe things like referring
to out-of-bounds data, even if the reason is 'performance'. The whole idea was
(or at least, that's what I thought it was) that you can get there at
reasonable speed without giving up the safety net. Like this you might as well
go the whole hog and program in C after all... It's a bit like making a vault
that has the front door hinges and the lock screwed on from the outside.

Compare with like Linux on the desktop not having too many viruses and such.
The viruses aren't there because nobody is motivated enough to write them
given the small distribution footprint of the OS. The money isn't there for
the virus writers. Not because Linux is somehow magically resistant to viruses
(though it does a few things better than say Windows).

The number of people trying to bust down the barriers is roughly proportional
to the size of the deployments, and I suspect that Haskell when put to the
test will eventually turn out to have it's own (different) class of problems
that have nothing to do with the class of problems that plagues the C like
languages.

Just like interpreted languages have a unique set of problems and virtual
machines have their own. Silver bullets are rare.

~~~
bkirwi
As a fellow relatively new to Haskell, I was surprised at all the unsafe
constructs in the core. Almost everything you'd expect to find in C's standard
library is exposed somewhere, with roughly the same level of safety. (Which is
to say, almost none.)

The main difference I find between the two is that I have never needed to
reach for an unsafe construct in Haskell myself - including some networking /
parsing code that lives at roughly the same level of the stack as you'd find
the heartbleed bug. The 'unsafe' functionality I use is encapsulated in
libraries which expose a safer, higher-level interface. (Which is roughly the
situation in Ruby with C bindings or Rust / Go with `unsafe` blocks.) I do
feel there's a significant difference between a language where you need to be
more-or-less constantly vigilant and one where you can isolate the memory
management to a small, well-vetted library, but it's true that the situation
still isn't ideal. (I think Haskell's story is much better as you move up the
stack, but that's another story...)

But if you're interested in a stronger level of safety in Haskell, you may be
interested in Safe Haskell[0] -- it disables many of the unsafe features (or
requires uses of them to be explicitly 'trusted') and thus provides much
stronger safety guarantees.

[0]
[http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/safe-...](http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/safe-
haskell.html)

~~~
dbaupp
Does Go have unsafe blocks? I was under the impression that it was similar to
Haskell, with the really bad functions just in an `unsafe` module (or
something like that?).

~~~
bkirwi
Sorry, editing error... meant to refer to unsafe blocks in _Rust_ , and the
unsafe _package_ in Go.

------
toolslive
completely off topic, but very nice nonetheless: when you hover above a code
fragment, you see the type of the expression as a tooltip. Indispensable for
reading Haskell on the web

------
userbinator
Personally, I think all the talk of "language safety" is overhyped. Bugs like
heartbleed occur because of programmers not reasoning correctly about their
code. In particular, is it really that hard to know how large some block of
memory is, and not access beyond it? It's such a _ridiculously simple_
concept, but I feel like all the high-level languages with their automatically
expanding data structures have only made this problem worse, by trying to hide
this behind _many_ layers of complexity (as evidenced by this article.)

In my opinion, if you are writing code that is performing array indexing, and
are even the slightest bit uncertain about the size of the array, then you
should not keep going, but stop and think a bit more about what it's doing.
Language safety is not a replacement for true understanding.

~~~
antris
Yeah, Real Programmers don't need safety.

[http://en.wikipedia.org/wiki/Real_Programmer](http://en.wikipedia.org/wiki/Real_Programmer)

~~~
Pacabel
Spare us the hyperbole and the misrepresentation, please.

userbinator makes a very valid and legitimate point: regardless of what safety
features a programming language may or may not offer, it's still critical for
the programmer to understand exactly what's actually happening.

You can't have true safety through tools alone. Operator knowledge is just as
critical as whatever safety features the tool may offer.

~~~
khyryk
Given layers upon layers of abstraction, it's often impractical for the
programmer to understand _exactly_ what's actually happening. Indeed, that's
the entire premise for the existence of more safe languages, which (hope to)
eliminate entire classes of bugs.

