@@ -5,13 +5,11 @@ import (
55 "io"
66 "os"
77 "path/filepath"
8- "regexp"
98 "strings"
109
1110 "github.com/iseki0/go-yarnlock"
1211 "github.com/murphysecurity/murphysec/infra/logctx"
1312 "github.com/murphysecurity/murphysec/module/pkgjs"
14- "github.com/murphysecurity/murphysec/module/pnpm/shared"
1513 "github.com/pkg/errors"
1614)
1715
@@ -38,10 +36,7 @@ func yarnFallback(dir string) ([]Dep, error) {
3836 }
3937
4038 for k , v := range distinct {
41- var di Dep
42- di .Name = k
43- di .Version = v
44- rs = append (rs , di )
39+ rs = append (rs , Dep {Name : k , Version : v })
4540 }
4641 return rs , nil
4742}
@@ -58,12 +53,16 @@ func analyzeYarnDep(ctx context.Context, dir string) (r []Dep, e error) {
5853 if e != nil {
5954 return nil , errors .Wrap (e , "Read yarn.lock failed." )
6055 }
56+
6157 var lockfile yarnlock.LockFile
62- var newLock = false
63- if strings .Contains (string (data ), "__metadata:" ) {
64- lockfile , e = parseYarnLockYaml (string (data ))
65- delete (lockfile , "__metadata" )
66- newLock = true
58+ var berryData * berryLockData
59+ newLock := strings .Contains (string (data ), "__metadata:" )
60+ if newLock {
61+ berryData , e = parseYarnLockYamlWithIndex (string (data ))
62+ if e == nil {
63+ lockfile = berryData .Lockfile
64+ delete (lockfile , "__metadata" )
65+ }
6766 } else {
6867 lockfile , e = yarnlock .ParseLockFileData (data )
6968 }
@@ -81,134 +80,7 @@ func analyzeYarnDep(ctx context.Context, dir string) (r []Dep, e error) {
8180 for name , ver := range pkg .DevDependencies {
8281 pkg .DevDependencies [name ] = "npm:" + ver
8382 }
83+ return buildDepTreeBerry (berryData , pkg ), nil
8484 }
8585 return buildDepTree (lockfile , pkg ), nil
8686}
87-
88- func parseYarnLockYaml (text string ) (r yarnlock.LockFile , e error ) {
89- type Element struct {
90- Version string `yaml:"version"`
91- Dependencies map [string ]string `yaml:"dependencies"`
92- }
93- var pkgs map [string ]Element
94- e = shared .ParseYaml ([]byte (text ), & pkgs )
95- if e != nil {
96- return
97- }
98- r = make (yarnlock.LockFile )
99- for key , value := range pkgs {
100- for keyEl := range strings .SplitSeq (key , ", " ) {
101- r [keyEl ] = yarnlock.LockFileEntry {
102- Version : value .Version ,
103- Dependencies : value .Dependencies ,
104- }
105- }
106- }
107- return
108- }
109-
110- func buildDepTree (lkFile yarnlock.LockFile , pkg * pkgjs.Pkg ) []Dep {
111- type id struct {
112- name string
113- version string
114- }
115- var rs []Dep
116- repeatedElement := map [id ]struct {}{}
117- for n , v := range pkg .Dependencies {
118- node := _buildDepTree (lkFile , n + "@" + v , map [string ]struct {}{}, 5 )
119- if node == nil {
120- continue
121- }
122- key := id {node .Name , node .Version }
123- if _ , ok := repeatedElement [key ]; ok {
124- continue
125- }
126- repeatedElement [key ] = struct {}{}
127- rs = append (rs , * node )
128- }
129- for n , v := range pkg .DevDependencies {
130- node := _buildDepTree (lkFile , n + "@" + v , map [string ]struct {}{}, 5 )
131- if node == nil {
132- continue
133- }
134- key := id {node .Name , node .Version }
135- if _ , ok := repeatedElement [key ]; ok {
136- continue
137- }
138- repeatedElement [key ] = struct {}{}
139- rs = append (rs , * node )
140- }
141- return rs
142- }
143-
144- var versionNpmPattern = regexp .MustCompile (`^npm:(.+?)@(.+)` )
145-
146- func _buildDepTree (lkFile yarnlock.LockFile , element string , visitedKey map [string ]struct {}, depth int ) * Dep {
147- if depth < 0 {
148- return nil
149- }
150- {
151- // avoid circle dependency
152- if _ , ok := visitedKey [element ]; ok {
153- return nil
154- }
155- visitedKey [element ] = struct {}{}
156- defer delete (visitedKey , element )
157- }
158- info , ok := lkFile [element ]
159- if ! ok {
160- return nil
161- }
162- pkgName , pkgVer := parsePkgName (element )
163- if pkgName == "" || pkgVer == "" {
164- return nil
165- }
166- node := & Dep {
167- Name : pkgName ,
168- Version : info .Version , // use real version
169- }
170- type id struct {
171- name string
172- version string
173- }
174- repeatedElement := map [id ]struct {}{}
175- for childComp , childVer := range lkFile [element ].Dependencies {
176- childKey := childComp + "@" + childVer
177- c := _buildDepTree (lkFile , childKey , visitedKey , depth - 1 )
178- if c == nil {
179- continue
180- }
181- if _ , ok := repeatedElement [id {c .Name , c .Version }]; ok {
182- continue
183- }
184- repeatedElement [id {c .Name , c .Version }] = struct {}{}
185- node .Children = append (node .Children , * c )
186- }
187- for childComp , childVer := range lkFile [element ].OptionalDependencies {
188- childKey := childComp + "@" + childVer
189- c := _buildDepTree (lkFile , childKey , visitedKey , depth - 1 )
190- if c == nil {
191- continue
192- }
193- if _ , ok := repeatedElement [id {c .Name , c .Version }]; ok {
194- continue
195- }
196- repeatedElement [id {c .Name , c .Version }] = struct {}{}
197- node .Children = append (node .Children , * c )
198- }
199- return node
200- }
201-
202- var __parsePkgNamePattern = regexp .MustCompile ("(@?[^@]+)@(.+)" )
203-
204- func parsePkgName (input string ) (pkgName string , pkgVersion string ) {
205- m := __parsePkgNamePattern .FindStringSubmatch (input )
206- if m == nil {
207- return "" , ""
208- } else {
209- if m := versionNpmPattern .FindStringSubmatch (m [2 ]); m != nil {
210- return m [1 ], m [2 ]
211- }
212- return m [1 ], m [2 ]
213- }
214- }
0 commit comments