{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/26288","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/26288/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/26288/comments","events_url":"https://api.github.com/repos/golang/go/issues/26288/events","html_url":"https://github.com/golang/go/issues/26288","id":339476046,"node_id":"MDU6SXNzdWUzMzk0NzYwNDY=","number":26288,"title":"cmd/cgo: Writing to C pointer causes Go heap corruption","user":{"login":"chfast","id":573380,"node_id":"MDQ6VXNlcjU3MzM4MA==","avatar_url":"https://avatars1.githubusercontent.com/u/573380?v=4","gravatar_id":"","url":"https://api.github.com/users/chfast","html_url":"https://github.com/chfast","followers_url":"https://api.github.com/users/chfast/followers","following_url":"https://api.github.com/users/chfast/following{/other_user}","gists_url":"https://api.github.com/users/chfast/gists{/gist_id}","starred_url":"https://api.github.com/users/chfast/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chfast/subscriptions","organizations_url":"https://api.github.com/users/chfast/orgs","repos_url":"https://api.github.com/users/chfast/repos","events_url":"https://api.github.com/users/chfast/events{/privacy}","received_events_url":"https://api.github.com/users/chfast/received_events","type":"User","site_admin":false},"labels":[{"id":373402289,"node_id":"MDU6TGFiZWwzNzM0MDIyODk=","url":"https://api.github.com/repos/golang/go/labels/NeedsInvestigation","name":"NeedsInvestigation","color":"ededed","default":false},{"id":357033853,"node_id":"MDU6TGFiZWwzNTcwMzM4NTM=","url":"https://api.github.com/repos/golang/go/labels/WaitingForInfo","name":"WaitingForInfo","color":"ededed","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/65","html_url":"https://github.com/golang/go/milestone/65","labels_url":"https://api.github.com/repos/golang/go/milestones/65/labels","id":3072996,"node_id":"MDk6TWlsZXN0b25lMzA3Mjk5Ng==","number":65,"title":"Go1.12","description":"","creator":{"login":"rsc","id":104030,"node_id":"MDQ6VXNlcjEwNDAzMA==","avatar_url":"https://avatars1.githubusercontent.com/u/104030?v=4","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":423,"closed_issues":23,"state":"open","created_at":"2018-01-29T21:17:52Z","updated_at":"2018-07-10T07:13:06Z","due_on":"2019-01-31T08:00:00Z","closed_at":null},"comments":2,"created_at":"2018-07-09T14:35:06Z","updated_at":"2018-07-10T10:51:36Z","closed_at":null,"author_association":"NONE","body":"### What version of Go are you using (`go version`)?\r\n\r\ngo version go1.10.1 linux/amd64\r\n\r\n### Does this issue reproduce with the latest release?\r\n\r\nI have not checked 1.10.3 nor 1.11 beta.\r\n\r\n### What operating system and processor architecture are you using (`go env`)?\r\n\r\n```sh\r\nGOARCH=\"amd64\"\r\nGOBIN=\"\"\r\nGOCACHE=\"/home/chfast/.cache/go-build\"\r\nGOEXE=\"\"\r\nGOHOSTARCH=\"amd64\"\r\nGOHOSTOS=\"linux\"\r\nGOOS=\"linux\"\r\nGOPATH=\"/home/chfast/go\"\r\nGORACE=\"\"\r\nGOROOT=\"/usr/lib/go-1.10\"\r\nGOTMPDIR=\"\"\r\nGOTOOLDIR=\"/usr/lib/go-1.10/pkg/tool/linux_amd64\"\r\nGCCGO=\"gccgo\"\r\nCC=\"gcc\"\r\nCXX=\"g++\"\r\nCGO_ENABLED=\"1\"\r\nCGO_CFLAGS=\"-g -O2\"\r\nCGO_CPPFLAGS=\"\"\r\nCGO_CXXFLAGS=\"-g -O2\"\r\nCGO_FFLAGS=\"-g -O2\"\r\nCGO_LDFLAGS=\"-g -O2\"\r\nPKG_CONFIG=\"pkg-config\"\r\nGOGCCFLAGS=\"-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build613522550=/tmp/go-build -gno-record-gcc-switches\"\r\n```\r\n\r\n### What did you do?\r\n\r\nI have an Go exported function that takes a pointer to a C struct as an argument. It is so-called output\r\nargument, so the Go function is writing data to this C struct via the provided pointer.\r\nDepending how exactly this is done the Go heap might get corrupted.\r\nI have not minimized the example fully.\r\n\r\nThe C struct is:\r\n```go\r\ntype _Ctype_struct_evmc_result struct {\r\n\tstatus_code\tint32\r\n\t_\t\t[4]byte\r\n\tgas_left\t_Ctype_int64_t\r\n\toutput_data\t*_Ctype_uint8_t\r\n\toutput_size\t_Ctype_size_t\r\n\trelease\t\t_Ctype_evmc_release_result_fn\r\n\tcreate_address\t_Ctype_struct_evmc_address\r\n\tpadding\t\t[4]_Ctype_uint8_t\r\n}\r\n```\r\n\r\nThe variant of the exported function working correctly:\r\n```go\r\n//export call\r\nfunc call(pResult *C.struct_evmc_result, pCtx unsafe.Pointer, msg *C.struct_evmc_message) {\r\n\tresult := C.struct_evmc_result{}\r\n\tresult.status_code = C.EVMC_FAILURE\r\n\t*pResult = result\r\n}\r\n```\r\nGo assembly:\r\n```go\r\n\"\".call STEXT size=158 args=0x18 locals=0x60\r\nTEXT\t\"\".call(SB), $96-24\r\nMOVQ\t(TLS), CX\r\nCMPQ\tSP, 16(CX)\r\nJLS\t148\r\nSUBQ\t$96, SP\r\nMOVQ\tBP, 88(SP)\r\nLEAQ\t88(SP), BP\r\nFUNCDATA\t$0, gclocals·e6397a44f8e1b6e77d0f200b4fba5269(SB)\r\nFUNCDATA\t$1, gclocals·6c80e7c7d827a5ab4457c7bd9e35d7d4(SB)\r\nXORPS\tX0, X0\r\nMOVUPS\tX0, \"\".result+24(SP)\r\nMOVUPS\tX0, \"\".result+40(SP)\r\nMOVUPS\tX0, \"\".result+56(SP)\r\nMOVUPS\tX0, \"\".result+72(SP)\r\nMOVL\t$1, \"\".result+24(SP)\r\nMOVQ\t\"\".pResult+104(SP), DI\r\nTESTB\tAL, (DI)\r\nMOVL\truntime.writeBarrier(SB), AX\r\nTESTL\tAX, AX\r\nJNE\t115\r\nLEAQ\t\"\".result+24(SP), SI\r\nDUFFCOPY\t$840\r\nMOVQ\t88(SP), BP\r\nADDQ\t$96, SP\r\nRET\r\nLEAQ\ttype.\"\".C.struct_evmc_result(SB), AX\r\nMOVQ\tAX, (SP)\r\nMOVQ\tDI, 8(SP)\r\nLEAQ\t\"\".result+24(SP), AX\r\nMOVQ\tAX, 16(SP)\r\nPCDATA\t$0, $1\r\nCALL\truntime.typedmemmove(SB)\r\nJMP\t105\r\nNOP\r\nPCDATA\t$0, $-1\r\nCALL\truntime.morestack_noctxt(SB)\r\nJMP\t0\r\n```\r\n\r\nThe variant of the exported function causing the following Go heap corruption:\r\n```sh\r\nruntime: pointer 0xc420cc3000 to unallocated span idx=0x661 span.base()=0xc420cbe000 span.limit=0xc420cc6000 span.state=3\r\nfatal error: found bad pointer in Go heap (incorrect use of unsafe or cgo?)\r\n\r\nruntime stack:\r\nruntime.throw(0x89ff13, 0x3e)\r\n\t/usr/lib/go-1.10/src/runtime/panic.go:616 +0x81 fp=0x7fbf767fb748 sp=0x7fbf767fb728 pc=0x42dca1\r\nruntime.heapBitsForObject(0xc420cc3000, 0x0, 0x0, 0xc4202a8d40, 0xc41ffeab95, 0x7fbf00000000, 0x7fbf90765ce8, 0x35)\r\n\t/usr/lib/go-1.10/src/runtime/mbitmap.go:425 +0x473 fp=0x7fbf767fb7a0 sp=0x7fbf767fb748 pc=0x415223\r\nruntime.wbBufFlush1(0xc420038500)\r\n\t/usr/lib/go-1.10/src/runtime/mwbbuf.go:234 +0xde fp=0x7fbf767fb820 sp=0x7fbf767fb7a0 pc=0x429bce\r\nruntime.wbBufFlush.func1()\r\n\t/usr/lib/go-1.10/src/runtime/mwbbuf.go:180 +0x3a fp=0x7fbf767fb838 sp=0x7fbf767fb820 pc=0x45811a\r\nruntime.systemstack(0x7fbf767fbe80)\r\n\t/usr/lib/go-1.10/src/runtime/asm_amd64.s:409 +0x79 fp=0x7fbf767fb840 sp=0x7fbf767fb838 pc=0x459b89\r\nruntime.mstart()\r\n\t/usr/lib/go-1.10/src/runtime/proc.go:1175 fp=0x7fbf767fb848 sp=0x7fbf767fb840 pc=0x4322e0\r\n\r\ngoroutine 3888 [running, locked to thread]:\r\nruntime.systemstack_switch()\r\n\t/usr/lib/go-1.10/src/runtime/asm_amd64.s:363 fp=0xc420afae50 sp=0xc420afae48 pc=0x459b00\r\nruntime.wbBufFlush(0xc420a6ec28, 0xc4202a8d40)\r\n\t/usr/lib/go-1.10/src/runtime/mwbbuf.go:179 +0x4e fp=0xc420afae70 sp=0xc420afae50 pc=0x429a5e\r\nruntime.gcWriteBarrier(0xc420afaf18, 0x20, 0xc420afaf38, 0x459eee, 0x8a6750, 0xc420b1a510, 0x7fbf767fbb90, 0x7fbf767fbc30, 0xc420afafb8, 0x404687, ...)\r\n\t/usr/lib/go-1.10/src/runtime/asm_amd64.s:2442 +0xb4 fp=0xc420afaef8 sp=0xc420afae70 pc=0x45c734\r\nruntime.deferreturn(0xc420afaf8f)\r\n\t/usr/lib/go-1.10/src/runtime/panic.go:343 +0xb3 fp=0xc420afaf48 sp=0xc420afaef8 pc=0x42cee3\r\nruntime.cgocallbackg1(0x0)\r\n\t/usr/lib/go-1.10/src/runtime/cgocall.go:332 +0x1a7 fp=0xc420afafc8 sp=0xc420afaf48 pc=0x404687\r\nruntime.cgocallbackg(0x0)\r\n\t/usr/lib/go-1.10/src/runtime/cgocall.go:194 +0xda fp=0xc420afb030 sp=0xc420afafc8 pc=0x40444a\r\nruntime.cgocallback_gofunc(0x4042f8, 0x7902a0, 0xc420afb0e0, 0x7a3843)\r\n\t/usr/lib/go-1.10/src/runtime/asm_amd64.s:826 +0x9b fp=0xc420afb050 sp=0xc420afb030 pc=0x45b49b\r\nruntime.asmcgocall(0x7902a0, 0xc420afb0e0)\r\n\t/usr/lib/go-1.10/src/runtime/asm_amd64.s:673 +0x42 fp=0xc420afb058 sp=0xc420afb050 pc=0x45b332\r\nruntime.cgocall(0x7902a0, 0xc420afb0e0, 0xc420af0001)\r\n\t/usr/lib/go-1.10/src/runtime/cgocall.go:131 +0x88 fp=0xc420afb090 sp=0xc420afb058 pc=0x4042f8\r\ngithub.com/ethereum/go-ethereum/core/vm._Cfunc_execute(0x7fbf8c2c93a0, 0x896, 0xc400000001, 0xc420b1a510, 0x7fbf6c003560, 0x84, 0x0, 0x0, 0x0, 0x0, ...)\r\n```\r\n```go\r\n//export call\r\nfunc call(pResult *C.struct_evmc_result, pCtx unsafe.Pointer, msg *C.struct_evmc_message) {\r\n\tpResult.status_code = C.EVMC_FAILURE\r\n\tpResult.output_size = 0\r\n\tpResult.release = nil\r\n}\r\n```\r\nGo assembly:\r\n```go\r\n\"\".call STEXT size=93 args=0x18 locals=0x8\r\nTEXT\t\"\".call(SB), $8-24\r\nMOVQ\t(TLS), CX\r\nCMPQ\tSP, 16(CX)\r\nJLS\t86\r\nSUBQ\t$8, SP\r\nMOVQ\tBP, (SP)\r\nLEAQ\t(SP), BP\r\nFUNCDATA\t$0, gclocals·d4dc2f11db048877dbc0f60a22b4adb3(SB)\r\nFUNCDATA\t$1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)\r\nMOVQ\t\"\".pResult+16(SP), CX\r\nMOVL\t$1, (CX)\r\nMOVQ\t$0, 24(CX)\r\nMOVL\truntime.writeBarrier(SB), DX\r\nLEAQ\t32(CX), DI\r\nTESTL\tDX, DX\r\nJNE\t77\r\nMOVQ\t$0, 32(CX)\r\nMOVQ\t(SP), BP\r\nADDQ\t$8, SP\r\nRET\r\nXORL\tAX, AX\r\nCALL\truntime.gcWriteBarrier(SB)\r\nJMP\t68\r\nNOP\r\nPCDATA\t$0, $-1\r\nCALL\truntime.morestack_noctxt(SB)\r\nJMP\t0\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/403781997","html_url":"https://github.com/golang/go/issues/26288#issuecomment-403781997","issue_url":"https://api.github.com/repos/golang/go/issues/26288","id":403781997,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMzc4MTk5Nw==","user":{"login":"chfast","id":573380,"node_id":"MDQ6VXNlcjU3MzM4MA==","avatar_url":"https://avatars1.githubusercontent.com/u/573380?v=4","gravatar_id":"","url":"https://api.github.com/users/chfast","html_url":"https://github.com/chfast","followers_url":"https://api.github.com/users/chfast/followers","following_url":"https://api.github.com/users/chfast/following{/other_user}","gists_url":"https://api.github.com/users/chfast/gists{/gist_id}","starred_url":"https://api.github.com/users/chfast/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chfast/subscriptions","organizations_url":"https://api.github.com/users/chfast/orgs","repos_url":"https://api.github.com/users/chfast/repos","events_url":"https://api.github.com/users/chfast/events{/privacy}","received_events_url":"https://api.github.com/users/chfast/received_events","type":"User","site_admin":false},"created_at":"2018-07-10T10:51:36Z","updated_at":"2018-07-10T10:51:36Z","author_association":"NONE","body":"> So where does the result of evmcAddress come from? It looks like a pointer into the Go heap. Does your program use package unsafe to compute that address? Is it computed in C from a Go pointer?\r\n\r\nSorry for the distraction with `evmcAddress()` function. It was copying the `[20]byte` byte-by-byte to a C struct. But it is not needed to reproduce the problem. I updated the description with a smaller example.\r\n\r\n> Go code is never permitted to store a Go pointer into memory allocated by C.\r\n\r\nI know that and really try not to. I even started copying byte arrays before passing to C. The `GODEBUG=cgocheck=2` does not report anything.\r\n\r\nI discovered one thing. If I modify the function by adding `pResult.create_address = C.struct_evmc_address{}`\r\n```\r\n//export call\r\nfunc call(pResult *C.struct_evmc_result, pCtx unsafe.Pointer, msg *C.struct_evmc_message) {\r\n\tpResult.create_address = C.struct_evmc_address{}\r\n\tpResult.status_code = C.EVMC_FAILURE\r\n\tpResult.output_size = 0\r\n\tpResult.release = nil\r\n}\r\n```\r\nI sometimes get different panic error:\r\n```sh\r\nruntime: nelems=128 nalloc=107 previous allocCount=106 nfreed=65535\r\nfatal error: sweep increased allocation count\r\n\r\nruntime stack:\r\nruntime.throw(0x8953ab, 0x20)\r\n\t/usr/lib/go-1.10/src/runtime/panic.go:616 +0x81\r\nruntime.(*mspan).sweep(0x7f2b5c33a708, 0x7f2b5c33a701, 0x7ffe3ae0b600)\r\n\t/usr/lib/go-1.10/src/runtime/mgcsweep.go:298 +0x89c\r\nruntime.(*mcentral).cacheSpan(0xd2c870, 0x7f2b4274cf68)\r\n\t/usr/lib/go-1.10/src/runtime/mcentral.go:58 +0x277\r\nruntime.(*mcache).refill(0x7f2b5c376000, 0xd1b80a)\r\n\t/usr/lib/go-1.10/src/runtime/mcache.go:123 +0x9c\r\nruntime.(*mcache).nextFree.func1()\r\n\t/usr/lib/go-1.10/src/runtime/malloc.go:556 +0x32\r\nruntime.systemstack(0x0)\r\n\t/usr/lib/go-1.10/src/runtime/asm_amd64.s:409 +0x79\r\nruntime.mstart()\r\n\t/usr/lib/go-1.10/src/runtime/proc.go:1175\r\n```\r\n"}}
{"actor":{"display_login":"chfast"}}