|
|
@ -21,9 +21,7 @@ import os
|
|
|
|
import shutil
|
|
|
|
import shutil
|
|
|
|
import subprocess
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
|
|
|
|
import time
|
|
|
|
import time
|
|
|
|
import xml.etree.ElementTree as ET
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from . import config, issues, jwlib, utils
|
|
|
|
from . import config, issues, jwlib, utils
|
|
|
|
|
|
|
|
|
|
|
@ -227,180 +225,6 @@ def help_exit(message):
|
|
|
|
exit(1)
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def compare_csv_rows(row_1, row_2):
|
|
|
|
|
|
|
|
filename_1 = row_1[utils.CSV_INDEX_FILENAME]
|
|
|
|
|
|
|
|
filename_2 = row_2[utils.CSV_INDEX_FILENAME]
|
|
|
|
|
|
|
|
if filename_1 < filename_2:
|
|
|
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
elif filename_1 > filename_2:
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
line_1 = int(row_1[utils.CSV_INDEX_LINE])
|
|
|
|
|
|
|
|
line_2 = int(row_2[utils.CSV_INDEX_LINE])
|
|
|
|
|
|
|
|
return line_1 - line_2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def compare_json_rows(row_1, row_2):
|
|
|
|
|
|
|
|
filename_1 = row_1[utils.JSON_INDEX_FILENAME]
|
|
|
|
|
|
|
|
filename_2 = row_2[utils.JSON_INDEX_FILENAME]
|
|
|
|
|
|
|
|
if filename_1 < filename_2:
|
|
|
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
elif filename_1 > filename_2:
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
line_1 = int(row_1[utils.JSON_INDEX_LINE])
|
|
|
|
|
|
|
|
line_2 = int(row_2[utils.JSON_INDEX_LINE])
|
|
|
|
|
|
|
|
return line_1 - line_2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def should_report(analyzer, error_kind, error_type, error_bucket):
|
|
|
|
|
|
|
|
analyzers_whitelist = [
|
|
|
|
|
|
|
|
config.ANALYZER_ERADICATE,
|
|
|
|
|
|
|
|
config.ANALYZER_CHECKERS,
|
|
|
|
|
|
|
|
config.ANALYZER_TRACING,
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
error_kinds = [issues.ISSUE_KIND_ERROR, issues.ISSUE_KIND_WARNING]
|
|
|
|
|
|
|
|
null_style_buckets = ['B1', 'B2']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if analyzer in analyzers_whitelist:
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if error_kind not in error_kinds:
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not error_type:
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if error_type in issues.NULL_STYLE_ISSUE_TYPES:
|
|
|
|
|
|
|
|
return error_bucket in null_style_buckets
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return error_type in issues.ISSUE_TYPES
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def should_report_csv(analyzer, row):
|
|
|
|
|
|
|
|
error_kind = row[utils.CSV_INDEX_KIND]
|
|
|
|
|
|
|
|
error_type = row[utils.CSV_INDEX_TYPE]
|
|
|
|
|
|
|
|
error_bucket = '' # can be updated later once we extract it from qualifier
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
qualifier_xml = ET.fromstring(row[utils.CSV_INDEX_QUALIFIER_TAGS])
|
|
|
|
|
|
|
|
if qualifier_xml.tag == utils.QUALIFIER_TAGS:
|
|
|
|
|
|
|
|
bucket = qualifier_xml.find(utils.BUCKET_TAGS)
|
|
|
|
|
|
|
|
if bucket is not None:
|
|
|
|
|
|
|
|
error_bucket = bucket.text
|
|
|
|
|
|
|
|
except ET.ParseError:
|
|
|
|
|
|
|
|
pass # this will skip any invalid xmls
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return should_report(analyzer, error_kind, error_type, error_bucket)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def should_report_json(analyzer, row):
|
|
|
|
|
|
|
|
error_kind = row[utils.JSON_INDEX_KIND]
|
|
|
|
|
|
|
|
error_type = row[utils.JSON_INDEX_TYPE]
|
|
|
|
|
|
|
|
error_bucket = '' # can be updated later once we extract it from qualifier
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for qual_tag in row[utils.QUALIFIER_TAGS]:
|
|
|
|
|
|
|
|
if qual_tag['tag'] == utils.BUCKET_TAGS:
|
|
|
|
|
|
|
|
error_bucket = qual_tag['value']
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return should_report(analyzer, error_kind, error_type, error_bucket)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def clean_json(args, json_report):
|
|
|
|
|
|
|
|
collected_rows = []
|
|
|
|
|
|
|
|
with codecs.open(json_report, 'r', encoding=utils.LOCALE) as file_in:
|
|
|
|
|
|
|
|
rows = json.load(file_in)
|
|
|
|
|
|
|
|
for row in rows:
|
|
|
|
|
|
|
|
filename = row[utils.JSON_INDEX_FILENAME]
|
|
|
|
|
|
|
|
if os.path.isfile(filename):
|
|
|
|
|
|
|
|
if args.no_filtering or should_report_json(args.analyzer, row):
|
|
|
|
|
|
|
|
collected_rows.append(row)
|
|
|
|
|
|
|
|
collected_rows = sorted(
|
|
|
|
|
|
|
|
collected_rows,
|
|
|
|
|
|
|
|
cmp=compare_json_rows)
|
|
|
|
|
|
|
|
temporary_file = tempfile.mktemp()
|
|
|
|
|
|
|
|
with codecs.open(temporary_file, 'w', encoding=utils.LOCALE) as file_out:
|
|
|
|
|
|
|
|
json.dump(collected_rows, file_out)
|
|
|
|
|
|
|
|
file_out.flush()
|
|
|
|
|
|
|
|
shutil.move(temporary_file, json_report)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def clean_csv(args, csv_report):
|
|
|
|
|
|
|
|
collected_rows = []
|
|
|
|
|
|
|
|
with open(csv_report, 'r') as file_in:
|
|
|
|
|
|
|
|
reader = utils.locale_csv_reader(file_in)
|
|
|
|
|
|
|
|
rows = [row for row in reader]
|
|
|
|
|
|
|
|
if len(rows) <= 1:
|
|
|
|
|
|
|
|
return rows
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
for row in rows[1:]:
|
|
|
|
|
|
|
|
filename = row[utils.CSV_INDEX_FILENAME]
|
|
|
|
|
|
|
|
if os.path.isfile(filename):
|
|
|
|
|
|
|
|
if args.no_filtering \
|
|
|
|
|
|
|
|
or should_report_csv(args.analyzer, row):
|
|
|
|
|
|
|
|
collected_rows.append(row)
|
|
|
|
|
|
|
|
collected_rows = sorted(
|
|
|
|
|
|
|
|
collected_rows,
|
|
|
|
|
|
|
|
cmp=compare_csv_rows)
|
|
|
|
|
|
|
|
collected_rows = [rows[0]] + collected_rows
|
|
|
|
|
|
|
|
temporary_file = tempfile.mktemp()
|
|
|
|
|
|
|
|
with open(temporary_file, 'w') as file_out:
|
|
|
|
|
|
|
|
writer = csv.writer(file_out)
|
|
|
|
|
|
|
|
writer.writerows(collected_rows)
|
|
|
|
|
|
|
|
file_out.flush()
|
|
|
|
|
|
|
|
shutil.move(temporary_file, csv_report)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_and_write(file_out, message):
|
|
|
|
|
|
|
|
print(message)
|
|
|
|
|
|
|
|
file_out.write(message + '\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_errors(json_report, bugs_out):
|
|
|
|
|
|
|
|
with codecs.open(json_report, 'r', encoding=utils.LOCALE) as file_in:
|
|
|
|
|
|
|
|
errors = json.load(file_in)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
errors = filter(lambda row: row[utils.JSON_INDEX_KIND] in
|
|
|
|
|
|
|
|
[issues.ISSUE_KIND_ERROR, issues.ISSUE_KIND_WARNING],
|
|
|
|
|
|
|
|
errors)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with codecs.open(bugs_out, 'w', encoding=utils.LOCALE) as file_out:
|
|
|
|
|
|
|
|
text_errors_list = []
|
|
|
|
|
|
|
|
for row in errors:
|
|
|
|
|
|
|
|
filename = row[utils.JSON_INDEX_FILENAME]
|
|
|
|
|
|
|
|
if os.path.isfile(filename):
|
|
|
|
|
|
|
|
kind = row[utils.JSON_INDEX_KIND]
|
|
|
|
|
|
|
|
line = row[utils.JSON_INDEX_LINE]
|
|
|
|
|
|
|
|
error_type = row[utils.JSON_INDEX_TYPE]
|
|
|
|
|
|
|
|
msg = row[utils.JSON_INDEX_QUALIFIER]
|
|
|
|
|
|
|
|
indenter = utils.Indenter()
|
|
|
|
|
|
|
|
indenter.indent_push()
|
|
|
|
|
|
|
|
indenter.add(
|
|
|
|
|
|
|
|
utils.build_source_context(filename,
|
|
|
|
|
|
|
|
utils.TERMINAL_FORMATTER,
|
|
|
|
|
|
|
|
int(line)))
|
|
|
|
|
|
|
|
source_context = unicode(indenter)
|
|
|
|
|
|
|
|
text_errors_list.append(
|
|
|
|
|
|
|
|
u'{0}:{1}: {2}: {3}\n {4}\n{5}'.format(
|
|
|
|
|
|
|
|
filename,
|
|
|
|
|
|
|
|
line,
|
|
|
|
|
|
|
|
kind.lower(),
|
|
|
|
|
|
|
|
error_type,
|
|
|
|
|
|
|
|
msg,
|
|
|
|
|
|
|
|
source_context,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
n_issues = len(text_errors_list)
|
|
|
|
|
|
|
|
if n_issues == 0:
|
|
|
|
|
|
|
|
print_and_write(file_out, 'No issues found')
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
msg = '\nFound %s\n' % utils.get_plural('issue', n_issues)
|
|
|
|
|
|
|
|
print_and_write(file_out, msg)
|
|
|
|
|
|
|
|
text_errors = '\n\n'.join(text_errors_list)
|
|
|
|
|
|
|
|
print_and_write(file_out, text_errors)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_command(cmd, debug_mode, javac_arguments, step, analyzer):
|
|
|
|
def run_command(cmd, debug_mode, javac_arguments, step, analyzer):
|
|
|
|
if debug_mode:
|
|
|
|
if debug_mode:
|
|
|
|
print('\n{0}\n'.format(' '.join(cmd)))
|
|
|
|
print('\n{0}\n'.format(' '.join(cmd)))
|
|
|
@ -668,8 +492,8 @@ class Infer:
|
|
|
|
logging.error('Error with InferPrint with the command: '
|
|
|
|
logging.error('Error with InferPrint with the command: '
|
|
|
|
+ infer_print_cmd)
|
|
|
|
+ infer_print_cmd)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
clean_csv(self.args, csv_report)
|
|
|
|
issues.clean_csv(self.args, csv_report)
|
|
|
|
clean_json(self.args, json_report)
|
|
|
|
issues.clean_json(self.args, json_report)
|
|
|
|
self.update_stats_with_warnings(csv_report)
|
|
|
|
self.update_stats_with_warnings(csv_report)
|
|
|
|
|
|
|
|
|
|
|
|
return exit_status
|
|
|
|
return exit_status
|
|
|
@ -725,7 +549,7 @@ class Infer:
|
|
|
|
utils.JSON_REPORT_FILENAME)
|
|
|
|
utils.JSON_REPORT_FILENAME)
|
|
|
|
bugs_out = os.path.join(self.args.infer_out,
|
|
|
|
bugs_out = os.path.join(self.args.infer_out,
|
|
|
|
utils.BUGS_FILENAME)
|
|
|
|
utils.BUGS_FILENAME)
|
|
|
|
print_errors(json_report, bugs_out)
|
|
|
|
issues.print_errors(json_report, bugs_out)
|
|
|
|
|
|
|
|
|
|
|
|
def print_analysis_stats(self):
|
|
|
|
def print_analysis_stats(self):
|
|
|
|
procs_total = self.stats['int']['procedures']
|
|
|
|
procs_total = self.stats['int']['procedures']
|
|
|
|