]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix integer overflow in amd64 memmove.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Fri, 8 Mar 2013 23:41:03 +0000 (00:41 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Fri, 8 Mar 2013 23:41:03 +0000 (00:41 +0100)
Fixes #4981.

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

src/pkg/runtime/memmove_amd64.s
src/pkg/runtime/memmove_linux_amd64_test.go [new file with mode: 0644]
src/pkg/runtime/runtime.h

index e78be814551f5d01886ee07cf9cd5ad3110cfdd3..6174407e33bca529e7439910a834ee2e570dd206 100644 (file)
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
+// void runtime·memmove(void*, void*, uintptr)
 TEXT runtime·memmove(SB), 7, $0
 
        MOVQ    to+0(FP), DI
        MOVQ    fr+8(FP), SI
-       MOVLQSX n+16(FP), BX
+       MOVQ    n+16(FP), BX
 
 /*
  * check and set for backwards
@@ -38,7 +39,7 @@ TEXT runtime·memmove(SB), 7, $0
 /*
  * forward copy loop
  */
-forward:       
+forward:
        MOVQ    BX, CX
        SHRQ    $3, CX
        ANDQ    $7, BX
diff --git a/src/pkg/runtime/memmove_linux_amd64_test.go b/src/pkg/runtime/memmove_linux_amd64_test.go
new file mode 100644 (file)
index 0000000..f7221f4
--- /dev/null
@@ -0,0 +1,61 @@
+// 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.
+
+package runtime_test
+
+import (
+       "io/ioutil"
+       "os"
+       "reflect"
+       "syscall"
+       "testing"
+       "unsafe"
+)
+
+// TestMemmoveOverflow maps 3GB of memory and calls memmove on
+// the corresponding slice.
+func TestMemmoveOverflow(t *testing.T) {
+       // Create a temporary file.
+       tmp, err := ioutil.TempFile("", "go-memmovetest")
+       if err != nil {
+               t.Fatal(err)
+       }
+       _, err = tmp.Write(make([]byte, 65536))
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer os.Remove(tmp.Name())
+       defer tmp.Close()
+
+       // Set up mappings.
+       base, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
+               0xa0<<32, 3<<30, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS, ^uintptr(0), 0)
+       if errno != 0 {
+               t.Skipf("could not create memory mapping: %s", errno)
+       }
+       syscall.Syscall(syscall.SYS_MUNMAP, base, 3<<30, 0)
+
+       for off := uintptr(0); off < 3<<30; off += 65536 {
+               _, _, errno := syscall.Syscall6(syscall.SYS_MMAP,
+                       base+off, 65536, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED|syscall.MAP_FIXED, tmp.Fd(), 0)
+               if errno != 0 {
+                       t.Fatalf("could not map a page at requested 0x%x: %s", base+off, errno)
+               }
+               defer syscall.Syscall(syscall.SYS_MUNMAP, base+off, 65536, 0)
+       }
+
+       var s []byte
+       sp := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+       sp.Data = base
+       sp.Len, sp.Cap = 3<<30, 3<<30
+
+       n := copy(s[1:], s)
+       if n != 3<<30-1 {
+               t.Fatalf("copied %d bytes, expected %d", n, 3<<30-1)
+       }
+       n = copy(s, s[1:])
+       if n != 3<<30-1 {
+               t.Fatalf("copied %d bytes, expected %d", n, 3<<30-1)
+       }
+}
index 66bcf603bd58b2f324abef6342816d70b4f0d3c6..8ae6e6a6c909d88487bb4a913b00a25e409d39a1 100644 (file)
@@ -668,7 +668,7 @@ void        runtime·prints(int8*);
 void   runtime·printf(int8*, ...);
 byte*  runtime·mchr(byte*, byte, byte*);
 int32  runtime·mcmp(byte*, byte*, uint32);
-void   runtime·memmove(void*, void*, uint32);
+void   runtime·memmove(void*, void*, uintptr);
 void*  runtime·mal(uintptr);
 String runtime·catstring(String, String);
 String runtime·gostring(byte*);