]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: don't crash in SetFinalizer if sizeof *x is zero
authorBrad Fitzpatrick <bradfitz@golang.org>
Tue, 17 Dec 2013 22:18:58 +0000 (14:18 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 17 Dec 2013 22:18:58 +0000 (14:18 -0800)
And document it explicitly, even though it already said
it wasn't guaranteed.

Fixes #6857

R=golang-dev, khr
CC=golang-dev
https://golang.org/cl/43580043

src/pkg/runtime/extern.go
src/pkg/runtime/malloc.goc
src/pkg/runtime/mfinal_test.go

index c96dc10384e490db71e47c55a1431c888ba9ef21..30fc34c0ba9c872d73f02e76ea3e010368a4bb4f 100644 (file)
@@ -160,6 +160,9 @@ func funcentry_go(*Func) uintptr
 // to depend on a finalizer to flush an in-memory I/O buffer such as a
 // bufio.Writer, because the buffer would not be flushed at program exit.
 //
+// It is not guaranteed that a finalizer will run if the size of *x is
+// zero bytes.
+//
 // A single goroutine runs all finalizers for a program, sequentially.
 // If a finalizer must run for a long time, it should do so by starting
 // a new goroutine.
index cd124f0f7177fa9163bbf66741c3e50c9132eaaf..b81fc398f03f4ccf81e4cfec83193f0def6e5af5 100644 (file)
@@ -760,12 +760,15 @@ func SetFinalizer(obj Eface, finalizer Eface) {
                runtime·printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.type->string);
                goto throw;
        }
+       ot = (PtrType*)obj.type;
+       if(ot->elem != nil && ot->elem->size == 0) {
+               return;
+       }
        if(!runtime·mlookup(obj.data, &base, &size, nil) || obj.data != base) {
                runtime·printf("runtime.SetFinalizer: pointer not at beginning of allocated block\n");
                goto throw;
        }
        nret = 0;
-       ot = (PtrType*)obj.type;
        fint = nil;
        if(finalizer.type != nil) {
                if(finalizer.type->kind != KindFunc)
index 6efef9bb0340e64aca04e6083d07c670cb95d2db..4a34cd61bd24a810b5a03ca3b50d2ca395df5cf6 100644 (file)
@@ -100,6 +100,13 @@ func TestFinalizerInterfaceBig(t *testing.T) {
 func fin(v *int) {
 }
 
+// Verify we don't crash at least. golang.org/issue/6857
+func TestFinalizerZeroSizedStruct(t *testing.T) {
+       type Z struct{}
+       z := new(Z)
+       runtime.SetFinalizer(z, func(*Z) {})
+}
+
 func BenchmarkFinalizer(b *testing.B) {
        const CallsPerSched = 1000
        procs := runtime.GOMAXPROCS(-1)