diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index d5a0f506f10d..cac0e9e57da5 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -2052,6 +2052,8 @@ func uppercaseCmd(str string) string { } func processCmdEnv(shlex *shell.Lex, cmd string, env shell.EnvGetter) string { + // since shlex is tripping off backslashes + cmd = strings.ReplaceAll(cmd, "\\", "\\\\") w, _, err := shlex.ProcessWord(cmd, env) if err != nil { return cmd diff --git a/frontend/dockerfile/dockerfile2llb/convert_test.go b/frontend/dockerfile/dockerfile2llb/convert_test.go index 80f4d895fb72..bfa5a29930fe 100644 --- a/frontend/dockerfile/dockerfile2llb/convert_test.go +++ b/frontend/dockerfile/dockerfile2llb/convert_test.go @@ -230,3 +230,54 @@ RUN echo bar assert.Equal(t, []digest.Digest{"sha256:2e112031b4b923a873c8b3d685d48037e4d5ccd967b658743d93a6e56c3064b9"}, baseImg.RootFS.DiffIDs) assert.Equal(t, "2024-01-17 21:49:12 +0000 UTC", baseImg.Created.String()) } + +// MockEnvGetter is a mock implementation of shell.EnvGetter for testing purposes. +type MockEnvGetter struct{} + +func (m *MockEnvGetter) Get(key string) (string, bool) { + return "", false +} + +func (m *MockEnvGetter) Keys() []string { + return []string{} +} + +func TestProcessCmdEnv(t *testing.T) { + tests := []struct { + name string + cmd string + expected string + }{ + { + name: "basic command without backslashes", + cmd: "echo hello world", + expected: "echo hello world", + }, + { + name: "command with single backslashes", + cmd: `echo C:\hello\world`, + expected: `echo C:\hello\world`, + }, + { + name: "command with multiple backslashes", + cmd: `echo C:\\hello\\world`, + expected: `echo C:\\hello\\world`, + }, + { + name: "command with mixed content", + cmd: `echo "C:\hello\world" && dir C:\test\path`, + expected: `echo "C:\hello\world" && dir C:\test\path`, + }, + } + + shlex := shell.NewLex('\\') + shlex.RawQuotes = true + env := &MockEnvGetter{} + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := processCmdEnv(shlex, tt.cmd, env) + assert.Equal(t, tt.expected, result) + }) + } +}