mirror of
https://github.com/golang/go
synced 2024-11-18 00:34:44 -07:00
os/user: fix buffer retry loop on macOS
getpwnam_r and friends return the errno as the result, not in the global errno. The code changes in CL 449316 inadvertently started using the global errno. So if a lookup didn't fit in the first buffer size, it was treated as not found instead of growing the buffer. Fixes #56942. Change-Id: Ic5904fbeb31161bccd858e5adb987e919fb3e9d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/455815 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Bryan Mills <bcmills@google.com> Auto-Submit: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
a4a86c7b24
commit
7ed50cfd09
@ -52,56 +52,60 @@ type Group struct {
|
||||
func libc_getpwnam_r_trampoline()
|
||||
|
||||
func Getpwnam(name *byte, pwd *Passwd, buf *byte, size uintptr, result **Passwd) syscall.Errno {
|
||||
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getpwnam_r_trampoline),
|
||||
// Note: Returns an errno as its actual result, not in global errno.
|
||||
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getpwnam_r_trampoline),
|
||||
uintptr(unsafe.Pointer(name)),
|
||||
uintptr(unsafe.Pointer(pwd)),
|
||||
uintptr(unsafe.Pointer(buf)),
|
||||
size,
|
||||
uintptr(unsafe.Pointer(result)),
|
||||
0)
|
||||
return errno
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
|
||||
//go:cgo_import_dynamic libc_getpwuid_r getpwuid_r "/usr/lib/libSystem.B.dylib"
|
||||
func libc_getpwuid_r_trampoline()
|
||||
|
||||
func Getpwuid(uid uint32, pwd *Passwd, buf *byte, size uintptr, result **Passwd) syscall.Errno {
|
||||
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getpwuid_r_trampoline),
|
||||
// Note: Returns an errno as its actual result, not in global errno.
|
||||
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getpwuid_r_trampoline),
|
||||
uintptr(uid),
|
||||
uintptr(unsafe.Pointer(pwd)),
|
||||
uintptr(unsafe.Pointer(buf)),
|
||||
size,
|
||||
uintptr(unsafe.Pointer(result)),
|
||||
0)
|
||||
return errno
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
|
||||
//go:cgo_import_dynamic libc_getgrnam_r getgrnam_r "/usr/lib/libSystem.B.dylib"
|
||||
func libc_getgrnam_r_trampoline()
|
||||
|
||||
func Getgrnam(name *byte, grp *Group, buf *byte, size uintptr, result **Group) syscall.Errno {
|
||||
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getgrnam_r_trampoline),
|
||||
// Note: Returns an errno as its actual result, not in global errno.
|
||||
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getgrnam_r_trampoline),
|
||||
uintptr(unsafe.Pointer(name)),
|
||||
uintptr(unsafe.Pointer(grp)),
|
||||
uintptr(unsafe.Pointer(buf)),
|
||||
size,
|
||||
uintptr(unsafe.Pointer(result)),
|
||||
0)
|
||||
return errno
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
|
||||
//go:cgo_import_dynamic libc_getgrgid_r getgrgid_r "/usr/lib/libSystem.B.dylib"
|
||||
func libc_getgrgid_r_trampoline()
|
||||
|
||||
func Getgrgid(gid uint32, grp *Group, buf *byte, size uintptr, result **Group) syscall.Errno {
|
||||
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getgrgid_r_trampoline),
|
||||
// Note: Returns an errno as its actual result, not in global errno.
|
||||
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getgrgid_r_trampoline),
|
||||
uintptr(gid),
|
||||
uintptr(unsafe.Pointer(grp)),
|
||||
uintptr(unsafe.Pointer(buf)),
|
||||
size,
|
||||
uintptr(unsafe.Pointer(result)),
|
||||
0)
|
||||
return errno
|
||||
return syscall.Errno(errno)
|
||||
}
|
||||
|
||||
//go:cgo_import_dynamic libc_sysconf sysconf "/usr/lib/libSystem.B.dylib"
|
||||
|
@ -141,7 +141,7 @@ func buildGroup(grp *_C_struct_group) *Group {
|
||||
|
||||
type bufferKind _C_int
|
||||
|
||||
const (
|
||||
var (
|
||||
userBuffer = bufferKind(_C__SC_GETPW_R_SIZE_MAX)
|
||||
groupBuffer = bufferKind(_C__SC_GETGR_R_SIZE_MAX)
|
||||
)
|
||||
|
@ -20,6 +20,13 @@ func init() {
|
||||
groupListImplemented = false
|
||||
}
|
||||
|
||||
var (
|
||||
// unused variables (in this implementation)
|
||||
// modified during test to exercise code paths in the cgo implementation.
|
||||
userBuffer = 0
|
||||
groupBuffer = 0
|
||||
)
|
||||
|
||||
func current() (*User, error) {
|
||||
ubytes, err := os.ReadFile("/dev/user")
|
||||
if err != nil {
|
||||
|
@ -13,6 +13,13 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
// unused variables (in this implementation)
|
||||
// modified during test to exercise code paths in the cgo implementation.
|
||||
userBuffer = 0
|
||||
groupBuffer = 0
|
||||
)
|
||||
|
||||
func current() (*User, error) {
|
||||
uid := currentUID()
|
||||
// $USER and /etc/passwd may disagree; prefer the latter if we can get it.
|
||||
|
@ -192,6 +192,13 @@ func newUser(uid, gid, dir, username, domain string) (*User, error) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
var (
|
||||
// unused variables (in this implementation)
|
||||
// modified during test to exercise code paths in the cgo implementation.
|
||||
userBuffer = 0
|
||||
groupBuffer = 0
|
||||
)
|
||||
|
||||
func current() (*User, error) {
|
||||
t, e := syscall.OpenCurrentProcessToken()
|
||||
if e != nil {
|
||||
|
@ -16,6 +16,11 @@ func checkUser(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCurrent(t *testing.T) {
|
||||
old := userBuffer
|
||||
defer func() {
|
||||
userBuffer = old
|
||||
}()
|
||||
userBuffer = 1 // force use of retry code
|
||||
u, err := Current()
|
||||
if err != nil {
|
||||
t.Fatalf("Current: %v (got %#v)", err, u)
|
||||
@ -91,6 +96,11 @@ func checkGroup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLookupGroup(t *testing.T) {
|
||||
old := groupBuffer
|
||||
defer func() {
|
||||
groupBuffer = old
|
||||
}()
|
||||
groupBuffer = 1 // force use of retry code
|
||||
checkGroup(t)
|
||||
user, err := Current()
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user