Skip to content

Commit ad02017

Browse files
mauri870gopherbot
authored andcommitted
windows: use SyscallN in mkwinsyscall
The mkwinsyscall command has a hard limit of 15 on the number of syscall arguments. Windows has several system calls with more than 15 arguments, for example CreateFontPackage has 18 arguments. If the number of arguments is higher than 15 we use SyscallN. Fixes golang/go#57914 Change-Id: I4205e779a960ae10c0778de7876154e0d7ec00a1 GitHub-Last-Rev: 1f1e96f GitHub-Pull-Request: #171 Reviewed-on: https://go-review.googlesource.com/c/sys/+/518995 Reviewed-by: Alex Brainman <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Run-TryBot: Alex Brainman <[email protected]>
1 parent 7023367 commit ad02017

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

Diff for: windows/mkwinsyscall/mkwinsyscall.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ import (
5757
"go/parser"
5858
"go/token"
5959
"io"
60-
"io/ioutil"
6160
"log"
6261
"os"
6362
"path/filepath"
@@ -568,6 +567,8 @@ func (f *Fn) SyscallParamCount() int {
568567
return 12
569568
case n <= 15:
570569
return 15
570+
case n <= 42: // current SyscallN limit
571+
return n
571572
default:
572573
panic("too many arguments to system call")
573574
}
@@ -579,6 +580,9 @@ func (f *Fn) Syscall() string {
579580
if c == 3 {
580581
return syscalldot() + "Syscall"
581582
}
583+
if c > 15 {
584+
return syscalldot() + "SyscallN"
585+
}
582586
return syscalldot() + "Syscall" + strconv.Itoa(c)
583587
}
584588

@@ -923,7 +927,7 @@ func main() {
923927
if *filename == "" {
924928
_, err = os.Stdout.Write(data)
925929
} else {
926-
err = ioutil.WriteFile(*filename, data, 0644)
930+
err = os.WriteFile(*filename, data, 0644)
927931
}
928932
if err != nil {
929933
log.Fatal(err)
@@ -1011,7 +1015,7 @@ func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
10111015
10121016
{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
10131017
1014-
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
1018+
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(),{{if le .ParamCount 15}} {{.ParamCount}},{{end}} {{.SyscallParamList}}){{end}}
10151019
10161020
{{define "tmpvarsreadback"}}{{range .Params}}{{if .TmpVarReadbackCode}}
10171021
{{.TmpVarReadbackCode}}{{end}}{{end}}{{end}}

Diff for: windows/mkwinsyscall/mkwinsyscall_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"go/format"
1010
"os"
1111
"path/filepath"
12+
"strings"
1213
"testing"
1314
)
1415

@@ -48,3 +49,65 @@ func TestDLLFilenameEscaping(t *testing.T) {
4849
})
4950
}
5051
}
52+
53+
func TestSyscallXGeneration(t *testing.T) {
54+
tests := []struct {
55+
name string
56+
wantsysfunc string
57+
sig string
58+
}{
59+
{
60+
name: "syscall with 2 params",
61+
wantsysfunc: "syscall.Syscall",
62+
sig: "Example(a1 *uint16, a2 *uint16) = ",
63+
},
64+
{
65+
name: "syscall with 6 params",
66+
wantsysfunc: "syscall.Syscall6",
67+
sig: "Example(a1 *uint, a2 *uint, a3 *uint, a4 *uint, a5 *uint, a6 *uint) = ",
68+
},
69+
{
70+
name: "syscall with 15 params",
71+
wantsysfunc: "syscall.Syscall15",
72+
sig: strings.ReplaceAll(`Example(a1 *uint, a2 *uint, a3 *uint, a4 *uint, a5 *uint, a6 *uint,
73+
a7 *uint, a8 *uint, a9 *uint, a10 *uint, a11 *uint, a12 *uint,
74+
a13 *uint, a14 *uint, a15 *uint) = `, "\n", ""),
75+
},
76+
{
77+
name: "syscall with 18 params",
78+
wantsysfunc: "syscall.SyscallN",
79+
sig: strings.ReplaceAll(`Example(a1 *uint, a2 *uint, a3 *uint, a4 *uint, a5 *uint, a6 *uint,
80+
a7 *uint, a8 *uint, a9 *uint, a10 *uint, a11 *uint, a12 *uint,
81+
a13 *uint, a14 *uint, a15 *uint, a16 *uint, a17 *uint, a18 *uint) = `, "\n", ""),
82+
},
83+
}
84+
for _, tt := range tests {
85+
t.Run(tt.name, func(t *testing.T) {
86+
// Write the syscall into a temp file for testing.
87+
prefix := "package windows\n//sys " + tt.sig
88+
suffix := ".Example"
89+
name := filepath.Join(t.TempDir(), "syscall.go")
90+
if err := os.WriteFile(name, []byte(prefix+"example"+suffix), 0666); err != nil {
91+
t.Fatal(err)
92+
}
93+
94+
// Ensure parsing, generating, and formatting run without errors.
95+
// This is good enough to show that escaping is working.
96+
src, err := ParseFiles([]string{name})
97+
if err != nil {
98+
t.Fatal(err)
99+
}
100+
var buf bytes.Buffer
101+
if err := src.Generate(&buf); err != nil {
102+
t.Fatal(err)
103+
}
104+
if _, err := format.Source(buf.Bytes()); err != nil {
105+
t.Fatal(err)
106+
}
107+
108+
if !strings.Contains(buf.String(), tt.wantsysfunc+"(") {
109+
t.Fatalf("expected syscall func %q in buffer %s", tt.wantsysfunc, buf.String())
110+
}
111+
})
112+
}
113+
}

0 commit comments

Comments
 (0)