Skip to content

Instantly share code, notes, and snippets.

@mdempsky
Created March 28, 2016 22:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdempsky/8e17da862a0f3a2c1036 to your computer and use it in GitHub Desktop.
Save mdempsky/8e17da862a0f3a2c1036 to your computer and use it in GitHub Desktop.
Standalone repro for CL 21005 regression
package syscall
import (
"errors"
"unsafe"
)
var ErrBadStat = errors.New("malformed stat buffer")
const (
STATMAX = 65535
STATFIXLEN = 49
)
const (
SYS_PREAD = 50
)
// readdirnames returns the names of files inside the directory represented by dirfd.
func readdirnames(dirfd int) (names []string, err error) {
names = make([]string, 0, 100)
var buf [STATMAX]byte
for {
n, e := Read(dirfd, buf[:])
if e != nil {
return nil, e
}
if n == 0 {
break
}
for i := 0; i < n; {
m, _ := gbit16(buf[i:])
m += 2
if m < STATFIXLEN {
return nil, ErrBadStat
}
s, _, ok := gstring(buf[i+41:])
if !ok {
return nil, ErrBadStat
}
names = append(names, s)
i += int(m)
}
}
return
}
// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b.
func gbit16(b []byte) (uint16, []byte) {
return uint16(b[0]) | uint16(b[1])<<8, b[2:]
}
// gstring reads a string from b, prefixed with a 16-bit length in little-endian order.
// It returns the string with the remaining slice of b and a boolean. If the length is
// greater than the number of bytes in b, the boolean will be false.
func gstring(b []byte) (string, []byte, bool) {
n, b := gbit16(b)
if int(n) > len(b) {
return "", b, false
}
return string(b[:n]), b[n:], true
}
func Read(fd int, p []byte) (n int, err error) {
return Pread(fd, p, -1)
}
func Pread(fd int, p []byte, offset int64) (n int, err error) {
var _p0 unsafe.Pointer
if len(p) > 0 {
_p0 = unsafe.Pointer(&p[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0)
n = int(r0)
if int32(r0) == -1 {
err = e1
}
return
}
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr
// ErrorString implements Error's String method by returning itself.
type ErrorString string
func (e ErrorString) Error() string { return string(e) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment