1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
# Copyright 2017 David Malcolm <dmalcolm@redhat.com>
# Copyright 2017 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
# USA
# Parser for .csv files emitted by "splint"
# http://splint.org/
from collections import namedtuple
import csv
import os
import re
from firehose.model import Message, Function, Point, Range, \
File, Location, Generator, Metadata, Analysis, Issue, Sut, Trace, \
State, Notes, CustomFields
FIELDS = ['warning', 'flag_code', 'flag_name', 'priority',
'file', 'line', 'column',
'warning_text', 'additional_text']
WARNING_TEXT_IDX = FIELDS.index('warning_text')
class Row(namedtuple('Row', FIELDS)):
def to_issue(self):
"""
Generate an Issue from this csv row.
"""
location = Location(file=File(givenpath=self.file,
abspath=None),
function=None, # FIXME
point=Point(int(self.line),
int(self.column)))
return Issue(cwe=None,
testid=self.flag_name,
location=location,
message=Message(self.warning_text),
notes=Notes(self.additional_text),
trace=None,
severity=self.priority,
customfields=None)
def parse_row(row):
"""
Convert a list generated by csv.reader into a Row
"""
# splint doesn't escape quotes that occur within the messages, which
# can lead to extra fields:
# https://github.com/ravenexp/splint/issues/6
# Workaround this by assuming that such quotes occurred in the
# "Warning Text" field.
# This fires for warnings 4 and 6
#
# This fixes the issue, but there is still some minor information loss
# e.g. some quote characters in the text disappear, and we sometimes
# gain a trailing quote character
if len(row) > len(FIELDS):
joined_text = ','.join(row[WARNING_TEXT_IDX:-1])
row = row[:WARNING_TEXT_IDX] + [joined_text, row[-1]]
return Row(*row)
def parse_splint_csv(path):
"""
Parse a .csv file written by splint's "-csv FILENAME" option.
Generate a list of Result instances.
"""
generator = Generator(name='splint')
metadata = Metadata(generator, None, None, None)
analysis = Analysis(metadata, [])
with open(path, 'r') as f:
reader = csv.reader(f)
for raw_row in reader:
# Skip the initial title row
if raw_row[0] == 'Warning':
continue
rowobj = parse_row(raw_row)
analysis.results.append(rowobj.to_issue())
return analysis
def parse_splint_stderr(stderr):
"""
Parse the stderr from splint (as a string).
Return a version string, or None.
"""
lines = stderr.splitlines()
if not lines:
return None
m = re.match("Splint\s+(.*)\s+---.*", lines[0])
if m:
return m.group(1)
|