Skip to content

Commit 397ba2c

Browse files
committed
cmd/cgo: replace C.malloc with our own wrapper
This allows us to make two changes: 1. Force the argument type to be size_t, even on broken systems that declare malloc to take a ulong. 2. Call runtime.throw if malloc fails. (That is, the program crashes; it does not panic.) Fixes #3403. Fixes #5926. R=golang-dev, iant CC=golang-dev https://golang.org/cl/13413047
1 parent 89b2676 commit 397ba2c

File tree

4 files changed

+48
-3
lines changed

4 files changed

+48
-3
lines changed

src/cmd/cgo/ast.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ func (f *File) saveRef(x interface{}, context string) {
187187
error_(sel.Pos(), "cannot refer to errno directly; see documentation")
188188
return
189189
}
190+
if goname == "_CMalloc" {
191+
error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
192+
return
193+
}
194+
if goname == "malloc" {
195+
goname = "_CMalloc"
196+
}
190197
name := f.Name[goname]
191198
if name == nil {
192199
name = &Name{

src/cmd/cgo/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ func (p *Package) Record(f *File) {
341341
if p.Name[k] == nil {
342342
p.Name[k] = v
343343
} else if !reflect.DeepEqual(p.Name[k], v) {
344-
error_(token.NoPos, "inconsistent definitions for C.%s", k)
344+
error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k))
345345
}
346346
}
347347
}

src/cmd/cgo/out.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
331331
}
332332

333333
// Builtins defined in the C prolog.
334-
inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes"
334+
inProlog := name == "CString" || name == "GoString" || name == "GoStringN" || name == "GoBytes" || name == "_CMalloc"
335335

336336
if *gccgo {
337337
// Gccgo style hooks.
@@ -476,9 +476,27 @@ func (p *Package) writeOutput(f *File, srcfile string) {
476476
fgcc.Close()
477477
}
478478

479+
// fixGo convers the internal Name.Go field into the name we should show
480+
// to users in error messages. There's only one for now: on input we rewrite
481+
// C.malloc into C._CMalloc, so change it back here.
482+
func fixGo(name string) string {
483+
if name == "_CMalloc" {
484+
return "malloc"
485+
}
486+
return name
487+
}
488+
489+
var isBuiltin = map[string]bool{
490+
"_Cfunc_CString": true,
491+
"_Cfunc_GoString": true,
492+
"_Cfunc_GoStringN": true,
493+
"_Cfunc_GoBytes": true,
494+
"_Cfunc__CMalloc": true,
495+
}
496+
479497
func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
480498
name := n.Mangle
481-
if name == "_Cfunc_CString" || name == "_Cfunc_GoString" || name == "_Cfunc_GoStringN" || name == "_Cfunc_GoBytes" || p.Written[name] {
499+
if isBuiltin[name] || p.Written[name] {
482500
// The builtins are already defined in the C prolog, and we don't
483501
// want to duplicate function definitions we've already done.
484502
return
@@ -1101,6 +1119,8 @@ __cgo_size_assert(double, 8)
11011119
`
11021120

11031121
const builtinProlog = `
1122+
#include <sys/types.h> /* for size_t below */
1123+
11041124
/* Define intgo when compiling with GCC. */
11051125
#ifdef __PTRDIFF_TYPE__
11061126
typedef __PTRDIFF_TYPE__ intgo;
@@ -1116,6 +1136,7 @@ _GoString_ GoString(char *p);
11161136
_GoString_ GoStringN(char *p, int l);
11171137
_GoBytes_ GoBytes(void *p, int n);
11181138
char *CString(_GoString_);
1139+
void *_CMalloc(size_t);
11191140
`
11201141

11211142
const cProlog = `
@@ -1153,6 +1174,13 @@ void
11531174
p[s.len] = 0;
11541175
FLUSH(&p);
11551176
}
1177+
1178+
void
1179+
·_Cfunc__CMalloc(uintptr n, int8 *p)
1180+
{
1181+
p = runtime·cmalloc(n);
1182+
FLUSH(&p);
1183+
}
11561184
`
11571185

11581186
const cPrologGccgo = `
@@ -1193,6 +1221,14 @@ Slice GoBytes(char *p, int32_t n) {
11931221
struct __go_string s = { (const unsigned char *)p, n };
11941222
return __go_string_to_byte_array(s);
11951223
}
1224+
1225+
extern void runtime_throw(const char *):
1226+
void *Cmalloc(size_t n) {
1227+
void *p = malloc(n);
1228+
if(p == NULL)
1229+
runtime_throw("runtime: C malloc failed");
1230+
return p;
1231+
}
11961232
`
11971233

11981234
func (p *Package) gccExportHeaderProlog() string {

src/pkg/runtime/cgocall.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ runtime·cmalloc(uintptr n)
198198
a.n = n;
199199
a.ret = nil;
200200
runtime·cgocall(_cgo_malloc, &a);
201+
if(a.ret == nil)
202+
runtime·throw("runtime: C malloc failed");
201203
return a.ret;
202204
}
203205

0 commit comments

Comments
 (0)