Skip to content

Commit 56e0fe1

Browse files
committed
fix(exec): deduplicate PATH to prevent exponential explosion on Windows
1 parent 1937082 commit 56e0fe1

1 file changed

Lines changed: 29 additions & 12 deletions

File tree

cmd/23.exec.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,25 +103,42 @@ Examples:
103103
RunE: runExec,
104104
}
105105

106+
func deduplicatePathString(pathStr string) string {
107+
parts := strings.Split(pathStr, string(os.PathListSeparator))
108+
var result []string
109+
seen := make(map[string]bool)
110+
for _, p := range parts {
111+
if p == "" {
112+
continue
113+
}
114+
// On Windows, paths are case-insensitive, so we use lower case for deduplication.
115+
key := p
116+
if runtime.GOOS == "windows" {
117+
key = strings.ToLower(p)
118+
}
119+
if !seen[key] {
120+
seen[key] = true
121+
result = append(result, p)
122+
}
123+
}
124+
return strings.Join(result, string(os.PathListSeparator))
125+
}
126+
106127
// mergeEnvMaps merges src into dst. PATH values are combined additively so
107128
// that each tool's bin directory is prepended in order.
108129
func mergeEnvMaps(dst, src map[string]string) {
109130
for k, v := range src {
110131
if k == "PATH" {
111132
if dst["PATH"] != "" {
112-
dst["PATH"] = v + string(os.PathListSeparator) + dst["PATH"]
133+
dst["PATH"] = deduplicatePathString(v + string(os.PathListSeparator) + dst["PATH"])
113134
} else {
114-
dst["PATH"] = v
135+
dst["PATH"] = deduplicatePathString(v)
115136
}
116137
} else if k == "NODE_PATH" {
117138
if dst["NODE_PATH"] != "" {
118-
// Avoid duplicates
119-
sep := string(os.PathListSeparator)
120-
if !strings.Contains(dst["NODE_PATH"]+sep, v+sep) {
121-
dst["NODE_PATH"] = dst["NODE_PATH"] + sep + v
122-
}
139+
dst["NODE_PATH"] = deduplicatePathString(dst["NODE_PATH"] + string(os.PathListSeparator) + v)
123140
} else {
124-
dst["NODE_PATH"] = v
141+
dst["NODE_PATH"] = deduplicatePathString(v)
125142
}
126143
} else {
127144
dst[k] = v
@@ -137,16 +154,16 @@ func applyEnvMap(envMap map[string]string) {
137154
if k == "PATH" && v != "" {
138155
existing := os.Getenv("PATH")
139156
if existing != "" {
140-
os.Setenv(k, v+string(os.PathListSeparator)+existing)
157+
os.Setenv(k, deduplicatePathString(v+string(os.PathListSeparator)+existing))
141158
} else {
142-
os.Setenv(k, v)
159+
os.Setenv(k, deduplicatePathString(v))
143160
}
144161
} else if k == "NODE_PATH" && v != "" {
145162
existing := os.Getenv("NODE_PATH")
146163
if existing != "" {
147-
os.Setenv(k, existing+string(os.PathListSeparator)+v)
164+
os.Setenv(k, deduplicatePathString(existing+string(os.PathListSeparator)+v))
148165
} else {
149-
os.Setenv(k, v)
166+
os.Setenv(k, deduplicatePathString(v))
150167
}
151168
} else if v != "" {
152169
os.Setenv(k, v)

0 commit comments

Comments
 (0)