Skip to content

Commit cf5aa33

Browse files
authored
fix(nodejs): fix infinite loop when package link from package-lock.json file is broken (#6858)
1 parent 8491469 commit cf5aa33

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

pkg/dependency/parser/nodejs/npm/parse.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,16 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype
194194
// node_modules/func1 -> link to target
195195
// see `package-lock_v3_with_workspace.json` to better understanding
196196
func (p *Parser) resolveLinks(packages map[string]Package) {
197-
links := lo.PickBy(packages, func(_ string, pkg Package) bool {
198-
return pkg.Link
197+
links := lo.PickBy(packages, func(pkgPath string, pkg Package) bool {
198+
if !pkg.Link {
199+
return false
200+
}
201+
if pkg.Resolved == "" {
202+
p.logger.Warn("`package-lock.json` contains broken link with empty `resolved` field. This package will be skipped to avoid receiving an empty package", log.String("pkg", pkgPath))
203+
delete(packages, pkgPath)
204+
return false
205+
}
206+
return true
199207
})
200208
// Early return
201209
if len(links) == 0 {
@@ -208,7 +216,9 @@ func (p *Parser) resolveLinks(packages map[string]Package) {
208216
}
209217

210218
workspaces := rootPkg.Workspaces
211-
for pkgPath, pkg := range packages {
219+
// Changing the map during the map iteration causes unexpected behavior,
220+
// so we need to iterate over the cloned `packages` map, but change the original `packages` map.
221+
for pkgPath, pkg := range maps.Clone(packages) {
212222
for linkPath, link := range links {
213223
if !strings.HasPrefix(pkgPath, link.Resolved) {
214224
continue

pkg/dependency/parser/nodejs/npm/parse_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ func TestParse(t *testing.T) {
5353
want: npmV3WithoutRootDepsField,
5454
wantDeps: npmV3WithoutRootDepsFieldDeps,
5555
},
56+
{
57+
name: "lock version v3 with broken link",
58+
file: "testdata/package-lock_v3_broken_link.json",
59+
want: nil,
60+
wantDeps: nil,
61+
},
5662
}
5763

5864
for _, tt := range tests {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "node_v3_without_direct_deps",
3+
"version": "1.0.0",
4+
"lockfileVersion": 3,
5+
"requires": true,
6+
"packages": {
7+
"": {
8+
"name": "node_v3_without_direct_deps",
9+
"version": "1.0.0",
10+
"license": "ISC"
11+
},
12+
"functions/func1": {
13+
"version": "1.0.0",
14+
"license": "ISC",
15+
"dependencies": {
16+
"debug": "^2.6.9"
17+
}
18+
},
19+
"node_modules/func1": {
20+
"resolved": "",
21+
"link": true
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)