-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
os: Environ is corrupted on windows #61956
Comments
I've since verified the same behavior exists on Windows 11 amd64. |
Thanks for reporting. I can reproduce a similar issue in windows/amd64 with go1.20 using PowerShell too:
|
Found this excellent article from Raymond Chen, titled TLDR: Go is not inventing nor misprocessing environment variables, We could filter out variables starting with
|
I don't mind having them but I think there are some things that ought to be done about os.Clearenv and os.Setenv, as one cannot set them or clear and restore them. Perhaps we should have a way to snapshot and restore environment, including weird things like that, reliably, without having to do it through the key=value interface? |
Thinking about this some more and looking at Line 61 in 8870b8d
|
If that is too tricky then perhaps we could have a comment on os.Clearenv, that one cannot round-trip with os.Clearenv and os.Setenv to get the same environment that one had before, on some platforms, so that os.Clearenv should be used carefully - with a link to the article referenced in the Go source tree. |
See previously:
Note in particular that the deduplication logic for |
Could you give some more detail on that? The test I added in https://go.dev/cl/367850 does attempt to verify that |
@bcmills apologies, I misunderstood how to work with environment variables with a leading- For anyone in the future looking at this, the entry is still ought to be a With this clarification all the stdlib functions work correctly: package main
import (
"log"
"os"
"strings"
)
func main() {
before := os.Environ()
os.Clearenv()
for _, ent := range before {
idx := strings.IndexByte(ent, '=')
bias := 0
if idx == 0 {
idx = strings.IndexByte(ent[1:], '=')
bias = 1 // ----------------^
}
if idx < 0 {
log.Fatalf("Environment entry %q is missing an =", ent)
}
idx += bias
k, v := ent[:idx], ent[idx+1:]
log.Printf("Setting environment variable %q to %q", k, v)
if err := os.Setenv(k, v); err != nil {
log.Fatalf("Cannot set environment variable %q to %q: %v", k, v, err)
}
}
after := os.Environ()
if len(before) != len(after) {
log.Fatalf("Environment size differs %d != %d", len(before), len(after))
}
for i := range before {
if before[i] != after[i] {
log.Fatalf("Environment entry %d differs: %q != %q", i, before[i], after[i])
}
}
} This leaves me with only one suggestion, perhaps there ought to be an One small remark about the test added in https://go-review.googlesource.com/c/go/+/367850 -- I think it handles missing, non-leading = incorrectly and would fail to report an error on environment with an entry like |
For reference, my implementation of splitEnv: https://gitlab.com/zygoon/go-cmdr/-/merge_requests/63/diffs |
That sounds reasonable to me. Want to file a separate proposal? |
Duplicate of #49886 |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
This is the latest release at this time, so yes.go
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I called
os.Environ
on a vanilla installation of Windows on aarch64 aka arm64:What did you expect to see?
Normal set of key=value pairs.
What did you see instead?
The first few entries seem malformed (each printed string is from
fmt
with%q
)The same program executed from powershell:
The text was updated successfully, but these errors were encountered: