]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix tv_sec 32-bit overflows in sleep routines.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 18 Mar 2013 19:11:11 +0000 (20:11 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 18 Mar 2013 19:11:11 +0000 (20:11 +0100)
Fixes #5063.

R=golang-dev, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/7876043

src/pkg/runtime/export_futex_test.go [new file with mode: 0644]
src/pkg/runtime/futex_test.go [new file with mode: 0644]
src/pkg/runtime/os_darwin.c
src/pkg/runtime/os_freebsd.c
src/pkg/runtime/os_linux.c
src/pkg/runtime/os_netbsd.c
src/pkg/runtime/os_openbsd.c

diff --git a/src/pkg/runtime/export_futex_test.go b/src/pkg/runtime/export_futex_test.go
new file mode 100644 (file)
index 0000000..bcab60f
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux freebsd
+
+package runtime
+
+func futexsleep(addr *uint32, val uint32, ns int64)
+func futexwakeup(addr *uint32, val uint32)
+
+var Futexsleep = futexsleep
+var Futexwakeup = futexwakeup
diff --git a/src/pkg/runtime/futex_test.go b/src/pkg/runtime/futex_test.go
new file mode 100644 (file)
index 0000000..51f4d0f
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux freebsd
+
+package runtime_test
+
+import (
+       . "runtime"
+       "testing"
+       "time"
+)
+
+func TestFutexsleep(t *testing.T) {
+       ch := make(chan bool, 1)
+       var dummy uint32
+       start := time.Now()
+       go func() {
+               Entersyscall()
+               Futexsleep(&dummy, 0, (1<<31+100)*1e9)
+               Exitsyscall()
+               ch <- true
+       }()
+       select {
+       case <-ch:
+               t.Errorf("futexsleep finished early after %s!", time.Since(start))
+       case <-time.After(time.Second):
+               Futexwakeup(&dummy, 1)
+       }
+}
index ba4e6ebdfcdecf24bbbeceadb8280796a3adbc50..6216e3a3ce2236220bb623bd92cdbf248a6f2947 100644 (file)
@@ -409,9 +409,14 @@ int32
 runtime·mach_semacquire(uint32 sem, int64 ns)
 {
        int32 r;
+       int64 secs;
 
        if(ns >= 0) {
-               r = runtime·mach_semaphore_timedwait(sem, ns/1000000000LL, ns%1000000000LL);
+               secs = ns/1000000000LL;
+               // Avoid overflow
+               if(secs > 1LL<<30)
+                       secs = 1LL<<30;
+               r = runtime·mach_semaphore_timedwait(sem, secs, ns%1000000000LL);
                if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT)
                        return -1;
                if(r != 0)
index 0632eabd30a831dbb584180b2f07019a575567ae..7ee329ff5c3b477e40711622979084197d92d93f 100644 (file)
@@ -45,11 +45,16 @@ runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
 {
        int32 ret;
        Timespec ts, *tsp;
+       int64 secs;
 
        if(ns < 0)
                tsp = nil;
        else {
-               ts.tv_sec = ns / 1000000000LL;
+               secs = ns / 1000000000LL;
+               // Avoid overflow
+               if(secs > 1LL<<30)
+                       secs = 1LL<<30;
+               ts.tv_sec = secs;
                ts.tv_nsec = ns % 1000000000LL;
                tsp = &ts;
        }
index dc1e274378fbdb93f3777693a2d736031accd3e2..8aa4c3d35d1a2a7c74932154f19cdbb17d7eeb4f 100644 (file)
@@ -36,15 +36,17 @@ void
 runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
 {
        Timespec ts, *tsp;
+       int64 secs;
 
        if(ns < 0)
                tsp = nil;
        else {
-               ts.tv_sec = ns/1000000000LL;
-               ts.tv_nsec = ns%1000000000LL;
+               secs = ns/1000000000LL;
                // Avoid overflow
-               if(ts.tv_sec > 1<<30)
-                       ts.tv_sec = 1<<30;
+               if(secs > 1LL<<30)
+                       secs = 1LL<<30;
+               ts.tv_sec = secs;
+               ts.tv_nsec = ns%1000000000LL;
                tsp = &ts;
        }
 
index d4b874f4c24da180372ca46fecee25bd5632bb27..6cf57d65645eea014e6ecf9cc45673afd6cded3b 100644 (file)
@@ -65,6 +65,7 @@ int32
 runtime·semasleep(int64 ns)
 {
        Timespec ts;
+       int64 secs;
 
        // spin-mutex lock
        while(runtime·xchg(&m->waitsemalock, 1))
@@ -93,7 +94,11 @@ runtime·semasleep(int64 ns)
                                runtime·lwp_park(nil, 0, &m->waitsemacount, nil);
                        } else {
                                ns += runtime·nanotime();
-                               ts.tv_sec = ns/1000000000LL;
+                               secs = ns/1000000000LL;
+                               // Avoid overflow
+                               if(secs > 1LL<<30)
+                                       secs = 1LL<<30;
+                               ts.tv_sec = secs;
                                ts.tv_nsec = ns%1000000000LL;
                                // TODO(jsing) - potential deadlock!
                                // See above for details.
index 01a2ef119595b882729d5b7d6f9978d6c6e5f8ff..c3f562e0a2214a2915460dbbe3b8c688b8786814 100644 (file)
@@ -62,6 +62,7 @@ int32
 runtime·semasleep(int64 ns)
 {
        Timespec ts;
+       int64 secs;
 
        // spin-mutex lock
        while(runtime·xchg(&m->waitsemalock, 1))
@@ -76,7 +77,11 @@ runtime·semasleep(int64 ns)
                                runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock, nil);
                        else {
                                ns += runtime·nanotime();
-                               ts.tv_sec = ns/1000000000LL;
+                               secs = ns/1000000000LL;
+                               // Avoid overflow
+                               if(secs > 1LL<<30)
+                                       secs = 1LL<<30;
+                               ts.tv_sec = secs;
                                ts.tv_nsec = ns%1000000000LL;
                                runtime·thrsleep(&m->waitsemacount, CLOCK_REALTIME, &ts, &m->waitsemalock, nil);
                        }