fix(windows): safer logic for parsing app exec links

This commit is contained in:
Jan De Dobbeleer 2022-02-08 20:20:30 +01:00 committed by Jan De Dobbeleer
parent 2046dcefeb
commit c7a446c081
3 changed files with 16 additions and 12 deletions

View file

@ -418,7 +418,8 @@ func (env *ShellEnvironment) HasCommand(command string) bool {
env.cmdCache.set(command, path) env.cmdCache.set(command, path)
return true return true
} }
if path, err := env.LookWinAppPath(command); err == nil { path, err = env.LookWinAppPath(command)
if err == nil {
env.cmdCache.set(command, path) env.cmdCache.set(command, path)
return true return true
} }

View file

@ -6,6 +6,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"path/filepath"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@ -117,13 +118,13 @@ func (env *ShellEnvironment) CachePath() string {
} }
func (env *ShellEnvironment) LookWinAppPath(file string) (string, error) { func (env *ShellEnvironment) LookWinAppPath(file string) (string, error) {
winAppPath := env.Home() + `\AppData\Local\Microsoft\WindowsApps\` winAppPath := filepath.Join(env.Getenv("LOCALAPPDATA"), `\Microsoft\WindowsApps\`)
command := file + ".exe" command := file + ".exe"
isWinStoreApp := func() bool { isWinStoreApp := func() bool {
return env.HasFilesInDir(winAppPath, command) return env.HasFilesInDir(winAppPath, command)
} }
if isWinStoreApp() { if isWinStoreApp() {
commandFile := winAppPath + command commandFile := filepath.Join(winAppPath, command)
return readWinAppLink(commandFile) return readWinAppLink(commandFile)
} }
return "", errors.New("no Windows Store App") return "", errors.New("no Windows Store App")

View file

@ -218,7 +218,7 @@ type AppExecLinkReparseBuffer struct {
StringList [1]uint16 StringList [1]uint16
} }
func (rb *AppExecLinkReparseBuffer) Path() string { func (rb *AppExecLinkReparseBuffer) Path() (string, error) {
UTF16ToStringPosition := func(s []uint16) (string, int) { UTF16ToStringPosition := func(s []uint16) (string, int) {
for i, v := range s { for i, v := range s {
if v == 0 { if v == 0 {
@ -228,15 +228,18 @@ func (rb *AppExecLinkReparseBuffer) Path() string {
} }
return "", 0 return "", 0
} }
s := (*[0xffff]uint16)(unsafe.Pointer(&rb.StringList[0]))[0:] stringList := (*[0xffff]uint16)(unsafe.Pointer(&rb.StringList[0]))[0:]
var link string var link string
position := 0 var position int
for i := 0; i <= 2; i++ { for i := 0; i <= 2; i++ {
link, position = UTF16ToStringPosition(s) link, position = UTF16ToStringPosition(stringList)
position++ position++
s = s[position:] if position >= len(stringList) {
return "", errors.New("invalid AppExecLinkReparseBuffer")
}
stringList = stringList[position:]
} }
return link return link, nil
} }
// openSymlink calls CreateFile Windows API with FILE_FLAG_OPEN_REPARSE_POINT // openSymlink calls CreateFile Windows API with FILE_FLAG_OPEN_REPARSE_POINT
@ -276,8 +279,7 @@ func readWinAppLink(path string) (string, error) {
rb := (*GenericDataBuffer)(unsafe.Pointer(&rdb.DUMMYUNIONNAME)) rb := (*GenericDataBuffer)(unsafe.Pointer(&rdb.DUMMYUNIONNAME))
appExecLink := (*AppExecLinkReparseBuffer)(unsafe.Pointer(&rb.DataBuffer)) appExecLink := (*AppExecLinkReparseBuffer)(unsafe.Pointer(&rb.DataBuffer))
if appExecLink.Version != 3 { if appExecLink.Version != 3 {
return " ", errors.New("unknown appexec link version") return " ", errors.New("unknown AppExecLink version")
} }
link := appExecLink.Path() return appExecLink.Path()
return link, nil
} }