]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/list: make a copy of the package before zeroing fields
authorMichael Matloob <matloob@golang.org>
Wed, 3 Jan 2024 19:23:49 +0000 (14:23 -0500)
committerMichael Matloob <matloob@golang.org>
Mon, 29 Jan 2024 19:35:47 +0000 (19:35 +0000)
go list -json=<fields> zeroes out the fields in the package struct
that aren't specified. The problem with this is that some of the fields
have references into other fields: specifically, the NoGoError's
Error() function accesses the package struct's Dir field, so if we
clear it out the error will just print out "no Go files in" without a
directory. Instead, make a copy of the package struct before we zero
out the fields so the original values are still there.

For #64946

Change-Id: I95103e91fa0782bb23a86a965d5eb87cb12654c6
Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-windows-amd64-longtest
Reviewed-on: https://go-review.googlesource.com/c/go/+/553795
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
src/cmd/go/internal/list/list.go
src/cmd/go/testdata/script/list_json_issue64946.txt [new file with mode: 0644]

index d9b09077c1ae1295d3865305e03c8ab4e30b594b..db587148826281b432bcadb1ddf756bee774cc04 100644 (file)
@@ -449,13 +449,15 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
        if listJson {
                do = func(x any) {
                        if !listJsonFields.needAll() {
-                               v := reflect.ValueOf(x).Elem() // do is always called with a non-nil pointer.
-                               // Clear all non-requested fields.
+                               //  Set x to a copy of itself with all non-requested fields cleared.
+                               v := reflect.New(reflect.TypeOf(x).Elem()).Elem() // do is always called with a non-nil pointer.
+                               v.Set(reflect.ValueOf(x).Elem())
                                for i := 0; i < v.NumField(); i++ {
                                        if !listJsonFields.needAny(v.Type().Field(i).Name) {
                                                v.Field(i).SetZero()
                                        }
                                }
+                               x = v.Interface()
                        }
                        b, err := json.MarshalIndent(x, "", "\t")
                        if err != nil {
diff --git a/src/cmd/go/testdata/script/list_json_issue64946.txt b/src/cmd/go/testdata/script/list_json_issue64946.txt
new file mode 100644 (file)
index 0000000..64ff9d9
--- /dev/null
@@ -0,0 +1,10 @@
+cd mod
+go list -e -json=ImportPath,Error ./foo
+stdout '"Err": "no Go files in .*(/|\\\\)src(/|\\\\)mod(/|\\\\)foo"'
+
+-- mod/go.mod --
+module example.com/foo
+
+go 1.21
+-- mod/foo/README.md --
+empty
\ No newline at end of file