Skip to content

Commit bf23839

Browse files
dgryskiaykevl
authored andcommitted
src/os,src/syscall: move env copy code to syscall.Environ()
1 parent 6b15a72 commit bf23839

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

src/os/env.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package os
88

99
import (
1010
"internal/testlog"
11-
"strings"
1211
"syscall"
1312
)
1413

@@ -138,13 +137,5 @@ func Clearenv() {
138137
// Environ returns a copy of strings representing the environment,
139138
// in the form "key=value".
140139
func Environ() []string {
141-
orig := syscall.Environ()
142-
single := strings.Join(orig, "")
143-
env := make([]string, len(orig))
144-
for i, v := range orig {
145-
s := single[:len(v)]
146-
env[i] = s
147-
single = single[len(v):]
148-
}
149-
return env
140+
return syscall.Environ()
150141
}

src/syscall/syscall_libc.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,20 +235,41 @@ func Mprotect(b []byte, prot int) (err error) {
235235
}
236236

237237
func Environ() []string {
238-
environ := libc_environ
239-
var envs []string
240-
for *environ != nil {
241-
// Convert the C string to a Go string.
242-
length := libc_strlen(*environ)
238+
// calculate total memory required
239+
var length uintptr
240+
var vars int
241+
for environ := libc_environ; *environ != nil; {
242+
length += libc_strlen(*environ)
243+
vars++
244+
environ = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(environ)) + unsafe.Sizeof(environ)))
245+
}
246+
247+
// allocate our backing slice for the strings
248+
b := make([]byte, length)
249+
// and the slice we're going to return
250+
envs := make([]string, 0, vars)
251+
252+
// loop over the environment again, this time copying over the data to the backing slice
253+
for environ := libc_environ; *environ != nil; {
254+
length = libc_strlen(*environ)
255+
// construct a Go string pointing at the libc-allocated environment variable data
243256
var envVar string
244257
rawEnvVar := (*struct {
245258
ptr unsafe.Pointer
246259
length uintptr
247260
})(unsafe.Pointer(&envVar))
248261
rawEnvVar.ptr = *environ
249262
rawEnvVar.length = length
250-
envs = append(envs, envVar)
251-
// This is the Go equivalent of "environ++" in C.
263+
// pull off the number of bytes we need for this environment variable
264+
var bs []byte
265+
bs, b = b[:length], b[length:]
266+
// copy over the bytes to the Go heap
267+
copy(bs, envVar)
268+
// convert trimmed slice to string
269+
s := *(*string)(unsafe.Pointer(&bs))
270+
// add s to our list of environment variables
271+
envs = append(envs, s)
272+
// environ++
252273
environ = (*unsafe.Pointer)(unsafe.Pointer(uintptr(unsafe.Pointer(environ)) + unsafe.Sizeof(environ)))
253274
}
254275
return envs

0 commit comments

Comments
 (0)