Skip to content

Commit 7ed50cf

Browse files
rscgopherbot
authored andcommitted
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 <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Bryan Mills <[email protected]> Auto-Submit: Russ Cox <[email protected]>
1 parent a4a86c7 commit 7ed50cf

File tree

6 files changed

+44
-9
lines changed

6 files changed

+44
-9
lines changed

src/internal/syscall/unix/user_darwin.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,56 +52,60 @@ type Group struct {
5252
func libc_getpwnam_r_trampoline()
5353

5454
func Getpwnam(name *byte, pwd *Passwd, buf *byte, size uintptr, result **Passwd) syscall.Errno {
55-
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getpwnam_r_trampoline),
55+
// Note: Returns an errno as its actual result, not in global errno.
56+
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getpwnam_r_trampoline),
5657
uintptr(unsafe.Pointer(name)),
5758
uintptr(unsafe.Pointer(pwd)),
5859
uintptr(unsafe.Pointer(buf)),
5960
size,
6061
uintptr(unsafe.Pointer(result)),
6162
0)
62-
return errno
63+
return syscall.Errno(errno)
6364
}
6465

6566
//go:cgo_import_dynamic libc_getpwuid_r getpwuid_r "/usr/lib/libSystem.B.dylib"
6667
func libc_getpwuid_r_trampoline()
6768

6869
func Getpwuid(uid uint32, pwd *Passwd, buf *byte, size uintptr, result **Passwd) syscall.Errno {
69-
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getpwuid_r_trampoline),
70+
// Note: Returns an errno as its actual result, not in global errno.
71+
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getpwuid_r_trampoline),
7072
uintptr(uid),
7173
uintptr(unsafe.Pointer(pwd)),
7274
uintptr(unsafe.Pointer(buf)),
7375
size,
7476
uintptr(unsafe.Pointer(result)),
7577
0)
76-
return errno
78+
return syscall.Errno(errno)
7779
}
7880

7981
//go:cgo_import_dynamic libc_getgrnam_r getgrnam_r "/usr/lib/libSystem.B.dylib"
8082
func libc_getgrnam_r_trampoline()
8183

8284
func Getgrnam(name *byte, grp *Group, buf *byte, size uintptr, result **Group) syscall.Errno {
83-
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getgrnam_r_trampoline),
85+
// Note: Returns an errno as its actual result, not in global errno.
86+
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getgrnam_r_trampoline),
8487
uintptr(unsafe.Pointer(name)),
8588
uintptr(unsafe.Pointer(grp)),
8689
uintptr(unsafe.Pointer(buf)),
8790
size,
8891
uintptr(unsafe.Pointer(result)),
8992
0)
90-
return errno
93+
return syscall.Errno(errno)
9194
}
9295

9396
//go:cgo_import_dynamic libc_getgrgid_r getgrgid_r "/usr/lib/libSystem.B.dylib"
9497
func libc_getgrgid_r_trampoline()
9598

9699
func Getgrgid(gid uint32, grp *Group, buf *byte, size uintptr, result **Group) syscall.Errno {
97-
_, _, errno := syscall_syscall6(abi.FuncPCABI0(libc_getgrgid_r_trampoline),
100+
// Note: Returns an errno as its actual result, not in global errno.
101+
errno, _, _ := syscall_syscall6(abi.FuncPCABI0(libc_getgrgid_r_trampoline),
98102
uintptr(gid),
99103
uintptr(unsafe.Pointer(grp)),
100104
uintptr(unsafe.Pointer(buf)),
101105
size,
102106
uintptr(unsafe.Pointer(result)),
103107
0)
104-
return errno
108+
return syscall.Errno(errno)
105109
}
106110

107111
//go:cgo_import_dynamic libc_sysconf sysconf "/usr/lib/libSystem.B.dylib"

src/os/user/cgo_lookup_unix.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func buildGroup(grp *_C_struct_group) *Group {
141141

142142
type bufferKind _C_int
143143

144-
const (
144+
var (
145145
userBuffer = bufferKind(_C__SC_GETPW_R_SIZE_MAX)
146146
groupBuffer = bufferKind(_C__SC_GETGR_R_SIZE_MAX)
147147
)

src/os/user/lookup_plan9.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ func init() {
2020
groupListImplemented = false
2121
}
2222

23+
var (
24+
// unused variables (in this implementation)
25+
// modified during test to exercise code paths in the cgo implementation.
26+
userBuffer = 0
27+
groupBuffer = 0
28+
)
29+
2330
func current() (*User, error) {
2431
ubytes, err := os.ReadFile("/dev/user")
2532
if err != nil {

src/os/user/lookup_stubs.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ import (
1313
"strconv"
1414
)
1515

16+
var (
17+
// unused variables (in this implementation)
18+
// modified during test to exercise code paths in the cgo implementation.
19+
userBuffer = 0
20+
groupBuffer = 0
21+
)
22+
1623
func current() (*User, error) {
1724
uid := currentUID()
1825
// $USER and /etc/passwd may disagree; prefer the latter if we can get it.

src/os/user/lookup_windows.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ func newUser(uid, gid, dir, username, domain string) (*User, error) {
192192
return u, nil
193193
}
194194

195+
var (
196+
// unused variables (in this implementation)
197+
// modified during test to exercise code paths in the cgo implementation.
198+
userBuffer = 0
199+
groupBuffer = 0
200+
)
201+
195202
func current() (*User, error) {
196203
t, e := syscall.OpenCurrentProcessToken()
197204
if e != nil {

src/os/user/user_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ func checkUser(t *testing.T) {
1616
}
1717

1818
func TestCurrent(t *testing.T) {
19+
old := userBuffer
20+
defer func() {
21+
userBuffer = old
22+
}()
23+
userBuffer = 1 // force use of retry code
1924
u, err := Current()
2025
if err != nil {
2126
t.Fatalf("Current: %v (got %#v)", err, u)
@@ -91,6 +96,11 @@ func checkGroup(t *testing.T) {
9196
}
9297

9398
func TestLookupGroup(t *testing.T) {
99+
old := groupBuffer
100+
defer func() {
101+
groupBuffer = old
102+
}()
103+
groupBuffer = 1 // force use of retry code
94104
checkGroup(t)
95105
user, err := Current()
96106
if err != nil {

0 commit comments

Comments
 (0)