
Consider the following GHCi session: GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. Prelude> :m Data.Array.IO Prelude Data.Array.IO> t <- newArray ((0,0),(5,4)) 0 :: IO (IOUArray (Int,Int) Int) Loading package array-0.1.0.0 ... linking ... done. Prelude Data.Array.IO> getBounds t ((0,0),(5,4)) Prelude Data.Array.IO> writeArray t (10,10) 5 *** Exception: Error in array index Prelude Data.Array.IO> writeArray t (7,3) 5 *** Exception: Error in array index Prelude Data.Array.IO> writeArray t (3,7) 5 Prelude Data.Array.IO> So the array has 0 <= x <= 5 and 0 <= y <= 4, and writing to (10,10) or (7,3) throws an exception. However, writing to (3,7) triggers no exception - despite being clearly out of range. Judging by the behaviour of the large, complex program I was debugging when I stumbled upon this, the coordinates "wrap round" to the next column. (!!) Obviously, writing to non-existent coordinates and not getting an exception is a Very Bad Thing. I was counting on writeArray (and readArray) to detect out-of-range coordinates so I could fix my code. But as you can see, it doesn't actually work as advertised. You have *no idea* how long I spent trying to track this bug down! >_< Is this a known bug? Is it likely to be fixed any time soon? (I'm guessing the bug is as simple is converting indicies to integers and then checking the integers are in-range, rather than the underlying index type.)

Andrew Coppin wrote:
Consider the following GHCi session:
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Prelude Data.Array.IO> t <- newArray ((0,0),(5,4)) 0 :: IO (IOUArray (Int,Int) Int) Prelude Data.Array.IO> getBounds t ((0,0),(5,4)) Prelude Data.Array.IO>
Is this a known bug? Is it likely to be fixed any time soon? (I'm guessing the bug is as simple is converting indicies to integers and then checking the integers are in-range, rather than the underlying index type.)
Yes, it's a known bug - a conscious choice really. See http://hackage.haskell.org/trac/ghc/ticket/2120 It's somewhat ironic that this behaviour was introduced by a patch that made arrays safer to use in other respects. Bertram

Bertram Felgenhauer wrote:
Yes, it's a known bug - a conscious choice really. See
http://hackage.haskell.org/trac/ghc/ticket/2120
It's somewhat ironic that this behaviour was introduced by a patch that made arrays safer to use in other respects.
...so it's *not* going to be fixed then? That's just fantastic. Nice to know that Haskell takes safety seriously...

Andrew Coppin wrote:
Bertram Felgenhauer wrote:
Yes, it's a known bug - a conscious choice really. See
http://hackage.haskell.org/trac/ghc/ticket/2120
It's somewhat ironic that this behaviour was introduced by a patch that made arrays safer to use in other respects.
...so it's *not* going to be fixed then?
It's not going to be fixed by itself - the first comment for the bug report basically asks interested parties to submit a proposal for changing this. Bertram

Bertram Felgenhauer wrote:
Andrew Coppin wrote:
Bertram Felgenhauer wrote:
Yes, it's a known bug - a conscious choice really. See
http://hackage.haskell.org/trac/ghc/ticket/2120
It's somewhat ironic that this behaviour was introduced by a patch that made arrays safer to use in other respects.
...so it's *not* going to be fixed then?
It's not going to be fixed by itself - the first comment for the bug report basically asks interested parties to submit a proposal for changing this.
Well I certainly don't have the skill to fix it. (Presumably all that array stuff is hard-wired into the compiler.) In my opinion, what we should have is 1. An interface that is guaranteed-safe, no matter how inefficient that is. 2. An interface that is guaranteed-efficient, no matter how unsafe that is. 3. It should be extremely easy to switch from one to the other. You write your code against the safe interface, test it until you're happy with it, and then switch to the fast interface. Currently, the "safe" interface actually allows out-of-bounds indicies (in a way which reveals the underlying implementation), and the "fast" interface isn't publicly supported. Both of these things should be changed.

On Sun, Nov 2, 2008 at 7:53 PM, Andrew Coppin
Bertram Felgenhauer wrote:
It's not going to be fixed by itself - the first comment for the bug report basically asks interested parties to submit a proposal for changing this.
Well I certainly don't have the skill to fix it. (Presumably all that array stuff is hard-wired into the compiler.)
Actually, it isn't. The code - the bounds-checking code, at least - is fairly plain haskell in the Array package. You could take a look and, quite possibly, fix it.
In my opinion, what we should have is
1. An interface that is guaranteed-safe, no matter how inefficient that is.
2. An interface that is guaranteed-efficient, no matter how unsafe that is.
3. It should be extremely easy to switch from one to the other.
You write your code against the safe interface, test it until you're happy with it, and then switch to the fast interface.
Sounds good to me.
Currently, the "safe" interface actually allows out-of-bounds indicies (in a way which reveals the underlying implementation), and the "fast" interface isn't publicly supported. Both of these things should be changed.
Go ahead. :)

On Mon, 3 Nov 2008, Svein Ove Aas wrote:
On Sun, Nov 2, 2008 at 7:53 PM, Andrew Coppin
In my opinion, what we should have is
1. An interface that is guaranteed-safe, no matter how inefficient that is.
2. An interface that is guaranteed-efficient, no matter how unsafe that is.
3. It should be extremely easy to switch from one to the other.
You write your code against the safe interface, test it until you're happy with it, and then switch to the fast interface.
Sounds good to me.
I think it is a good idea to switch this feature on and off by a compiler switch. It does not alter the correctness of a program. If the program is incorrect, the switch does only affect the way how the program goes wrong.

Henning Thielemann
I think it is a good idea to switch this feature on and off by a compiler switch.
I agree. Same with Int overflow checking, if it can be done at all. The interesting question is how to name it, the obvious -funsafe-optimization might imply that these optimizations are fun and safe, which is probably misleading :-) -k -- If I haven't seen further, it is by standing in the footprints of giants

ketil:
Henning Thielemann
writes: I think it is a good idea to switch this feature on and off by a compiler switch.
I agree. Same with Int overflow checking, if it can be done at all.
The interesting question is how to name it, the obvious
-funsafe-optimization
might imply that these optimizations are fun and safe, which is probably misleading :-)
The uvector package as -funsafe, which disables bounds checking on primitive reads/writes. It's a compile time flag to cabal that sets a #define, that then let's GHC optimise away a guard. So there's precedent. -- Don

Ketil Malde
Henning Thielemann
writes: I think it is a good idea to switch this feature on and off by a compiler switch.
I agree. Same with Int overflow checking, if it can be done at all.
The interesting question is how to name it, the obvious
-funsafe-optimization
might imply that these optimizations are fun and safe, which is probably misleading :-)
-fno-paranoia -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited.

On Mon, Nov 3, 2008 at 4:55 PM, Henning Thielemann
I think it is a good idea to switch this feature on and off by a compiler switch. It does not alter the correctness of a program. If the program is incorrect, the switch does only affect the way how the program goes wrong.
I disagree. In a normal program, you may want to mix the two - use the safe functions for untrusted input, the unsafe ones once you have already validated the input. Such a switch, if it existed, should only affect the *unsafe* version of the call - this way, it would be possible to remove all chance of corruption from a program at need. Also, of course, the exceptions should be catchable based on the new ghc 6.10 exception library (on ghc 6.10, anyhow)

On Mon, 3 Nov 2008, Svein Ove Aas wrote:
On Mon, Nov 3, 2008 at 4:55 PM, Henning Thielemann
I think it is a good idea to switch this feature on and off by a compiler switch. It does not alter the correctness of a program. If the program is incorrect, the switch does only affect the way how the program goes wrong.
I disagree. In a normal program, you may want to mix the two - use the safe functions for untrusted input, the unsafe ones once you have already validated the input.
Such a switch, if it existed, should only affect the *unsafe* version of the call - this way, it would be possible to remove all chance of corruption from a program at need.
Also, of course, the exceptions should be catchable based on the new ghc 6.10 exception library (on ghc 6.10, anyhow)
I think you mix up errors and exceptions: http://www.haskell.org/haskellwiki/Exception http://www.haskell.org/haskellwiki/Error If you read untrusted data and encounter an index out of range, then you must throw an exception (or return an "exception code"). The internal array bound checking must be active though, since your code that checks the untrusted data may be buggy. The internal array bound checking is entirely intended for revealing buggy code, not for validating untrusted data. That is, for debugging you turn the bound checking on and if you are sure it is exhaustively tested, then you can turn it off for maximum efficiency. You may want to give http://hackage.haskell.org/cgi-bin/hackage-scripts/package/explicit-exceptio... a try.

Hello Bertram, Saturday, November 1, 2008, 5:14:30 PM, you wrote:
Yes, it's a known bug - a conscious choice really. See
does it possible to do both checks? -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (9)
-
Achim Schneider
-
Andrew Coppin
-
Bertram Felgenhauer
-
Bulat Ziganshin
-
Don Stewart
-
Henning Thielemann
-
Jonathan Cast
-
Ketil Malde
-
Svein Ove Aas