Skip to content
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

syscall: GetStartupInfo on Windows checks nonexistent return code #31316

Open
apenwarr opened this issue Apr 7, 2019 · 7 comments

Comments

@apenwarr
Copy link

commented Apr 7, 2019

What version of Go are you using (go version)?

$ go version
go version go1.12.1 linux/amd64

(cross compiling to Windows amd64)

Does this issue reproduce with the latest release?

The relevant code has not changed lately.

What did you do?

    var si syscall.StartupInfo
    err := syscall.GetStartupInfo(&si)
    if err != nil {
            fatal("GetStartupInfo: %v\n", err)
    }

What did you expect to see?

err should always be nil, because according to https://technet.microsoft.com/en-us/ms683230(v=vs.90), "The Unicode version (GetStartupInfoW) does not fail."

What did you see instead?

Under some circumstances (eg. starting from cmd.exe), GetStartupInfo returns syscall.EINVAL. Under other circumstances (eg. starting from WSL's bash), it succeeds.

The implementation of GetStartupInfo() is:

func GetStartupInfo(startupInfo *StartupInfo) (err error) {
        r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0)
        if r1 == 0 {
                if e1 != 0 {
                        err = errnoErr(e1)
                } else {
                        err = EINVAL
                }
        }
        return
}

So EINVAL should only happen if r1==0 && e1==0. As far as I can tell, GetStartupInfoW() is never supposed to return any value, so checking r1 is not the right thing to do here.

Indeed, if I copy this function but disable the error check, the StartupInfo struct seems to be filled correctly even in the error case. So I think the correct fix is to simply stop checking the return code.

If you want to be paranoid, you could verify that StartupInfo.Cb is set to a nonzero value after the syscall finishes.

@tklauser

This comment has been minimized.

Copy link
Member

commented Apr 8, 2019

@tklauser tklauser changed the title Windows syscall.GetStartupInfo checks nonexistent return code syscall: GetStartupInfo on Windows checks nonexistent return code Apr 8, 2019
@alexbrainman

This comment has been minimized.

Copy link
Member

commented Apr 9, 2019

Yes, I agree. Thank you very much for reporting.

If I would add this function again, I would have it return nothing, like

func GetStartupInfo(startupInfo *StartupInfo)

But I don't think we could change function signature. Can we @ianlancetaylor ?

If we have to keep it as is

func GetStartupInfo(startupInfo *StartupInfo) error

than we need to decide what to return.

We could always return nil.

Alternatively we could return what GetLastError Windows API returns.

I am not sure which approach is better.

Regardless, we will need new test with this change, because GetStartupInfo is not used anywhere in standard library. So we should at least somehow test it.

And we should, probably, copy our solution into golang.org/x/sys/windows package too.

Alex

@apenwarr

This comment has been minimized.

Copy link
Author

commented Apr 9, 2019

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Apr 10, 2019

GetLastError() is going to just be some random number, and/or what it was before you made the call.

How do you know? Value returned by GetLastError is set during GetStartupInfo implementation.

It's better to just return nil.

Maybe.

Alex

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Apr 10, 2019

I don't think we should change the function signature of GetStartupInfo, but it would fine to make it always return nil if that is appropriate.

@apenwarr

This comment has been minimized.

Copy link
Author

commented Apr 10, 2019

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Apr 12, 2019

I don't think we should change the function signature of GetStartupInfo, but it would fine to make it always return nil if that is appropriate.

Thank you for replying. SGTM

It’s standard for windows functions to not change GetLastError state if they don’t return an “error” status value.

I never seen any of Microsoft Windows API implementations source code, so I would not really know. But pretty much every Windows API changes GetLastError value. So, if the implementation calls other Windows APIs, that would make GetLastError change. But maybe GetStartupInfo implementation does not call any other APIs.

Anyway, it is not important, because we all agreed to have GetStartupInfo return nil. Would you like to send a change? The change would need a test too.

Alex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.