Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into 59016-FailureActi…
Browse files Browse the repository at this point in the history
…onsFlag
  • Loading branch information
craig65535 committed May 3, 2023
2 parents 8df3816 + ca59eda commit 3626b01
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 8 deletions.
2 changes: 1 addition & 1 deletion execabs/execabs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
// Copied from internal/testenv.HasExec
func hasExec() bool {
switch runtime.GOOS {
case "js", "ios":
case "wasip1", "js", "ios":
return false
}
return true
Expand Down
6 changes: 3 additions & 3 deletions windows/env_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) {
return nil, err
}
defer DestroyEnvironmentBlock(block)
blockp := uintptr(unsafe.Pointer(block))
blockp := unsafe.Pointer(block)
for {
entry := UTF16PtrToString((*uint16)(unsafe.Pointer(blockp)))
entry := UTF16PtrToString((*uint16)(blockp))
if len(entry) == 0 {
break
}
env = append(env, entry)
blockp += 2 * (uintptr(len(entry)) + 1)
blockp = unsafe.Add(blockp, 2*(len(entry)+1))
}
return env, nil
}
Expand Down
7 changes: 6 additions & 1 deletion windows/exec_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,17 @@ func ComposeCommandLine(args []string) string {
// DecomposeCommandLine breaks apart its argument command line into unescaped parts using CommandLineToArgv,
// as gathered from GetCommandLine, QUERY_SERVICE_CONFIG's BinaryPathName argument, or elsewhere that
// command lines are passed around.
// DecomposeCommandLine returns error if commandLine contains NUL.
func DecomposeCommandLine(commandLine string) ([]string, error) {
if len(commandLine) == 0 {
return []string{}, nil
}
utf16CommandLine, err := UTF16FromString(commandLine)
if err != nil {
return nil, errorspkg.New("string with NUL passed to DecomposeCommandLine")
}
var argc int32
argv, err := CommandLineToArgv(StringToUTF16Ptr(commandLine), &argc)
argv, err := CommandLineToArgv(&utf16CommandLine[0], &argc)
if err != nil {
return nil, err
}
Expand Down
17 changes: 17 additions & 0 deletions windows/svc/mgr/mgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"testing"
"time"

"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
)
Expand Down Expand Up @@ -259,6 +260,16 @@ func testMultipleRecoverySettings(t *testing.T, s *mgr.Service, rebootMsgShould,
}
}

func testControl(t *testing.T, s *mgr.Service, c svc.Cmd, expectedErr error, expectedStatus svc.Status) {
status, err := s.Control(c)
if err != expectedErr {
t.Fatalf("Unexpected return from s.Control: %v (expected %v)", err, expectedErr)
}
if expectedStatus != status {
t.Fatalf("Unexpected status from s.Control: %+v (expected %+v)", status, expectedStatus)
}
}

func remove(t *testing.T, s *mgr.Service) {
err := s.Delete()
if err != nil {
Expand Down Expand Up @@ -302,6 +313,7 @@ func TestMyService(t *testing.T) {
t.Fatalf("service %s is not installed", name)
}
defer s.Close()
defer s.Delete()

c.BinaryPathName = exepath
c = testConfig(t, s, c)
Expand Down Expand Up @@ -347,6 +359,11 @@ func TestMyService(t *testing.T) {
testRecoveryActionsOnNonCrashFailures(t, s, false)
testMultipleRecoverySettings(t, s, fmt.Sprintf("%s failed", name), fmt.Sprintf("sc query %s", name), true)

expectedStatus := svc.Status{
State: svc.Stopped,
}
testControl(t, s, svc.Stop, windows.ERROR_SERVICE_NOT_ACTIVE, expectedStatus)

remove(t, s)
}

Expand Down
14 changes: 11 additions & 3 deletions windows/svc/mgr/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,25 @@ func (s *Service) Start(args ...string) error {
return windows.StartService(s.Handle, uint32(len(args)), p)
}

// Control sends state change request c to the service s.
// Control sends state change request c to the service s. It returns the most
// recent status the service reported to the service control manager, and an
// error if the state change request was not accepted.
// Note that the returned service status is only set if the status change
// request succeeded, or if it failed with error ERROR_INVALID_SERVICE_CONTROL,
// ERROR_SERVICE_CANNOT_ACCEPT_CTRL, or ERROR_SERVICE_NOT_ACTIVE.
func (s *Service) Control(c svc.Cmd) (svc.Status, error) {
var t windows.SERVICE_STATUS
err := windows.ControlService(s.Handle, uint32(c), &t)
if err != nil {
if err != nil &&
err != windows.ERROR_INVALID_SERVICE_CONTROL &&
err != windows.ERROR_SERVICE_CANNOT_ACCEPT_CTRL &&
err != windows.ERROR_SERVICE_NOT_ACTIVE {
return svc.Status{}, err
}
return svc.Status{
State: svc.State(t.CurrentState),
Accepts: svc.Accepted(t.ControlsAccepted),
}, nil
}, err
}

// Query returns current status of service s.
Expand Down
16 changes: 16 additions & 0 deletions windows/syscall_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,22 @@ func TestCommandLineRecomposition(t *testing.T) {
continue
}
}

// check that windows.DecomposeCommandLine returns error for strings with NUL
testsWithNUL := []string{
"\x00abcd",
"ab\x00cd",
"abcd\x00",
"\x00abcd\x00",
"\x00ab\x00cd\x00",
"\x00\x00\x00",
}
for _, test := range testsWithNUL {
_, err := windows.DecomposeCommandLine(test)
if err == nil {
t.Errorf("Failed to return error while decomposing %#q string with NUL inside", test)
}
}
}

func TestWinVerifyTrust(t *testing.T) {
Expand Down

0 comments on commit 3626b01

Please sign in to comment.