Merge ~alexmurray/ubuntu-cve-tracker:misc-cve-lib-and-check-syntax-cleanups into ubuntu-cve-tracker:master
- Git
- lp:~alexmurray/ubuntu-cve-tracker
- misc-cve-lib-and-check-syntax-cleanups
- Merge into master
Proposed by
Alex Murray
Status: | Merged |
---|---|
Merged at revision: | b7100a0074408e315ffae2395875e69036d3044d |
Proposed branch: | ~alexmurray/ubuntu-cve-tracker:misc-cve-lib-and-check-syntax-cleanups |
Merge into: | ubuntu-cve-tracker:master |
Diff against target: |
434 lines (+94/-68) 3 files modified
scripts/check-syntax (+15/-1) scripts/cve-mode.el (+2/-2) scripts/cve_lib.py (+77/-65) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Eduardo Barretto | Approve | ||
Review via email: mp+440925@code.launchpad.net |
Commit message
Description of the change
A bunch of miscellaneous fixups to get some bits of check-syntax working betterer
To post a comment you must log in.
Revision history for this message
Seth Arnold (seth-arnold) wrote : | # |
Revision history for this message
Alex Murray (alexmurray) wrote : | # |
Thanks Seth - not sure I understand your comment so if you could help explain it for me that would be great.
Revision history for this message
Seth Arnold (seth-arnold) : | # |
Revision history for this message
Alex Murray (alexmurray) : | # |
Revision history for this message
Steve Beattie (sbeattie) : | # |
Revision history for this message
Eduardo Barretto (ebarretto) wrote : | # |
hey Alex, is this still needed?
review:
Needs Information
Revision history for this message
Alex Murray (alexmurray) wrote : | # |
Added --stdin as first class argument to check-syntax and fixed up other bits. Yes this is still needed. As can be seen the check-syntax lpci job fails as expected currently showing check-syntax still works for the regular use-case as well as this new --stdin one (which is used by the flymake integration for emacs in cve-mode.el)
Revision history for this message
Alex Murray (alexmurray) wrote : | # |
Any chance to get a review on this? Otherwise I'll look to merge it tomorrow during CVE triage.
Revision history for this message
Eduardo Barretto (ebarretto) wrote : | # |
cve_lib and check-syntax changes lgtm!
thanks!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/scripts/check-syntax b/scripts/check-syntax | |||
2 | index f89a0e4..7d401f6 100755 | |||
3 | --- a/scripts/check-syntax | |||
4 | +++ b/scripts/check-syntax | |||
5 | @@ -261,6 +261,13 @@ parser.add_option( | |||
6 | 261 | help="Number of jobs to run simultaneously (default: %d)" % multiprocessing.cpu_count(), | 261 | help="Number of jobs to run simultaneously (default: %d)" % multiprocessing.cpu_count(), |
7 | 262 | default=multiprocessing.cpu_count(), | 262 | default=multiprocessing.cpu_count(), |
8 | 263 | ) | 263 | ) |
9 | 264 | parser.add_option( | ||
10 | 265 | "--stdin", | ||
11 | 266 | help="Check the contents of stdin instead of a filelist or modified files etc", | ||
12 | 267 | action="store_true", | ||
13 | 268 | default=False, | ||
14 | 269 | ) | ||
15 | 270 | |||
16 | 264 | # parser.add_option("-c", "--cna", help="Ensure every CVE assigned by Canonical's CNA has an entry", action='store_true') | 271 | # parser.add_option("-c", "--cna", help="Ensure every CVE assigned by Canonical's CNA has an entry", action='store_true') |
17 | 265 | (opt, args) = parser.parse_args() | 272 | (opt, args) = parser.parse_args() |
18 | 266 | 273 | ||
19 | @@ -304,7 +311,11 @@ if os.path.islink(cve_lib.embargoed_dir): | |||
20 | 304 | debug("check_dirs %s" % check_dirs) | 311 | debug("check_dirs %s" % check_dirs) |
21 | 305 | 312 | ||
22 | 306 | all_files = True | 313 | all_files = True |
24 | 307 | if len(args) == 0: | 314 | if opt.stdin: |
25 | 315 | debug("Using /dev/stdin as input") | ||
26 | 316 | args = ["/dev/stdin"] | ||
27 | 317 | all_files = False | ||
28 | 318 | elif len(args) == 0: | ||
29 | 308 | if opt.filelist: | 319 | if opt.filelist: |
30 | 309 | debug("Using filelist %s" % opt.filelist) | 320 | debug("Using filelist %s" % opt.filelist) |
31 | 310 | 321 | ||
32 | @@ -525,6 +536,9 @@ def check_cve(cve): | |||
33 | 525 | except ValueError as e: | 536 | except ValueError as e: |
34 | 526 | print(e, file=sys.stderr) | 537 | print(e, file=sys.stderr) |
35 | 527 | return False | 538 | return False |
36 | 539 | # get the real CVE if we are using stdin | ||
37 | 540 | if opt.stdin: | ||
38 | 541 | cve = data["Candidate"] | ||
39 | 528 | if cve in ignored: | 542 | if cve in ignored: |
40 | 529 | print( | 543 | print( |
41 | 530 | "%s: %d: duplicate CVE found in not-for-us.txt" % (cvepath, 1), | 544 | "%s: %d: duplicate CVE found in not-for-us.txt" % (cvepath, 1), |
42 | diff --git a/scripts/cve-mode.el b/scripts/cve-mode.el | |||
43 | index b8d8230..4f5797e 100644 | |||
44 | --- a/scripts/cve-mode.el | |||
45 | +++ b/scripts/cve-mode.el | |||
46 | @@ -683,7 +683,7 @@ cross boundaries of block literals." | |||
47 | 683 | :name "cve-mode-flymake" :noquery t :connection-type 'pipe | 683 | :name "cve-mode-flymake" :noquery t :connection-type 'pipe |
48 | 684 | ;; Make output go to a temporary buffer. | 684 | ;; Make output go to a temporary buffer. |
49 | 685 | :buffer (generate-new-buffer " *cve-mode-flymake*") | 685 | :buffer (generate-new-buffer " *cve-mode-flymake*") |
51 | 686 | :command `(,cve-mode--check-syntax-executable "/dev/stdin") | 686 | :command `(,cve-mode--check-syntax-executable "--stdin") |
52 | 687 | :sentinel | 687 | :sentinel |
53 | 688 | (lambda (proc _event) | 688 | (lambda (proc _event) |
54 | 689 | (when (memq (process-status proc) '(exit signal)) | 689 | (when (memq (process-status proc) '(exit signal)) |
55 | @@ -723,7 +723,7 @@ cross boundaries of block literals." | |||
56 | 723 | 723 | ||
57 | 724 | ;;;###autoload | 724 | ;;;###autoload |
58 | 725 | (defun cve-mode-setup-flymake-backend () | 725 | (defun cve-mode-setup-flymake-backend () |
60 | 726 | "Setuo the `flymake' backend for `cve-mode'." | 726 | "Setup the `flymake' backend for `cve-mode'." |
61 | 727 | (add-hook 'flymake-diagnostic-functions 'cve-mode-flymake nil t)) | 727 | (add-hook 'flymake-diagnostic-functions 'cve-mode-flymake nil t)) |
62 | 728 | 728 | ||
63 | 729 | ;;;###autoload | 729 | ;;;###autoload |
64 | diff --git a/scripts/cve_lib.py b/scripts/cve_lib.py | |||
65 | index 416d5f7..811ea55 100755 | |||
66 | --- a/scripts/cve_lib.py | |||
67 | +++ b/scripts/cve_lib.py | |||
68 | @@ -980,8 +980,8 @@ def find_external_subproject_cves(cve): | |||
69 | 980 | # top-level project directory even though this is preferred | 980 | # top-level project directory even though this is preferred |
70 | 981 | for d in [get_external_subproject_cve_dir(rel), | 981 | for d in [get_external_subproject_cve_dir(rel), |
71 | 982 | get_external_subproject_dir(rel)]: | 982 | get_external_subproject_dir(rel)]: |
74 | 983 | path = os.path.join(d, cve) | 983 | path = os.path.realpath(os.path.join(d, cve)) |
75 | 984 | if os.path.exists(path): | 984 | if os.path.exists(path) and path not in cves: |
76 | 985 | cves.append(path) | 985 | cves.append(path) |
77 | 986 | return cves | 986 | return cves |
78 | 987 | 987 | ||
79 | @@ -1076,24 +1076,26 @@ def load_external_subprojects(strict=False): | |||
80 | 1076 | if project: | 1076 | if project: |
81 | 1077 | subprojects[subproject].setdefault("customer", project) | 1077 | subprojects[subproject].setdefault("customer", project) |
82 | 1078 | 1078 | ||
84 | 1079 | load_external_subprojects() | 1079 | # now ensure they are consistent |
85 | 1080 | global devel_release | ||
86 | 1081 | for release in subprojects: | ||
87 | 1082 | details = subprojects[release] | ||
88 | 1083 | rel = release_alias(release) | ||
89 | 1084 | # prefer the alias name | ||
90 | 1085 | all_releases.append(rel) | ||
91 | 1086 | if details["eol"]: | ||
92 | 1087 | eol_releases.append(rel) | ||
93 | 1088 | if "devel" in details and details["devel"]: | ||
94 | 1089 | if devel_release != "": | ||
95 | 1090 | raise ValueError("there can be only one ⚔ devel") | ||
96 | 1091 | devel_release = rel | ||
97 | 1092 | # ubuntu specific releases | ||
98 | 1093 | product, _ = product_series(release) | ||
99 | 1094 | if product == PRODUCT_UBUNTU: | ||
100 | 1095 | releases.append(rel) | ||
101 | 1080 | 1096 | ||
102 | 1081 | for release in subprojects: | ||
103 | 1082 | details = subprojects[release] | ||
104 | 1083 | rel = release_alias(release) | ||
105 | 1084 | # prefer the alias name | ||
106 | 1085 | all_releases.append(rel) | ||
107 | 1086 | if details["eol"]: | ||
108 | 1087 | eol_releases.append(rel) | ||
109 | 1088 | if "devel" in details and details["devel"]: | ||
110 | 1089 | if devel_release != "": | ||
111 | 1090 | raise ValueError("there can be only one ⚔ devel") | ||
112 | 1091 | devel_release = rel | ||
113 | 1092 | # ubuntu specific releases | ||
114 | 1093 | product, series = product_series(release) | ||
115 | 1094 | if product == PRODUCT_UBUNTU: | ||
116 | 1095 | releases.append(rel) | ||
117 | 1096 | 1097 | ||
118 | 1098 | load_external_subprojects() | ||
119 | 1097 | 1099 | ||
120 | 1098 | def release_sort(release_list): | 1100 | def release_sort(release_list): |
121 | 1099 | '''takes a list of release names and sorts them in release order | 1101 | '''takes a list of release names and sorts them in release order |
122 | @@ -2099,7 +2101,7 @@ def find_cve(cve): | |||
123 | 2099 | # e.g.: git/github.com/gogo/protobuf_gogoprotobuf: needs-triage | 2101 | # e.g.: git/github.com/gogo/protobuf_gogoprotobuf: needs-triage |
124 | 2100 | # This method should keep supporting existing current format: | 2102 | # This method should keep supporting existing current format: |
125 | 2101 | # e.g.: bionic_jackson-databind: needs-triage | 2103 | # e.g.: bionic_jackson-databind: needs-triage |
127 | 2102 | def parse_cve_release_package_field(cve, field, data, value, code, msg, linenum): | 2104 | def parse_cve_release_package_field(cvefile, field, data, value, code, msg, linenum): |
128 | 2103 | package = "" | 2105 | package = "" |
129 | 2104 | release = "" | 2106 | release = "" |
130 | 2105 | state = "" | 2107 | state = "" |
131 | @@ -2107,14 +2109,14 @@ def parse_cve_release_package_field(cve, field, data, value, code, msg, linenum) | |||
132 | 2107 | try: | 2109 | try: |
133 | 2108 | release, package = field.split('_', 1) | 2110 | release, package = field.split('_', 1) |
134 | 2109 | except ValueError: | 2111 | except ValueError: |
136 | 2110 | msg += "%s: %d: bad field with '_': '%s'\n" % (cve, linenum, field) | 2112 | msg += "%s: %d: bad field with '_': '%s'\n" % (cvefile, linenum, field) |
137 | 2111 | code = EXIT_FAIL | 2113 | code = EXIT_FAIL |
138 | 2112 | return False, package, release, state, details, code, msg | 2114 | return False, package, release, state, details, code, msg |
139 | 2113 | 2115 | ||
140 | 2114 | try: | 2116 | try: |
141 | 2115 | info = value.split(' ', 1) | 2117 | info = value.split(' ', 1) |
142 | 2116 | except ValueError: | 2118 | except ValueError: |
144 | 2117 | msg += "%s: %d: missing state for '%s': '%s'\n" % (cve, linenum, field, value) | 2119 | msg += "%s: %d: missing state for '%s': '%s'\n" % (cvefile, linenum, field, value) |
145 | 2118 | code = EXIT_FAIL | 2120 | code = EXIT_FAIL |
146 | 2119 | return False, package, release, state, details, code, msg | 2121 | return False, package, release, state, details, code, msg |
147 | 2120 | 2122 | ||
148 | @@ -2128,7 +2130,7 @@ def parse_cve_release_package_field(cve, field, data, value, code, msg, linenum) | |||
149 | 2128 | details = info[1].strip() | 2130 | details = info[1].strip() |
150 | 2129 | 2131 | ||
151 | 2130 | if details.startswith("["): | 2132 | if details.startswith("["): |
153 | 2131 | msg += "%s: %d: %s has details that starts with a bracket: '%s'\n" % (cve, linenum, field, details) | 2133 | msg += "%s: %d: %s has details that starts with a bracket: '%s'\n" % (cvefile, linenum, field, details) |
154 | 2132 | code = EXIT_FAIL | 2134 | code = EXIT_FAIL |
155 | 2133 | return False, package, release, state, details, code, msg | 2135 | return False, package, release, state, details, code, msg |
156 | 2134 | 2136 | ||
157 | @@ -2144,19 +2146,19 @@ def parse_cve_release_package_field(cve, field, data, value, code, msg, linenum) | |||
158 | 2144 | 2146 | ||
159 | 2145 | valid_states = ['needs-triage', 'needed', 'active', 'pending', 'released', 'deferred', 'DNE', 'ignored', 'not-affected'] | 2147 | valid_states = ['needs-triage', 'needed', 'active', 'pending', 'released', 'deferred', 'DNE', 'ignored', 'not-affected'] |
160 | 2146 | if state not in valid_states: | 2148 | if state not in valid_states: |
162 | 2147 | msg += "%s: %d: %s has unknown state: '%s' (valid states are: %s)\n" % (cve, linenum, field, state, | 2149 | msg += "%s: %d: %s has unknown state: '%s' (valid states are: %s)\n" % (cvefile, linenum, field, state, |
163 | 2148 | ' '.join(valid_states)) | 2150 | ' '.join(valid_states)) |
164 | 2149 | code = EXIT_FAIL | 2151 | code = EXIT_FAIL |
165 | 2150 | return False, package, release, state, details, code, msg | 2152 | return False, package, release, state, details, code, msg |
166 | 2151 | 2153 | ||
167 | 2152 | # Verify "released" kernels have version details | 2154 | # Verify "released" kernels have version details |
168 | 2153 | #if state == 'released' and package in kernel_srcs and details == '': | 2155 | #if state == 'released' and package in kernel_srcs and details == '': |
170 | 2154 | # msg += "%s: %s_%s has state '%s' but lacks version note\n" % (cve, package, release, state) | 2156 | # msg += "%s: %s_%s has state '%s' but lacks version note\n" % (cvefile, package, release, state) |
171 | 2155 | # code = EXIT_FAIL | 2157 | # code = EXIT_FAIL |
172 | 2156 | 2158 | ||
173 | 2157 | # Verify "active" states have an Assignee | 2159 | # Verify "active" states have an Assignee |
174 | 2158 | if state == 'active' and data['Assigned-to'].strip() == "": | 2160 | if state == 'active' and data['Assigned-to'].strip() == "": |
176 | 2159 | msg += "%s: %d: %s has state '%s' but lacks 'Assigned-to'\n" % (cve, linenum, field, state) | 2161 | msg += "%s: %d: %s has state '%s' but lacks 'Assigned-to'\n" % (cvefile, linenum, field, state) |
177 | 2160 | code = EXIT_FAIL | 2162 | code = EXIT_FAIL |
178 | 2161 | return False, package, release, state, details, code, msg | 2163 | return False, package, release, state, details, code, msg |
179 | 2162 | 2164 | ||
180 | @@ -2247,16 +2249,25 @@ def amend_external_subproject_pkg(cve, data, srcmap, amendments, code, msg): | |||
181 | 2247 | return code, msg | 2249 | return code, msg |
182 | 2248 | 2250 | ||
183 | 2249 | if '_' in field: | 2251 | if '_' in field: |
185 | 2250 | success, pkg, release, state, details, code, msg = parse_cve_release_package_field(cve, field, data, value, code, msg, linenum) | 2252 | success, pkg, rel, state, details, code, msg = parse_cve_release_package_field(cve, field, data, value, code, msg, linenum) |
186 | 2251 | if not success: | 2253 | if not success: |
187 | 2252 | return code, msg | 2254 | return code, msg |
188 | 2253 | 2255 | ||
189 | 2256 | canon, _, _, _ = get_subproject_details(rel) | ||
190 | 2257 | if canon is None and rel not in ['upstream', 'devel']: | ||
191 | 2258 | msg += "%s: %d: unknown entry '%s'\n" % (cve, linenum, rel) | ||
192 | 2259 | code = EXIT_FAIL | ||
193 | 2260 | return code, msg | ||
194 | 2254 | data.setdefault("pkgs", dict()) | 2261 | data.setdefault("pkgs", dict()) |
195 | 2255 | data["pkgs"].setdefault(pkg, dict()) | 2262 | data["pkgs"].setdefault(pkg, dict()) |
196 | 2256 | srcmap["pkgs"].setdefault(pkg, dict()) | 2263 | srcmap["pkgs"].setdefault(pkg, dict()) |
200 | 2257 | # override existing release info if it exists | 2264 | if rel in data["pkgs"][pkg]: |
201 | 2258 | data["pkgs"][pkg][release] = [state, details] | 2265 | msg += ("%s: %d: duplicate entry for '%s': original at %s line %d (%s)\n" |
202 | 2259 | srcmap["pkgs"][pkg][release] = (cve, linenum) | 2266 | % (cve, linenum, rel, srcmap['pkgs'][pkg][rel][0], srcmap['pkgs'][pkg][rel][1], data["pkgs"][pkg][rel])) |
203 | 2267 | code = EXIT_FAIL | ||
204 | 2268 | return code, msg | ||
205 | 2269 | data["pkgs"][pkg][rel] = [state, details] | ||
206 | 2270 | srcmap["pkgs"][pkg][rel] = (cve, linenum) | ||
207 | 2260 | 2271 | ||
208 | 2261 | return code, msg | 2272 | return code, msg |
209 | 2262 | 2273 | ||
210 | @@ -2271,7 +2282,7 @@ def load_external_subproject_cve_data(cve, data, srcmap, code, msg): | |||
211 | 2271 | 2282 | ||
212 | 2272 | return code, msg | 2283 | return code, msg |
213 | 2273 | 2284 | ||
215 | 2274 | def load_cve(cve, strict=False, srcmap=None): | 2285 | def load_cve(cvefile, strict=False, srcmap=None): |
216 | 2275 | '''Loads a given CVE into: | 2286 | '''Loads a given CVE into: |
217 | 2276 | dict( fields... | 2287 | dict( fields... |
218 | 2277 | 'pkgs' -> dict( pkg -> dict( release -> (state, details) ) ) | 2288 | 'pkgs' -> dict( pkg -> dict( release -> (state, details) ) ) |
219 | @@ -2298,13 +2309,13 @@ def load_cve(cve, strict=False, srcmap=None): | |||
220 | 2298 | affected = dict() | 2309 | affected = dict() |
221 | 2299 | lastfield = "" | 2310 | lastfield = "" |
222 | 2300 | fields_seen = [] | 2311 | fields_seen = [] |
225 | 2301 | if not os.path.exists(cve): | 2312 | if not os.path.exists(cvefile): |
226 | 2302 | raise ValueError("File does not exist: '%s'" % (cve)) | 2313 | raise ValueError("File does not exist: '%s'" % cvefile) |
227 | 2303 | linenum = 0 | 2314 | linenum = 0 |
228 | 2304 | notes_parser = NotesParser() | 2315 | notes_parser = NotesParser() |
229 | 2305 | priority_reason = {} | 2316 | priority_reason = {} |
230 | 2306 | cvss_entries = [] | 2317 | cvss_entries = [] |
232 | 2307 | with codecs.open(cve, encoding="utf-8") as inF: | 2318 | with codecs.open(cvefile, encoding="utf-8") as inF: |
233 | 2308 | lines = inF.readlines() | 2319 | lines = inF.readlines() |
234 | 2309 | for line in lines: | 2320 | for line in lines: |
235 | 2310 | line = line.rstrip() | 2321 | line = line.rstrip() |
236 | @@ -2317,7 +2328,7 @@ def load_cve(cve, strict=False, srcmap=None): | |||
237 | 2317 | try: | 2328 | try: |
238 | 2318 | # parse Notes properly | 2329 | # parse Notes properly |
239 | 2319 | if lastfield == 'Notes': | 2330 | if lastfield == 'Notes': |
241 | 2320 | code, newmsg = notes_parser.parse_line(cve, line, linenum, code) | 2331 | code, newmsg = notes_parser.parse_line(cvefile, line, linenum, code) |
242 | 2321 | if code != EXIT_OKAY: | 2332 | if code != EXIT_OKAY: |
243 | 2322 | msg += newmsg | 2333 | msg += newmsg |
244 | 2323 | elif lastfield.startswith('Priority'): | 2334 | elif lastfield.startswith('Priority'): |
245 | @@ -2333,9 +2344,9 @@ def load_cve(cve, strict=False, srcmap=None): | |||
246 | 2333 | patch_type = patch_type.strip() | 2344 | patch_type = patch_type.strip() |
247 | 2334 | entry = entry.strip() | 2345 | entry = entry.strip() |
248 | 2335 | data['patches'][pkg].append((patch_type, entry)) | 2346 | data['patches'][pkg].append((patch_type, entry)) |
250 | 2336 | srcmap['patches'][pkg].append((cve, linenum)) | 2347 | srcmap['patches'][pkg].append((cvefile, linenum)) |
251 | 2337 | except Exception as e: | 2348 | except Exception as e: |
253 | 2338 | msg += "%s: %d: Failed to parse '%s' entry %s: %s\n" % (cve, linenum, lastfield, line, e) | 2349 | msg += "%s: %d: Failed to parse '%s' entry %s: %s\n" % (cvefile, linenum, lastfield, line, e) |
254 | 2339 | code = EXIT_FAIL | 2350 | code = EXIT_FAIL |
255 | 2340 | elif lastfield == 'CVSS': | 2351 | elif lastfield == 'CVSS': |
256 | 2341 | try: | 2352 | try: |
257 | @@ -2358,36 +2369,36 @@ def load_cve(cve, strict=False, srcmap=None): | |||
258 | 2358 | # to a dict first if needed | 2369 | # to a dict first if needed |
259 | 2359 | if type(srcmap["CVSS"]) is tuple: | 2370 | if type(srcmap["CVSS"]) is tuple: |
260 | 2360 | srcmap["CVSS"] = dict() | 2371 | srcmap["CVSS"] = dict() |
262 | 2361 | srcmap["CVSS"].setdefault(cvss['source'], (cve, linenum)) | 2372 | srcmap["CVSS"].setdefault(cvss['source'], (cvefile, linenum)) |
263 | 2362 | except Exception as e: | 2373 | except Exception as e: |
265 | 2363 | msg += "%s: %d: Failed to parse CVSS: %s\n" % (cve, linenum, e) | 2374 | msg += "%s: %d: Failed to parse CVSS: %s\n" % (cvefile, linenum, e) |
266 | 2364 | code = EXIT_FAIL | 2375 | code = EXIT_FAIL |
267 | 2365 | else: | 2376 | else: |
268 | 2366 | data[lastfield] += '\n%s' % (line[1:]) | 2377 | data[lastfield] += '\n%s' % (line[1:]) |
269 | 2367 | except KeyError as e: | 2378 | except KeyError as e: |
271 | 2368 | msg += "%s: %d: bad line '%s' (%s)\n" % (cve, linenum, line, e) | 2379 | msg += "%s: %d: bad line '%s' (%s)\n" % (cvefile, linenum, line, e) |
272 | 2369 | code = EXIT_FAIL | 2380 | code = EXIT_FAIL |
273 | 2370 | continue | 2381 | continue |
274 | 2371 | 2382 | ||
275 | 2372 | try: | 2383 | try: |
276 | 2373 | field, value = line.split(':', 1) | 2384 | field, value = line.split(':', 1) |
277 | 2374 | except ValueError as e: | 2385 | except ValueError as e: |
279 | 2375 | msg += "%s: %d: bad line '%s' (%s)\n" % (cve, linenum, line, e) | 2386 | msg += "%s: %d: bad line '%s' (%s)\n" % (cvefile, linenum, line, e) |
280 | 2376 | code = EXIT_FAIL | 2387 | code = EXIT_FAIL |
281 | 2377 | continue | 2388 | continue |
282 | 2378 | 2389 | ||
283 | 2379 | lastfield = field = field.strip() | 2390 | lastfield = field = field.strip() |
284 | 2380 | if field in fields_seen: | 2391 | if field in fields_seen: |
286 | 2381 | msg += "%s: %d: repeated field '%s'\n" % (cve, linenum, field) | 2392 | msg += "%s: %d: repeated field '%s'\n" % (cvefile, linenum, field) |
287 | 2382 | code = EXIT_FAIL | 2393 | code = EXIT_FAIL |
288 | 2383 | else: | 2394 | else: |
289 | 2384 | fields_seen.append(field) | 2395 | fields_seen.append(field) |
290 | 2385 | value = value.strip() | 2396 | value = value.strip() |
291 | 2386 | if field == 'Candidate': | 2397 | if field == 'Candidate': |
292 | 2387 | data.setdefault(field, value) | 2398 | data.setdefault(field, value) |
294 | 2388 | srcmap.setdefault(field, (cve, linenum)) | 2399 | srcmap.setdefault(field, (cvefile, linenum)) |
295 | 2389 | if value != "" and not value.startswith('CVE-') and not value.startswith('UEM-') and not value.startswith('EMB-'): | 2400 | if value != "" and not value.startswith('CVE-') and not value.startswith('UEM-') and not value.startswith('EMB-'): |
297 | 2390 | msg += "%s: %d: unknown Candidate '%s' (must be /(CVE|UEM|EMB)-/)\n" % (cve, linenum, value) | 2401 | msg += "%s: %d: unknown Candidate '%s' (must be /(CVE|UEM|EMB)-/)\n" % (cvefile, linenum, value) |
298 | 2391 | code = EXIT_FAIL | 2402 | code = EXIT_FAIL |
299 | 2392 | elif 'Priority' in field: | 2403 | elif 'Priority' in field: |
300 | 2393 | # For now, throw away comments on Priority fields | 2404 | # For now, throw away comments on Priority fields |
301 | @@ -2397,26 +2408,26 @@ def load_cve(cve, strict=False, srcmap=None): | |||
302 | 2397 | try: | 2408 | try: |
303 | 2398 | _, pkg = field.split('_', 1) | 2409 | _, pkg = field.split('_', 1) |
304 | 2399 | except ValueError: | 2410 | except ValueError: |
306 | 2400 | msg += "%s: %d: bad field with 'Priority_': '%s'\n" % (cve, linenum, field) | 2411 | msg += "%s: %d: bad field with 'Priority_': '%s'\n" % (cvefile, linenum, field) |
307 | 2401 | code = EXIT_FAIL | 2412 | code = EXIT_FAIL |
308 | 2402 | continue | 2413 | continue |
309 | 2403 | # initially set the priority reason as an empty string - this will | 2414 | # initially set the priority reason as an empty string - this will |
310 | 2404 | # be fixed up later with a real value if one is found | 2415 | # be fixed up later with a real value if one is found |
311 | 2405 | data.setdefault(field, [value, ""]) | 2416 | data.setdefault(field, [value, ""]) |
313 | 2406 | srcmap.setdefault(field, (cve, linenum)) | 2417 | srcmap.setdefault(field, (cvefile, linenum)) |
314 | 2407 | if value not in ['untriaged', 'not-for-us'] + priorities: | 2418 | if value not in ['untriaged', 'not-for-us'] + priorities: |
316 | 2408 | msg += "%s: %d: unknown Priority '%s'\n" % (cve, linenum, value) | 2419 | msg += "%s: %d: unknown Priority '%s'\n" % (cvefile, linenum, value) |
317 | 2409 | code = EXIT_FAIL | 2420 | code = EXIT_FAIL |
318 | 2410 | elif 'Patches_' in field: | 2421 | elif 'Patches_' in field: |
319 | 2411 | try: | 2422 | try: |
320 | 2412 | _, pkg = field.split('_', 1) | 2423 | _, pkg = field.split('_', 1) |
321 | 2413 | except ValueError: | 2424 | except ValueError: |
323 | 2414 | msg += "%s: %d: bad field with 'Patches_': '%s'\n" % (cve, linenum, field) | 2425 | msg += "%s: %d: bad field with 'Patches_': '%s'\n" % (cvefile, linenum, field) |
324 | 2415 | code = EXIT_FAIL | 2426 | code = EXIT_FAIL |
325 | 2416 | continue | 2427 | continue |
326 | 2417 | # value should be empty | 2428 | # value should be empty |
327 | 2418 | if len(value) > 0: | 2429 | if len(value) > 0: |
329 | 2419 | msg += "%s: %d: '%s' field should have no value\n" % (cve, linenum, field) | 2430 | msg += "%s: %d: '%s' field should have no value\n" % (cvefile, linenum, field) |
330 | 2420 | code = EXIT_FAIL | 2431 | code = EXIT_FAIL |
331 | 2421 | continue | 2432 | continue |
332 | 2422 | data['patches'].setdefault(pkg, list()) | 2433 | data['patches'].setdefault(pkg, list()) |
333 | @@ -2426,41 +2437,42 @@ def load_cve(cve, strict=False, srcmap=None): | |||
334 | 2426 | try: | 2437 | try: |
335 | 2427 | _, pkg = field.split('_', 1) | 2438 | _, pkg = field.split('_', 1) |
336 | 2428 | except ValueError: | 2439 | except ValueError: |
338 | 2429 | msg += "%s: %d: bad field with 'Tags_': '%s'\n" % (cve, linenum, field) | 2440 | msg += "%s: %d: bad field with 'Tags_': '%s'\n" % (cvefile, linenum, field) |
339 | 2430 | code = EXIT_FAIL | 2441 | code = EXIT_FAIL |
340 | 2431 | continue | 2442 | continue |
341 | 2432 | data['tags'].setdefault(pkg, set()) | 2443 | data['tags'].setdefault(pkg, set()) |
343 | 2433 | srcmap['tags'].setdefault(pkg, (cve, linenum)) | 2444 | srcmap['tags'].setdefault(pkg, (cvefile, linenum)) |
344 | 2434 | for word in value.strip().split(' '): | 2445 | for word in value.strip().split(' '): |
345 | 2435 | if word not in valid_tags: | 2446 | if word not in valid_tags: |
347 | 2436 | msg += "%s: %d: invalid tag '%s': '%s'\n" % (cve, linenum, word, field) | 2447 | msg += "%s: %d: invalid tag '%s': '%s'\n" % (cvefile, linenum, word, field) |
348 | 2437 | code = EXIT_FAIL | 2448 | code = EXIT_FAIL |
349 | 2438 | continue | 2449 | continue |
350 | 2439 | data['tags'][pkg].add(word) | 2450 | data['tags'][pkg].add(word) |
351 | 2440 | elif '_' in field: | 2451 | elif '_' in field: |
353 | 2441 | success, pkg, rel, state, details, code, msg = parse_cve_release_package_field(cve, field, data, value, code, msg, linenum) | 2452 | success, pkg, rel, state, details, code, msg = parse_cve_release_package_field(cvefile, field, data, value, code, msg, linenum) |
354 | 2442 | if not success: | 2453 | if not success: |
355 | 2443 | assert(code == EXIT_FAIL) | 2454 | assert(code == EXIT_FAIL) |
356 | 2444 | continue | 2455 | continue |
357 | 2445 | canon, _, _, _ = get_subproject_details(rel) | 2456 | canon, _, _, _ = get_subproject_details(rel) |
358 | 2446 | if canon is None and rel not in ['upstream', 'devel']: | 2457 | if canon is None and rel not in ['upstream', 'devel']: |
360 | 2447 | msg += "%s: %d: unknown entry '%s'\n" % (cve, linenum, rel) | 2458 | msg += "%s: %d: unknown entry '%s'\n" % (cvefile, linenum, rel) |
361 | 2448 | code = EXIT_FAIL | 2459 | code = EXIT_FAIL |
362 | 2449 | continue | 2460 | continue |
363 | 2450 | affected.setdefault(pkg, dict()) | 2461 | affected.setdefault(pkg, dict()) |
364 | 2451 | if rel in affected[pkg]: | 2462 | if rel in affected[pkg]: |
366 | 2452 | msg += "%s: %d: duplicate entry for '%s': original at line %d\n" % (cve, linenum, rel, srcmap['pkgs'][pkg][rel][1]) | 2463 | msg += ("%s: %d: duplicate entry for '%s': original at %s line %d\n" |
367 | 2464 | % (cvefile, linenum, rel, srcmap['pkgs'][pkg][rel][0], srcmap['pkgs'][pkg][rel][1])) | ||
368 | 2453 | code = EXIT_FAIL | 2465 | code = EXIT_FAIL |
369 | 2454 | continue | 2466 | continue |
370 | 2455 | affected[pkg].setdefault(rel, [state, details]) | 2467 | affected[pkg].setdefault(rel, [state, details]) |
371 | 2456 | srcmap['pkgs'].setdefault(pkg, dict()) | 2468 | srcmap['pkgs'].setdefault(pkg, dict()) |
373 | 2457 | srcmap['pkgs'][pkg].setdefault(rel, (cve, linenum)) | 2469 | srcmap['pkgs'][pkg].setdefault(rel, (cvefile, linenum)) |
374 | 2458 | elif field not in required_fields + extra_fields: | 2470 | elif field not in required_fields + extra_fields: |
376 | 2459 | msg += "%s: %d: unknown field '%s'\n" % (cve, linenum, field) | 2471 | msg += "%s: %d: unknown field '%s'\n" % (cvefile, linenum, field) |
377 | 2460 | code = EXIT_FAIL | 2472 | code = EXIT_FAIL |
378 | 2461 | else: | 2473 | else: |
379 | 2462 | data.setdefault(field, value) | 2474 | data.setdefault(field, value) |
381 | 2463 | srcmap.setdefault(field, (cve, linenum)) | 2475 | srcmap.setdefault(field, (cvefile, linenum)) |
382 | 2464 | 2476 | ||
383 | 2465 | data['Notes'] = notes_parser.finalize() | 2477 | data['Notes'] = notes_parser.finalize() |
384 | 2466 | data['CVSS'] = cvss_entries | 2478 | data['CVSS'] = cvss_entries |
385 | @@ -2468,28 +2480,28 @@ def load_cve(cve, strict=False, srcmap=None): | |||
386 | 2468 | # Check for required fields | 2480 | # Check for required fields |
387 | 2469 | for field in required_fields: | 2481 | for field in required_fields: |
388 | 2470 | # boilerplate files are special and can (should?) be empty | 2482 | # boilerplate files are special and can (should?) be empty |
390 | 2471 | nonempty = [] if "boilerplate" in cve else ['Candidate'] | 2483 | nonempty = [] if "boilerplate" in cvefile else ['Candidate'] |
391 | 2472 | if strict: | 2484 | if strict: |
392 | 2473 | nonempty += ['PublicDate'] | 2485 | nonempty += ['PublicDate'] |
393 | 2474 | 2486 | ||
394 | 2475 | if field not in data or field not in fields_seen: | 2487 | if field not in data or field not in fields_seen: |
396 | 2476 | msg += "%s: %d: missing field '%s'\n" % (cve, linenum, field) | 2488 | msg += "%s: %d: missing field '%s'\n" % (cvefile, linenum, field) |
397 | 2477 | code = EXIT_FAIL | 2489 | code = EXIT_FAIL |
398 | 2478 | elif field in nonempty and data[field].strip() == "": | 2490 | elif field in nonempty and data[field].strip() == "": |
400 | 2479 | msg += "%s: %d: required field '%s' is empty\n" % (cve, linenum, field) | 2491 | msg += "%s: %d: required field '%s' is empty\n" % (cvefile, linenum, field) |
401 | 2480 | code = EXIT_FAIL | 2492 | code = EXIT_FAIL |
402 | 2481 | 2493 | ||
403 | 2482 | # Fill in defaults for missing fields | 2494 | # Fill in defaults for missing fields |
404 | 2483 | if 'Priority' not in data: | 2495 | if 'Priority' not in data: |
405 | 2484 | data.setdefault('Priority', ['untriaged']) | 2496 | data.setdefault('Priority', ['untriaged']) |
407 | 2485 | srcmap.setdefault('Priority', (cve, 1)) | 2497 | srcmap.setdefault('Priority', (cvefile, 1)) |
408 | 2486 | # Perform override fields | 2498 | # Perform override fields |
409 | 2487 | if 'PublicDateAtUSN' in data: | 2499 | if 'PublicDateAtUSN' in data: |
410 | 2488 | data['PublicDate'] = data['PublicDateAtUSN'] | 2500 | data['PublicDate'] = data['PublicDateAtUSN'] |
411 | 2489 | srcmap['PublicDate'] = srcmap['PublicDateAtUSN'] | 2501 | srcmap['PublicDate'] = srcmap['PublicDateAtUSN'] |
412 | 2490 | if 'CRD' in data and data['CRD'].strip() != '' and data['PublicDate'] != data['CRD']: | 2502 | if 'CRD' in data and data['CRD'].strip() != '' and data['PublicDate'] != data['CRD']: |
415 | 2491 | if cve.startswith("embargoed"): | 2503 | if cvefile.startswith("embargoed"): |
416 | 2492 | print("%s: %d: adjusting PublicDate to use CRD: %s" % (cve, linenum, data['CRD']), file=sys.stderr) | 2504 | print("%s: %d: adjusting PublicDate to use CRD: %s" % (cvefile, linenum, data['CRD']), file=sys.stderr) |
417 | 2493 | data['PublicDate'] = data['CRD'] | 2505 | data['PublicDate'] = data['CRD'] |
418 | 2494 | srcmap['PublicDate'] = srcmap['CRD'] | 2506 | srcmap['PublicDate'] = srcmap['CRD'] |
419 | 2495 | 2507 | ||
420 | @@ -2510,12 +2522,12 @@ def load_cve(cve, strict=False, srcmap=None): | |||
421 | 2510 | if rel not in external_releases: | 2522 | if rel not in external_releases: |
422 | 2511 | needs_upstream = True | 2523 | needs_upstream = True |
423 | 2512 | if needs_upstream and 'upstream' not in affected[pkg]: | 2524 | if needs_upstream and 'upstream' not in affected[pkg]: |
425 | 2513 | msg += "%s: %d: missing upstream '%s'\n" % (cve, linenum, pkg) | 2525 | msg += "%s: %d: missing upstream '%s'\n" % (cvefile, linenum, pkg) |
426 | 2514 | code = EXIT_FAIL | 2526 | code = EXIT_FAIL |
427 | 2515 | 2527 | ||
428 | 2516 | data['pkgs'] = affected | 2528 | data['pkgs'] = affected |
429 | 2517 | 2529 | ||
431 | 2518 | code, msg = load_external_subproject_cve_data(cve, data, srcmap, code, msg) | 2530 | code, msg = load_external_subproject_cve_data(cvefile, data, srcmap, code, msg) |
432 | 2519 | 2531 | ||
433 | 2520 | if code != EXIT_OKAY: | 2532 | if code != EXIT_OKAY: |
434 | 2521 | raise ValueError(msg.strip()) | 2533 | raise ValueError(msg.strip()) |
I added one comment on the /proc/pid/fd/0 symlink-breaking -- and did a very quick skim on the rest; it seemed fine, but also like the sort of mechanical thing that would be easy to overlook a mistake.
Thanks