Created
March 28, 2016 22:06
-
-
Save mdempsky/8e17da862a0f3a2c1036 to your computer and use it in GitHub Desktop.
Standalone repro for CL 21005 regression
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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