Issue 1:
by joelegasse:

What steps will reproduce the problem?

Compiling and running the following program:

package main

import (
"bytes"
"fmt"
)

func main() {
data := bytes.NewBuffer([]byte{1, 2, 3, 4, 5})
data.Next(2) // buffer now on element 3
line, _ := data.ReadBytes(3)
fmt.Println(line)
}

What is the expected output?

[3]

What do you see instead?

Runtime panic.

Which compiler are you using (5g, 6g, 8g, gccgo)?

6g

Which operating system are you using?

linux

Which revision are you using? (hg identify)

867d37fb41a4+ release.2011-02-01.1/release

Please provide any additional information below.

In src/pkg/bytes/buffer.go, in the ReadBytes() method, the following line needs to be
updated (including the fix for issue #1498).

diff -r 867d37fb41a4 src/pkg/bytes/buffer.go
--- a/src/pkg/bytes/buffer.go Wed Feb 02 12:09:31 2011 +1100
+++ b/src/pkg/bytes/buffer.go Fri Feb 11 02:35:19 2011 -0500
@@ -309,13 +309,14 @@
// delim.
func (b *Buffer) ReadBytes(delim byte) (line []byte, err os.Error) {
i := IndexByte(b.buf[b.off:], delim)
- size := i + 1 - b.off
- if i < 0 {
+ size := i + 1
+ if size <= 0 {
size = len(b.buf) - b.off
err = os.EOF
}
line = make([]byte, size)
copy(line, b.buf[b.off:])
+ b.off += size
return
}

This is because IndexByte will return the index into the slice that it was passed
(b.buf[b.off:] in this case), which means that i is actually b.off + i with respect to
b.buf. So, there is no need to take away the current offset when calculating the size. A
zero would represent that the delim is at b.off, so we would want to copy 1 byte out of
ReadBytes(), not -1 as in the sample program provided (b.off == 2, so i + 1 - 2 would be
-1). That -1 is then passed to make(), which doesn't like negative sizes. To fix this, I
also changed the check from 'i < 0', to 'size <= 0'. That way we know that in the
call to make() size is greater than or equal to zero.

Issue 2:
by danderson@google.com:

What steps will reproduce the problem?
1. Compile a trivial hello world with the 8* compiler suite.
2. Deploy this binary to a 32-bit server running a kernel patched with grsecurity.
3. Run binary.

What is the expected output?

The binary should run happily.

What do you see instead?

The binary outputs "throw: out of memory (FixAlloc)" and hangs.

Which compiler are you using (5g, 6g, 8g, gccgo)?

8g.

Which operating system are you using?

Linux atlas.natulte.net 2.6.32.24-grsec #1 SMP Fri Oct 22 21:57:04 PDT 2010 i686
GNU/Linux

Which revision are you using? (hg identify)

03da6860bb39 tip

Please provide any additional information below.

Suspecting a binary compatibility issue, I tried to rebuild the entire Go universe on
this server. ./all.bash crashes the first time it tries to run cgo, with the same error.

strace pinpoints the specific startup failure:

mmap2(NULL, 131072, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
-1 EPERM (Operation not permitted)

In kernels hardened with the PaX features of grsecurity, mmap() denies requests for
memory that is both writable and executable, to stop attacks that dump shellcode into
memory and then execute it. It's likely that other hardened kernels (e.g. the more
popular SELinux) enforce the same restrictions.

I haven't yet had time to examine the needs of the Go runtime's allocator, but my hope
is that it doesn't actually need executable memory, in which case the fix is trivially
removing the X bit from the mmap() call.

PaX also comes with a commandline utility to toggle some protection features on a
per-binary basis. Unfortunately, this tool claims that Go binaries have a malformed ELF
header, so I'm unable to toggle the flags. I need to further diagnose this subfailure to
figure out if there's a bug in the ELF writer.