fmt.Sprintf("%x") may cause a stack overflow

1,364 views
Skip to first unread message

HWJ

unread,
Feb 12, 2018, 10:51:03 AM2/12/18
to golan...@googlegroups.com
Hello,

fmt.Sprintf("%x") with a named int type may cause a stack overflow.
Is that expected?

Input:

package main

import "fmt"

type T int

func (t T) String() string {
return fmt.Sprintf("%x", t)
}

func main() {
t := T(0)
println(t.String())
}

Output:

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x10c2705, 0xe)
/usr/local/opt/go/libexec/src/runtime/panic.go:619 +0x81
runtime.newstack()
/usr/local/opt/go/libexec/src/runtime/stack.go:1054 +0x71f
runtime.morestack()
/usr/local/opt/go/libexec/src/runtime/asm_amd64.s:480 +0x89

goroutine 1 [running]:
runtime.heapBitsSetType(0xc42c46b380, 0xc0, 0xb8, 0x10b6a40)
/usr/local/opt/go/libexec/src/runtime/mbitmap.go:864 +0x61c fp=0xc4401002f8 sp=0xc4401002f0 pc=0x10110dc
runtime.mallocgc(0xc0, 0x10b6a40, 0x1, 0x4)
/usr/local/opt/go/libexec/src/runtime/malloc.go:740 +0x548 fp=0xc440100398 sp=0xc4401002f8 pc=0x100e198
runtime.newobject(0x10b6a40, 0xc4204520a8)
/usr/local/opt/go/libexec/src/runtime/malloc.go:839 +0x38 fp=0xc4401003c8 sp=0xc440100398 pc=0x100e798
fmt.glob..func1(0x1137490, 0x0)
/usr/local/opt/go/libexec/src/fmt/print.go:128 +0x2d fp=0xc4401003e8 sp=0xc4401003c8 pc=0x108fc9d
sync.(*Pool).Get(0x1137490, 0x0, 0x0)
/usr/local/opt/go/libexec/src/sync/pool.go:151 +0xab fp=0xc440100430 sp=0xc4401003e8 pc=0x105cf4b
fmt.newPrinter(0x0)
/usr/local/opt/go/libexec/src/fmt/print.go:133 +0x31 fp=0xc440100458 sp=0xc440100430 pc=0x10881c1
fmt.Sprintf(0x10c12ba, 0x2, 0xc4401004f0, 0x1, 0x1, 0xc4401004b8, 0x0)
/usr/local/opt/go/libexec/src/fmt/print.go:202 +0x26 fp=0xc4401004b0 sp=0xc440100458 pc=0x1088546

-HWJ

Jan Mercl

unread,
Feb 12, 2018, 10:53:44 AM2/12/18
to HWJ, golan...@googlegroups.com
On Mon, Feb 12, 2018 at 4:51 PM HWJ <hwj+g...@secure.mailbox.org> wrote:

> fmt.Sprintf("%x") with a named int type may cause a stack overflow.
> Is that expected?

Yes it is. Use `return fmt.Sprintf("%x", int(t))` to avoid the infinite recursion.

--

-j

HWJ

unread,
Feb 12, 2018, 11:00:59 AM2/12/18
to golan...@googlegroups.com
>> fmt.Sprintf("%x") with a named int type may cause a stack overflow.
>> Is that expected?
>
>Yes it is. Use `return fmt.Sprintf("%x", int(t))` to avoid the infinite
>recursion.

Thanks.

Is it this way because %d is only valid for ints whereas %x for strings
too?

-HWJ

Lucio De Re

unread,
Feb 12, 2018, 11:01:31 AM2/12/18
to Jan Mercl, HWJ, golan...@googlegroups.com
That bit me recently, yet I did not recognise it here (a very long
stack dump would have probably reminded me). Thanks Jan for shedding
some memorable light.

Is there no cheap trick that would prevent this problem. It wasn't
very bright of me (or of OP above - no insult intended) to fall in
that trap, but I worry that it will happen to me again and to others
unnecessarily, unless somehow the compiler or the print interpreter
can pick that up.

I'm not up to the challenge, but there are some bright minds surrounding us...

Lucio.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-dev+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>


--
Lucio De Re
2 Piet Retief St
Kestell (Eastern Free State)
9860 South Africa

Ph.: +27 58 653 1433
Cell: +27 83 251 5824
FAX: +27 58 653 1435

Jan Mercl

unread,
Feb 12, 2018, 11:13:54 AM2/12/18
to Lucio De Re, HWJ, golan...@googlegroups.com
On Mon, Feb 12, 2018 at 5:01 PM Lucio De Re <lucio...@gmail.com> wrote:

> Is there no cheap trick that would prevent this problem.

go vet detect this and Go 1.10 runs go vet automatically.

jnml@r550:/tmp> cat main.go 
package main

import "fmt"

type T int

func (t T) String() string {
return fmt.Sprintf("%x", t)
}

func main() {
t := T(0)
println(t.String())
}
jnml@r550:/tmp> go vet main.go 
main.go:8: arg t for printf causes recursive call to String method
exit status 1
jnml@r550:/tmp> 

--

-j

Lucio De Re

unread,
Feb 12, 2018, 1:27:30 PM2/12/18
to Jan Mercl, HWJ, golan...@googlegroups.com
On 2/12/18, Jan Mercl <0xj...@gmail.com> wrote:
> On Mon, Feb 12, 2018 at 5:01 PM Lucio De Re <lucio...@gmail.com> wrote:
>
>> Is there no cheap trick that would prevent this problem.
>
> go vet detect this and Go 1.10 runs go vet automatically.
>
Nice, indeed! Thank you.

Lucio.
Reply all
Reply to author
Forward
0 new messages