Skip to content

Commit 7dd9fde

Browse files
committed
fix: normalize paths to prevent concatenation on Windows
Fixes #5673 On Windows, when using absolute paths like C:\path\to\dir, the path could be incorrectly concatenated, resulting in: C:\working\dir\C:\path\to\dir\file This fix applies filepath.Abs() and filepath.Clean() to normalize the path before using it, ensuring absolute paths are handled correctly on all platforms. Changes: - Apply filepath.Abs() to convert relative paths to absolute - Apply filepath.Clean() to remove redundant separators and resolve .. - Add tests for absolute paths, complex paths with .., and paths with redundant separators to verify normalization works correctly The tests use actual 'flux build kustomization' commands with: 1. Absolute paths (prevents concatenation bugs) 2. Paths with parent directory (..) references 3. Paths with redundant separators (//) All tests verify the command produces correct output, ensuring the path normalization fix works as expected. Signed-off-by: Sibasis Padhi <[email protected]>
1 parent f2f7d59 commit 7dd9fde

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

cmd/flux/build_kustomization.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"os"
2222
"os/signal"
23+
"path/filepath"
2324

2425
"github.com/spf13/cobra"
2526

@@ -97,6 +98,13 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
9798
return fmt.Errorf("invalid resource path %q", buildKsArgs.path)
9899
}
99100

101+
// Normalize the path to handle Windows absolute and relative paths correctly
102+
buildKsArgs.path, err = filepath.Abs(buildKsArgs.path)
103+
if err != nil {
104+
return fmt.Errorf("failed to resolve absolute path: %w", err)
105+
}
106+
buildKsArgs.path = filepath.Clean(buildKsArgs.path)
107+
100108
if fs, err := os.Stat(buildKsArgs.path); err != nil || !fs.IsDir() {
101109
return fmt.Errorf("invalid resource path %q", buildKsArgs.path)
102110
}

cmd/flux/build_kustomization_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,65 @@ spec:
218218
})
219219
}
220220
}
221+
222+
// TestBuildKustomizationPathNormalization verifies that absolute and complex
223+
// paths are normalized to prevent path concatenation bugs (issue #5673).
224+
// Without normalization, paths could be duplicated like: /path/test/path/test/file
225+
func TestBuildKustomizationPathNormalization(t *testing.T) {
226+
// Get absolute path to testdata to test absolute path handling
227+
absTestDataPath, err := filepath.Abs("testdata/build-kustomization/podinfo")
228+
if err != nil {
229+
t.Fatalf("failed to get absolute path: %v", err)
230+
}
231+
232+
tests := []struct {
233+
name string
234+
args string
235+
resultFile string
236+
assertFunc string
237+
}{
238+
{
239+
name: "build with absolute path",
240+
args: "build kustomization podinfo --path " + absTestDataPath,
241+
resultFile: "./testdata/build-kustomization/podinfo-result.yaml",
242+
assertFunc: "assertGoldenTemplateFile",
243+
},
244+
{
245+
name: "build with complex relative path (parent dir)",
246+
args: "build kustomization podinfo --path ./testdata/build-kustomization/../build-kustomization/podinfo",
247+
resultFile: "./testdata/build-kustomization/podinfo-result.yaml",
248+
assertFunc: "assertGoldenTemplateFile",
249+
},
250+
{
251+
name: "build with path containing redundant separators",
252+
args: "build kustomization podinfo --path ./testdata//build-kustomization//podinfo",
253+
resultFile: "./testdata/build-kustomization/podinfo-result.yaml",
254+
assertFunc: "assertGoldenTemplateFile",
255+
},
256+
}
257+
258+
tmpl := map[string]string{
259+
"fluxns": allocateNamespace("flux-system"),
260+
}
261+
setup(t, tmpl)
262+
263+
for _, tt := range tests {
264+
t.Run(tt.name, func(t *testing.T) {
265+
var assert assertFunc
266+
267+
switch tt.assertFunc {
268+
case "assertGoldenTemplateFile":
269+
assert = assertGoldenTemplateFile(tt.resultFile, tmpl)
270+
case "assertError":
271+
assert = assertError(tt.resultFile)
272+
}
273+
274+
cmd := cmdTestCase{
275+
args: tt.args + " -n " + tmpl["fluxns"],
276+
assert: assert,
277+
}
278+
279+
cmd.runTestCmd(t)
280+
})
281+
}
282+
}

0 commit comments

Comments
 (0)