@@ -13,14 +13,16 @@ def quote_if_needed(row):
13
13
if row != "true" and row != "false" :
14
14
return "\" " + row + "\" "
15
15
# subtypes column
16
- return row
16
+ return row [ 0 ]. upper () + row [ 1 :]
17
17
18
18
def parseData (data ):
19
- rows = ""
20
- for (row ) in data :
19
+ rows = { }
20
+
21
+ for row in data :
21
22
d = row [0 ].split (';' )
23
+ namespace = d [0 ]
22
24
d = map (quote_if_needed , d )
23
- rows += " - [" + ', ' .join (d ) + ']\n '
25
+ helpers . insert_update ( rows , namespace , " - [" + ', ' .join (d ) + ']\n ' )
24
26
25
27
return rows
26
28
@@ -38,12 +40,10 @@ def __init__ (self, language):
38
40
39
41
def printHelp (self ):
40
42
print (f"""Usage:
41
- python3 GenerateFlowModel.py <library-database> <outputYml> [<friendlyFrameworkName>] [--with-sinks] [--with-sources] [--with-summaries] [--with-typebased-summaries] [--dry-run]
43
+ python3 GenerateFlowModel.py <library-database> [--with-sinks] [--with-sources] [--with-summaries] [--with-typebased-summaries] [--dry-run]
42
44
43
45
This generates summary, source and sink models for the code in the database.
44
- The files will be placed in `{ self .language } /ql/lib/ext/generated/<outputYml>.model.yml` where
45
- outputYml is the name (and path) of the output YAML file. Usually, models are grouped by their
46
- respective frameworks.
46
+ The files will be placed in `{ self .language } /ql/lib/ext/generated/`.
47
47
48
48
Which models are generated is controlled by the flags:
49
49
--with-sinks
@@ -57,28 +57,18 @@ def printHelp(self):
57
57
58
58
Example invocations:
59
59
$ python3 GenerateFlowModel.py /tmp/dbs/my_library_db mylibrary
60
- $ python3 GenerateFlowModel.py /tmp/dbs/my_library_db mylibrary "Friendly Name of Framework"
60
+ $ python3 GenerateFlowModel.py /tmp/dbs/my_library_db mylibrary
61
61
$ python3 GenerateFlowModel.py /tmp/dbs/my_library_db --with-sinks
62
62
63
63
Requirements: `codeql` should both appear on your path.
64
64
""" )
65
65
66
66
67
- def setenvironment (self , target , database , friendlyName ):
67
+ def setenvironment (self , database ):
68
68
self .codeQlRoot = subprocess .check_output (["git" , "rev-parse" , "--show-toplevel" ]).decode ("utf-8" ).strip ()
69
- if not target .endswith (".model.yml" ):
70
- target += ".model.yml"
71
- filename = os .path .basename (target )
72
- if friendlyName is not None :
73
- self .friendlyname = friendlyName
74
- else :
75
- self .friendlyname = filename [:- 10 ]
76
- self .shortname = filename [:- 10 ]
77
69
self .database = database
78
70
self .generatedFrameworks = os .path .join (
79
71
self .codeQlRoot , f"{ self .language } /ql/lib/ext/generated/" )
80
- self .frameworkTarget = os .path .join (self .generatedFrameworks , filename )
81
- self .typeBasedFrameworkTarget = os .path .join (self .generatedFrameworks , "TypeBased" + filename )
82
72
self .workDir = tempfile .mkdtemp ()
83
73
os .makedirs (self .generatedFrameworks , exist_ok = True )
84
74
@@ -117,15 +107,11 @@ def make(language):
117
107
if not generator .generateSinks and not generator .generateSources and not generator .generateSummaries and not generator .generateNeutrals and not generator .generateTypeBasedSummaries :
118
108
generator .generateSinks = generator .generateSources = generator .generateSummaries = generator .generateNeutrals = True
119
109
120
- if len (sys .argv ) < 3 or len ( sys . argv ) > 4 :
110
+ if len (sys .argv ) < 2 :
121
111
generator .printHelp ()
122
112
sys .exit (1 )
123
113
124
- friendlyName = None
125
- if len (sys .argv ) == 4 :
126
- friendlyName = sys .argv [3 ]
127
-
128
- generator .setenvironment (sys .argv [2 ], sys .argv [1 ], friendlyName )
114
+ generator .setenvironment (sys .argv [1 ])
129
115
return generator
130
116
131
117
@@ -141,58 +127,57 @@ def runQuery(self, query):
141
127
142
128
143
129
def asAddsTo (self , rows , predicate ):
144
- if rows . strip () == "" :
145
- return ""
146
- return helpers .addsToTemplate .format (f"codeql/{ self .language } -all" , predicate , rows )
147
-
130
+ extensions = { }
131
+ for key in rows :
132
+ extensions [ key ] = helpers .addsToTemplate .format (f"codeql/{ self .language } -all" , predicate , rows [ key ] )
133
+ return extensions
148
134
149
135
def getAddsTo (self , query , predicate ):
150
136
data = self .runQuery (query )
151
137
rows = parseData (data )
152
138
return self .asAddsTo (rows , predicate )
153
139
154
-
155
140
def makeContent (self ):
156
141
if self .generateSummaries :
157
142
summaryAddsTo = self .getAddsTo ("CaptureSummaryModels.ql" , helpers .summaryModelPredicate )
158
143
else :
159
- summaryAddsTo = ""
144
+ summaryAddsTo = { }
160
145
161
146
if self .generateSinks :
162
147
sinkAddsTo = self .getAddsTo ("CaptureSinkModels.ql" , helpers .sinkModelPredicate )
163
148
else :
164
- sinkAddsTo = ""
149
+ sinkAddsTo = { }
165
150
166
151
if self .generateSources :
167
152
sourceAddsTo = self .getAddsTo ("CaptureSourceModels.ql" , helpers .sourceModelPredicate )
168
153
else :
169
- sourceAddsTo = ""
154
+ sourceAddsTo = {}
170
155
171
156
if self .generateNeutrals :
172
157
neutralAddsTo = self .getAddsTo ("CaptureNeutralModels.ql" , helpers .neutralModelPredicate )
173
158
else :
174
- neutralAddsTo = ""
159
+ neutralAddsTo = { }
175
160
176
- return f"""# THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT.
177
- # Definitions of models for the { self .friendlyname } framework.
178
- extensions:
179
- { sinkAddsTo } { sourceAddsTo } { summaryAddsTo } { neutralAddsTo } """
161
+ return helpers .merge (summaryAddsTo , sinkAddsTo , sourceAddsTo , neutralAddsTo )
180
162
181
163
def makeTypeBasedContent (self ):
182
164
if self .generateTypeBasedSummaries :
183
- typeBasedSummaryAddsTo = self .getAddsTo ("CaptureTypeBasedSummaryModels.ql" , "extSummaryModel" )
165
+ typeBasedSummaryAddsTo = self .getAddsTo ("CaptureTypeBasedSummaryModels.ql" , helpers . summaryModelPredicate )
184
166
else :
185
- typeBasedSummaryAddsTo = ""
167
+ typeBasedSummaryAddsTo = { }
186
168
187
- return f"""# THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT.
188
- # Definitions of type based summaries in the { self .friendlyname } framework.
189
- extensions:
190
- { typeBasedSummaryAddsTo } """
169
+ return typeBasedSummaryAddsTo
191
170
192
- def save (self , content , target ):
193
- with open (target , "w" ) as targetYml :
194
- targetYml .write (content )
195
- print ("Models as data extensions written to " + target )
171
+ def save (self , extensions , extension ):
172
+ # Create a file for each namespace and save models.
173
+ extensionTemplate = """# THIS FILE IS AN AUTO-GENERATED MODELS AS DATA FILE. DO NOT EDIT.
174
+ extensions:
175
+ {0}"""
176
+ for entry in extensions :
177
+ target = os .path .join (self .generatedFrameworks , entry + extension )
178
+ with open (target , "w" ) as f :
179
+ f .write (extensionTemplate .format (extensions [entry ]))
180
+ print ("Models as data extensions written to " + target )
196
181
197
182
198
183
def run (self ):
@@ -204,7 +189,7 @@ def run(self):
204
189
sys .exit (0 )
205
190
206
191
if self .generateSinks or self .generateSinks or self .generateSummaries :
207
- self .save (content , self . frameworkTarget )
192
+ self .save (content , ".model.yml" )
208
193
209
194
if self .generateTypeBasedSummaries :
210
- self .save (typeBasedContent , self . typeBasedFrameworkTarget )
195
+ self .save (typeBasedContent , ".typebased.model.yml" )
0 commit comments