Skip to content

Commit 67a137d

Browse files
authored
Add mmap protected buffer to verify under/over flows (#34)
* add mmap protected buffer to verify under/over flows * remove unused fill functions
1 parent 1272040 commit 67a137d

File tree

3 files changed

+127
-31
lines changed

3 files changed

+127
-31
lines changed

ascii/ascii_test.go

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"strings"
77
"testing"
88
"unicode/utf8"
9+
10+
"github.com/segmentio/asm/internal/buffer"
911
)
1012

1113
var testStrings = [...]string{
@@ -65,45 +67,49 @@ func testValidPrint(s string) bool {
6567
}
6668

6769
func TestValid(t *testing.T) {
68-
var input [1024]byte
69-
70-
for i := 0; i < len(input); i++ {
71-
in := input[:i+1]
72-
73-
for b := 0; b <= 0xFF; b++ {
74-
in[i] = byte(b)
75-
if b < 0x80 {
76-
if !Valid(in) {
77-
t.Errorf("should be valid: %v", in)
78-
}
79-
} else {
80-
if Valid(in) {
81-
t.Errorf("should not be valid: %v", in)
70+
buf := newBuffer(t, 1024)
71+
72+
for _, input := range [2][]byte{buf.ProtectHead(), buf.ProtectTail()} {
73+
for i := 0; i < len(input); i++ {
74+
in := input[:i+1]
75+
76+
for b := 0; b <= 0xFF; b++ {
77+
in[i] = byte(b)
78+
if b < 0x80 {
79+
if !Valid(in) {
80+
t.Errorf("should be valid: %v", in)
81+
}
82+
} else {
83+
if Valid(in) {
84+
t.Errorf("should not be valid: %v", in)
85+
}
8286
}
87+
in[i] = 'x'
8388
}
84-
in[i] = 'x'
8589
}
8690
}
8791
}
8892

8993
func TestValidPrint(t *testing.T) {
90-
var input [1024]byte
91-
92-
for i := 0; i < len(input); i++ {
93-
in := input[:i+1]
94-
95-
for b := 0; b <= 0xFF; b++ {
96-
in[i] = byte(b)
97-
if ' ' <= b && b <= '~' {
98-
if !ValidPrint(in) {
99-
t.Errorf("should be valid: %v", in)
100-
}
101-
} else {
102-
if ValidPrint(in) {
103-
t.Errorf("should not be valid: %v", in)
94+
buf := newBuffer(t, 1024)
95+
96+
for _, input := range [2][]byte{buf.ProtectHead(), buf.ProtectTail()} {
97+
for i := 0; i < len(input); i++ {
98+
in := input[:i+1]
99+
100+
for b := 0; b <= 0xFF; b++ {
101+
in[i] = byte(b)
102+
if ' ' <= b && b <= '~' {
103+
if !ValidPrint(in) {
104+
t.Errorf("should be valid: %v", in)
105+
}
106+
} else {
107+
if ValidPrint(in) {
108+
t.Errorf("should not be valid: %v", in)
109+
}
104110
}
111+
in[i] = 'x'
105112
}
106-
in[i] = 'x'
107113
}
108114
}
109115
}
@@ -232,8 +238,27 @@ func TestEqualFoldString(t *testing.T) {
232238
}
233239
}
234240

241+
func newBuffer(t *testing.T, n int) buffer.Buffer {
242+
buf, err := buffer.New(n)
243+
if err != nil {
244+
t.Fatal(err)
245+
}
246+
return buf
247+
}
248+
235249
func TestEqualFold(t *testing.T) {
236-
var upper, lower, mixed [1024]byte
250+
ubuf := newBuffer(t, 1024)
251+
defer ubuf.Release()
252+
253+
lbuf := newBuffer(t, 1024)
254+
defer lbuf.Release()
255+
256+
mbuf := newBuffer(t, 1024)
257+
defer mbuf.Release()
258+
259+
upper := ubuf.ProtectHead()
260+
lower := lbuf.ProtectTail()
261+
mixed := mbuf.ProtectHead()
237262

238263
for i := 0; i < len(upper); i++ {
239264
u := upper[:i+1]

internal/buffer/buffer_default.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// +build !aix,!android,!darwin,!dragonfly,!freebsd,!illumos,!ios,!linux,!netbsd,!openbsd,!plan9,!solaris
2+
3+
package buffer
4+
5+
type Buffer []byte
6+
7+
func New(n int) (Buffer, error) {
8+
return make([]byte, n), nil
9+
}
10+
11+
func (a *Buffer) ProtectHead() []byte {
12+
return []byte(*a)
13+
}
14+
15+
func (a *Buffer) ProtectTail() []byte {
16+
return []byte(*a)
17+
}
18+
19+
func (a *Buffer) Release() {
20+
}

internal/buffer/buffer_mmap.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// +build aix android darwin dragonfly freebsd illumos ios linux netbsd openbsd plan9 solaris
2+
3+
package buffer
4+
5+
import (
6+
"syscall"
7+
)
8+
9+
type Buffer struct {
10+
n int
11+
pg int
12+
mmap []byte
13+
}
14+
15+
func New(n int) (Buffer, error) {
16+
pg := syscall.Getpagesize()
17+
full := ((n+(pg-1))/pg + 2) * pg
18+
19+
b, err := syscall.Mmap(-1, 0, full, syscall.PROT_NONE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
20+
if err != nil {
21+
return Buffer{}, err
22+
}
23+
24+
if n > 0 {
25+
err = syscall.Mprotect(b[pg:full-pg], syscall.PROT_READ|syscall.PROT_WRITE)
26+
if err != nil {
27+
syscall.Munmap(b)
28+
return Buffer{}, err
29+
}
30+
}
31+
32+
return Buffer{
33+
n: n,
34+
pg: pg,
35+
mmap: b,
36+
}, nil
37+
}
38+
39+
func (a *Buffer) ProtectHead() []byte {
40+
head := a.pg
41+
return a.mmap[head : head+a.n]
42+
}
43+
44+
func (a *Buffer) ProtectTail() []byte {
45+
tail := len(a.mmap) - a.pg - a.n
46+
return a.mmap[tail : tail+a.n]
47+
}
48+
49+
func (a *Buffer) Release() {
50+
syscall.Munmap(a.mmap)
51+
}

0 commit comments

Comments
 (0)