Skip to content

Commit 10ae7c3

Browse files
committed
Improve LookPath
1 parent ae2d1bd commit 10ae7c3

File tree

18 files changed

+129
-42
lines changed

18 files changed

+129
-42
lines changed

common/hexec/safeCommand.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2020 The Hugo Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package hexec
15+
16+
import (
17+
"context"
18+
19+
"os/exec"
20+
21+
"github.com/cli/safeexec"
22+
)
23+
24+
// SafeCommand is a wrapper around os/exec Command which uses a LookPath
25+
// implementation that does not search in current directory before looking in PATH.
26+
// See https://github.com/cli/safeexec and the linked issues.
27+
func SafeCommand(name string, arg ...string) (*exec.Cmd, error) {
28+
bin, err := safeexec.LookPath(name)
29+
if err != nil {
30+
return nil, err
31+
}
32+
33+
return exec.Command(bin, arg...), nil
34+
}
35+
36+
// SafeCommandContext wraps CommandContext
37+
// See SafeCommand for more context.
38+
func SafeCommandContext(ctx context.Context, name string, arg ...string) (*exec.Cmd, error) {
39+
bin, err := safeexec.LookPath(name)
40+
if err != nil {
41+
return nil, err
42+
}
43+
44+
return exec.CommandContext(ctx, bin, arg...), nil
45+
}

create/content.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import (
1818
"bytes"
1919
"io"
2020
"os"
21-
"os/exec"
2221
"path/filepath"
2322
"strings"
2423

2524
"github.com/pkg/errors"
2625

26+
"github.com/gohugoio/hugo/common/hexec"
2727
"github.com/gohugoio/hugo/hugofs/files"
2828

2929
"github.com/gohugoio/hugo/hugofs"
@@ -105,7 +105,10 @@ func NewContent(
105105
jww.FEEDBACK.Printf("Editing %s with %q ...\n", targetPath, editor)
106106

107107
editorCmd := append(strings.Fields(editor), contentPath)
108-
cmd := exec.Command(editorCmd[0], editorCmd[1:]...)
108+
cmd, err := hexec.SafeCommand(editorCmd[0], editorCmd[1:]...)
109+
if err != nil {
110+
return err
111+
}
109112
cmd.Stdin = os.Stdin
110113
cmd.Stdout = os.Stdout
111114
cmd.Stderr = os.Stderr

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
github.com/bep/gitmap v1.1.2
1414
github.com/bep/golibsass v0.7.0
1515
github.com/bep/tmc v0.5.1
16+
github.com/cli/safeexec v1.0.0
1617
github.com/disintegration/gift v1.2.1
1718
github.com/dlclark/regexp2 v1.4.0 // indirect
1819
github.com/dustin/go-humanize v1.0.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgk
148148
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
149149
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
150150
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
151+
github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
152+
github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
151153
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
152154
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
153155
github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=

hugolib/js_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ package hugolib
1616
import (
1717
"fmt"
1818
"os"
19-
"os/exec"
2019
"path/filepath"
2120
"runtime"
2221
"testing"
2322

23+
"github.com/gohugoio/hugo/common/hexec"
24+
2425
"github.com/gohugoio/hugo/htesting"
2526

2627
"github.com/spf13/viper"
@@ -125,7 +126,9 @@ TS: {{ template "print" $ts }}
125126

126127
b.WithSourceFile("assets/js/included.js", includedJS)
127128

128-
out, err := exec.Command("npm", "install").CombinedOutput()
129+
cmd, err := hexec.SafeCommand("npm", "install")
130+
b.Assert(err, qt.IsNil)
131+
out, err := cmd.CombinedOutput()
129132
b.Assert(err, qt.IsNil, qt.Commentf(string(out)))
130133

131134
b.Build(BuildCfg{})
@@ -193,7 +196,8 @@ require github.com/gohugoio/hugoTestProjectJSModImports v0.5.0 // indirect
193196
}`)
194197

195198
b.Assert(os.Chdir(workDir), qt.IsNil)
196-
_, err = exec.Command("npm", "install").CombinedOutput()
199+
cmd, _ := hexec.SafeCommand("npm", "install")
200+
_, err = cmd.CombinedOutput()
197201
b.Assert(err, qt.IsNil)
198202

199203
b.Build(BuildCfg{})

hugolib/resource_chain_babel_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ package hugolib
1616
import (
1717
"bytes"
1818
"os"
19-
"os/exec"
2019
"path/filepath"
2120
"runtime"
2221
"testing"
2322

23+
"github.com/gohugoio/hugo/common/hexec"
24+
2425
jww "github.com/spf13/jwalterweatherman"
2526

2627
"github.com/gohugoio/hugo/htesting"
@@ -111,7 +112,8 @@ Transpiled: {{ $transpiled.Content | safeJS }}
111112
b.WithSourceFile("babel.config.js", babelConfig)
112113

113114
b.Assert(os.Chdir(workDir), qt.IsNil)
114-
_, err = exec.Command("npm", "install").CombinedOutput()
115+
cmd, _ := hexec.SafeCommand("npm", "install")
116+
_, err = cmd.CombinedOutput()
115117
b.Assert(err, qt.IsNil)
116118

117119
b.Build(BuildCfg{})

hugolib/resource_chain_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import (
1919
"io"
2020
"math/rand"
2121
"os"
22-
"os/exec"
22+
2323
"path/filepath"
2424
"runtime"
2525
"strings"
2626
"testing"
2727
"time"
2828

29+
"github.com/gohugoio/hugo/common/hexec"
30+
2931
jww "github.com/spf13/jwalterweatherman"
3032

3133
"github.com/gohugoio/hugo/common/herrors"
@@ -930,7 +932,8 @@ class-in-b {
930932
b.WithSourceFile("postcss.config.js", postcssConfig)
931933

932934
b.Assert(os.Chdir(workDir), qt.IsNil)
933-
_, err = exec.Command("npm", "install").CombinedOutput()
935+
cmd, err := hexec.SafeCommand("npm", "install")
936+
_, err = cmd.CombinedOutput()
934937
b.Assert(err, qt.IsNil)
935938
b.Build(BuildCfg{})
936939

markup/asciidocext/convert.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ package asciidocext
1818

1919
import (
2020
"bytes"
21-
"os/exec"
2221
"path/filepath"
2322

23+
"github.com/cli/safeexec"
24+
2425
"github.com/gohugoio/hugo/identity"
2526
"github.com/gohugoio/hugo/markup/asciidocext/asciidocext_config"
2627
"github.com/gohugoio/hugo/markup/converter"
@@ -193,7 +194,7 @@ func (a *asciidocConverter) appendArg(args []string, option, value, defaultValue
193194
}
194195

195196
func getAsciidoctorExecPath() string {
196-
path, err := exec.LookPath("asciidoctor")
197+
path, err := safeexec.LookPath("asciidoctor")
197198
if err != nil {
198199
return ""
199200
}

markup/internal/external.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package internal
22

33
import (
44
"bytes"
5-
"os/exec"
65
"strings"
76

7+
"github.com/cli/safeexec"
8+
"github.com/gohugoio/hugo/common/hexec"
9+
810
"github.com/gohugoio/hugo/markup/converter"
911
)
1012

@@ -13,12 +15,16 @@ func ExternallyRenderContent(
1315
ctx converter.DocumentContext,
1416
content []byte, path string, args []string) []byte {
1517
logger := cfg.Logger
16-
cmd := exec.Command(path, args...)
18+
cmd, err := hexec.SafeCommand(path, args...)
19+
if err != nil {
20+
logger.Errorf("%s rendering %s: %v", path, ctx.DocumentName, err)
21+
return nil
22+
}
1723
cmd.Stdin = bytes.NewReader(content)
1824
var out, cmderr bytes.Buffer
1925
cmd.Stdout = &out
2026
cmd.Stderr = &cmderr
21-
err := cmd.Run()
27+
err = cmd.Run()
2228
// Most external helpers exit w/ non-zero exit code only if severe, i.e.
2329
// halting errors occurred. -> log stderr output regardless of state of err
2430
for _, item := range strings.Split(cmderr.String(), "\n") {
@@ -40,9 +46,9 @@ func normalizeExternalHelperLineFeeds(content []byte) []byte {
4046
}
4147

4248
func GetPythonExecPath() string {
43-
path, err := exec.LookPath("python")
49+
path, err := safeexec.LookPath("python")
4450
if err != nil {
45-
path, err = exec.LookPath("python.exe")
51+
path, err = safeexec.LookPath("python.exe")
4652
if err != nil {
4753
return ""
4854
}

markup/pandoc/convert.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
package pandoc
1616

1717
import (
18-
"os/exec"
19-
18+
"github.com/cli/safeexec"
2019
"github.com/gohugoio/hugo/identity"
2120
"github.com/gohugoio/hugo/markup/internal"
2221

@@ -65,7 +64,7 @@ func (c *pandocConverter) getPandocContent(src []byte, ctx converter.DocumentCon
6564
}
6665

6766
func getPandocExecPath() string {
68-
path, err := exec.LookPath("pandoc")
67+
path, err := safeexec.LookPath("pandoc")
6968
if err != nil {
7069
return ""
7170
}

0 commit comments

Comments
 (0)