Home > OS >  Golang untyped int overflow on 32-bit arm
Golang untyped int overflow on 32-bit arm

Time:08-27

I am trying to create a switch on a 32-bit signed integer returned from a C function. This is all being compiled for a 32-bit arm system via: GOARCH=arm GOOS=linux CC="..." go build

My code is:

func ResultToString(value C.int) error {
    switch int(value) {
    case 1:
        return nil
    case -1:
        return fmt.Errorf("Unknown")
    case 0xF3210123:
        return fmt.Errorf("Line high")
    }
    return fmt.Errorf("bad value")
}

The error I am receiving is: pkg/app/conversions.go:200:7: 0xF3210123 (untyped int constant 4079026467) overflows int

0xF3210123 in decimal is 4_079_026_467 and fits completely in 32-bits as 1111 0011 0010 0001 0000 0001 0010 0011. However, this is the unsigned representation, when I want the signed one (which is -215_940_829).

I have tried to convert it in the switch but all my methods are not working (here tried on constant 0xF3210124:

  • case int(0xF3210124): gives error cannot convert 0xF3210124 (untyped int constant 4079026468) to type int

I've also tried creating it as a regular var and casting that way as described in this blog post: https://go.dev/blog/constants but that isn't working either:

# Source
var testVal = 0xF3210123
...
case int(testVal):
# Error
cannot use 0xF3210123 (untyped int constant 4079026467) as int value in variable declaration (overflows)

I want to use the literals directly to match the specification I am trying to implement. Is there a way to do this easily that I'm just missing?

--

What DOES work is using the converted constant (shown below). However, I have a lot of these codes and again want to use the hex literal for easy spec matching.

# Working example
func ResultToString(value C.int) error {
    switch int(value) {
    case 1:
        return nil
    case -1:
        return fmt.Errorf("Unknown")
    case -215_940_829:
        return fmt.Errorf("Line high")
    }
    return fmt.Errorf("bad value")
}

CodePudding user response:

This might be explained with a particular interpretation of the language spec about untyped constants. It looks like 0xF3210123 is interpreted as an uint32 value, which then causes overflow when converted to a int32 value at compile time.

But it does not do that when converted at runtime.

So ugly, but a workaround could be (i did not test this on a 32-bit system):

var v = 0xF3210124
var x = int32(v)

...

switch ... {
   case x: ...
}

CodePudding user response:

I also tried a few things... this one worked:

const (
        ZERO int32 = 0
        BIG1 = 0xF3210123
        BIG2 = 0xFF00FF00
)

and later:

    case BIG1:
        fmt.Printf("big\n");

It sounds like you'll have to come up with lots of names, but some folks would say that's better than having lots of unknown constants everywhere.

  • Related