Overflow when reading C types

Prelude> import Foreign.C.Types Prelude Foreign.C.Types> read "-10" :: CUInt 4294967286 Prelude Foreign.C.Types> read "300" :: CChar 44 This seems like a bug. Shouldn't these result in some kind of read error? The values expressed as strings are simply not part of the type they are being parsed into. However, Haskell seems to parse them into an arbitrarily wide numeric type, and then overflow them down to the correct size. What's the rationale here?

On Mon, Dec 02, 2013 at 11:38:33AM +1300, ml@extensibl.com wrote:
On Mon, Dec 02, 2013 at 11:30:50AM +1300, Patrick Redmond wrote:
Prelude> import Foreign.C.Types Prelude Foreign.C.Types> read "-10" :: CUInt 4294967286 Prelude Foreign.C.Types> read "300" :: CChar 44
CUInt? I would try CInt instead.
Whoops, that is not related to the original question, sorry.

Yeah, the unsigned is to demonstrate how "-10" is being interpreted as a number before being cast to an unsigned. My question is: Why isn't this just a read/parse error? "-10" isn't a valid representation for any value of the CUInt type. On Monday, December 2, 2013, wrote:
On Mon, Dec 02, 2013 at 11:38:33AM +1300, ml@extensibl.com javascript:;wrote:
On Mon, Dec 02, 2013 at 11:30:50AM +1300, Patrick Redmond wrote:
Prelude> import Foreign.C.Types Prelude Foreign.C.Types> read "-10" :: CUInt 4294967286 Prelude Foreign.C.Types> read "300" :: CChar 44
CUInt? I would try CInt instead.
Whoops, that is not related to the original question, sorry.
_______________________________________________ Beginners mailing list Beginners@haskell.org javascript:; http://www.haskell.org/mailman/listinfo/beginners

On 12/02/2013 05:05 PM, Patrick Redmond wrote:
Yeah, the unsigned is to demonstrate how "-10" is being interpreted as a number before being cast to an unsigned.
My question is: Why isn't this just a read/parse error? "-10" isn't a valid representation for any value of the CUInt type.
Sure it is, unsigned int x = -10; If you don't want a CUInt, don't use a CUInt =)

On 12/02/2013 05:09 PM, Michael Orlitzky wrote:
On 12/02/2013 05:05 PM, Patrick Redmond wrote:
Yeah, the unsigned is to demonstrate how "-10" is being interpreted as a number before being cast to an unsigned.
My question is: Why isn't this just a read/parse error? "-10" isn't a valid representation for any value of the CUInt type.
Sure it is,
unsigned int x = -10;
If you don't want a CUInt, don't use a CUInt =)
That is a C integral->integral conversion. A better comparison for Haskell "read", if you think C gets to define the Haskell conversion from Haskell string to C integral type, would be strtol()/strtoul(), which are standard C functions that convert from C string to C integral type. strtol() saturates at LONG_MIN and LONG_MAX. strtoul() saturates at ULONG_MAX and is modulo at 0 (the first time; if the number is too negative then it saturates to ULONG_MAX). Both set errno to ERANGE when they saturate. C conversions from floating-point to signed or unsigned integral also saturate. Unsigned types being Z/nZ is mathematically sound, but C is not very dedicated to this interpretation. Furthermore, C signed arithmetic is undefined behavior if you overflow. Haskell is much more dedicated to thinking both signed and unsigned C types are modulo than C is. I too am curious whether it would make more sense for Haskell read/readsPrec to fail to read out-of-range integers. -Isaac

On Monday 02 December 2013, 18:14:20, Isaac Dupree wrote:
C conversions from floating-point to signed or unsigned integral also saturate.
Not really. Clause 6.3.1.4 is quite explicit: "When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined." and adds a footnote to make it unmistakeably clear that the remaindering operation need not be carried out when the target type is unsigned.
Unsigned types being Z/nZ is mathematically sound, but C is not very dedicated to this interpretation.
It's mandated in 6.2.5 (9), "A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."
Furthermore, C signed arithmetic is undefined behavior if you overflow.
That cannot be stressed too much.

On 12/02/2013 07:14 PM, Daniel Fischer wrote:
On Monday 02 December 2013, 18:14:20, Isaac Dupree wrote:
C conversions from floating-point to signed or unsigned integral also saturate.
Not really. Clause 6.3.1.4 is quite explicit:
"When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined."
and adds a footnote to make it unmistakeably clear that the remaindering operation need not be carried out when the target type is unsigned.
Whoops! Thank you for correcting me.
Unsigned types being Z/nZ is mathematically sound, but C is not very dedicated to this interpretation.
It's mandated in 6.2.5 (9),
"A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."
Yes, indeed, C unsigned arithmetic *is* Z/nZ and that is lovely (when you want it, at least). My point there was that some functions/operations specified by the C standard that are related to unsigned types, like conversion from strings (strtoul()) and floats (casting), aren't modulo 2^n. I see that's a weak point since each of those only differ from modulo in error conditions (errno set, or undefined behaviour). If C was as good as(?) Haskell it might use modulo for those conversions too. -Isaac
participants (5)
-
Daniel Fischer
-
Isaac Dupree
-
Michael Orlitzky
-
ml@extensibl.com
-
Patrick Redmond