@@ -334,7 +334,7 @@ def extract_code_coverage_data(code_coverage_summary):
334
334
return line_total_summary
335
335
336
336
337
- def prepare_code_coverage_dict (
337
+ def prepare_code_coverage_data (
338
338
code_coverage_summary , project_name : str , date_str : str ,
339
339
project_language : str ) -> Optional [Dict [str , Any ]]:
340
340
"""Gets coverage URL and line coverage total of a project"""
@@ -498,7 +498,7 @@ def extract_local_project_data(project_name, oss_fuzz_path,
498
498
macro_block
499
499
}
500
500
501
- code_coverage_data_dict = prepare_code_coverage_dict (
501
+ code_coverage_data_dict = prepare_code_coverage_data (
502
502
code_coverage_summary , project_name , '' , project_language )
503
503
504
504
if cov_fuzz_stats is not None :
@@ -776,7 +776,7 @@ def extract_project_data(project_name, date_str, should_include_details,
776
776
'macro_block' : macro_block
777
777
}
778
778
779
- code_coverage_data_dict = prepare_code_coverage_dict (
779
+ code_coverage_data_dict = prepare_code_coverage_data (
780
780
code_coverage_summary , project_name , date_str , project_language )
781
781
782
782
per_fuzzer_cov = {}
@@ -787,10 +787,19 @@ def extract_project_data(project_name, date_str, should_include_details,
787
787
788
788
amount_of_fuzzers = len (all_fuzzers )
789
789
for ff in all_fuzzers :
790
+ try :
791
+ fuzzer_corpus_size = oss_fuzz .get_fuzzer_corpus_size (
792
+ project_name , date_str .replace ("-" , "" ), ff ,
793
+ introspector_report )
794
+ except :
795
+ fuzzer_corpus_size = None
796
+
790
797
try :
791
798
fuzzer_cov = oss_fuzz .get_fuzzer_code_coverage_summary (
792
799
project_name , date_str .replace ("-" , "" ), ff )
793
800
fuzzer_cov_data = extract_code_coverage_data (fuzzer_cov )
801
+ if fuzzer_cov_data is not None :
802
+ fuzzer_cov_data ['corpus_size' ] = fuzzer_corpus_size
794
803
per_fuzzer_cov [ff ] = fuzzer_cov_data
795
804
except :
796
805
pass
@@ -958,8 +967,36 @@ def extend_db_timestamps(db_timestamp, output_directory):
958
967
json .dump (existing_timestamps , f )
959
968
960
969
970
+ def per_fuzzer_coverage_has_degraded (fuzzer_data : List [Dict [str , Any ]],
971
+ project_name : str ,
972
+ ff : str ) -> List [Dict [str , str ]]:
973
+ """Go through the fuzzer data and find coverage drops."""
974
+
975
+ def get_url (date ):
976
+ report_url = oss_fuzz .get_fuzzer_code_coverage_summary_url (
977
+ project_name , date .replace ('-' , '' ), ff )
978
+ report_url = report_url [:- len ('summary.json' )] + 'index.html'
979
+ return report_url
980
+
981
+ res = []
982
+ for yesterday , today in zip (fuzzer_data [:- 1 ], fuzzer_data [1 :]):
983
+ if yesterday ['percentage' ] - today [
984
+ 'percentage' ] > FUZZER_COVERAGE_IS_DEGRADED :
985
+ res .append ({
986
+ 'before_date' : yesterday ['date' ],
987
+ 'before_url' : get_url (yesterday ['date' ]),
988
+ 'before_perc' : yesterday ['percentage' ],
989
+ 'current_date' : today ['date' ],
990
+ 'current_url' : get_url (today ['date' ]),
991
+ 'current_perc' : today ['percentage' ],
992
+ })
993
+
994
+ return res
995
+
996
+
961
997
def per_fuzzer_coverage_analysis (project_name : str ,
962
- coverages : Dict [str , List [Tuple [int , str ]]],
998
+ per_fuzzer_data : Dict [str , List [Dict [str ,
999
+ Any ]]],
963
1000
lost_fuzzers ):
964
1001
"""Go through the recent coverage results and combine them into a short summary.
965
1002
Including an assessment if the fuzzer got worse over time.
@@ -971,34 +1008,47 @@ def per_fuzzer_coverage_analysis(project_name: str,
971
1008
# at per fuzzer coverage, which is should already be normalized to what
972
1009
# can be reached.
973
1010
# TODO What would be a good percentage to mark as coverage degradation,
974
- # taking 5% for now but should be observed, maybe per it should be
1011
+ # taking 5% for now but should be observed, maybe it should be
975
1012
# configurable per project as well.
976
1013
results = {}
977
- for ff , data in coverages .items ():
1014
+ for ff , data in per_fuzzer_data .items ():
978
1015
if len (data ) > 0 :
979
- values = [dd [0 ] for dd in data ]
980
- dates = [dd [1 ] for dd in data ]
981
- latest_date_with_value = next (dd [1 ] for dd in reversed (data )
982
- if dd [0 ] is not None )
1016
+ percentages = [dd ['percentage' ] for dd in data ]
1017
+ dates = [dd ['date' ] for dd in data ]
1018
+ totals = [dd ['total' ] for dd in data ]
1019
+ covered = [dd ['covered' ] for dd in data ]
1020
+ corpus_size = [dd ['corpus_size' ] for dd in data ]
1021
+ latest_date_with_value = next (dd ['date' ] for dd in reversed (data )
1022
+ if dd ['percentage' ] is not None )
983
1023
if latest_date_with_value is not None :
984
1024
report_url = oss_fuzz .get_fuzzer_code_coverage_summary_url (
985
1025
project_name , latest_date_with_value .replace ('-' , '' ), ff )
986
1026
report_url = report_url [:- len ('summary.json' )] + 'index.html'
987
1027
else :
988
1028
report_url = None
989
- max_cov = max (values [:- 1 ], default = 0 )
990
- avg_cov = round (statistics .fmean (values ), 2 )
991
- current = values [- 1 ]
1029
+ max_cov = max (percentages [:- 1 ], default = 0 )
1030
+ avg_cov = round (statistics .fmean (percentages ), 2 )
1031
+ current = percentages [- 1 ]
1032
+ try :
1033
+ days_degraded = per_fuzzer_coverage_has_degraded (
1034
+ data , project_name , ff )
1035
+ except :
1036
+ days_degraded = []
992
1037
results [ff ] = {
993
1038
'report_url' : report_url ,
994
1039
'report_date' : latest_date_with_value ,
995
- 'coverages_values' : values ,
1040
+ 'hashed_name' : str (hash (ff )),
1041
+ 'coverages_perc' : percentages ,
1042
+ 'coverages_totals' : totals ,
1043
+ 'coverages_covered' : covered ,
1044
+ 'coverages_corpus' : corpus_size ,
996
1045
'coverages_dates' : dates ,
997
1046
'max' : max_cov ,
998
1047
'avg' : avg_cov ,
999
1048
'current' : current ,
1000
- 'has_degraded ' :
1049
+ 'max_has_degraded ' :
1001
1050
(max_cov - current ) > FUZZER_COVERAGE_IS_DEGRADED ,
1051
+ 'days_degraded' : days_degraded ,
1002
1052
'got_lost' : ff in lost_fuzzers ,
1003
1053
}
1004
1054
return results
@@ -1038,7 +1088,18 @@ def calculate_recent_results(projects_with_new_results, timestamps,
1038
1088
except :
1039
1089
perc = 0
1040
1090
1041
- per_fuzzer_coverages [ff ].append ((perc , do ))
1091
+ per_fuzzer_coverages [ff ].append ({
1092
+ 'corpus_size' :
1093
+ cov_data ['corpus_size' ],
1094
+ 'covered' :
1095
+ cov_data ['covered' ],
1096
+ 'total' :
1097
+ cov_data ['count' ],
1098
+ 'percentage' :
1099
+ perc ,
1100
+ 'date' :
1101
+ do
1102
+ })
1042
1103
except :
1043
1104
continue
1044
1105
@@ -1450,6 +1511,7 @@ def setup_webapp_cache() -> None:
1450
1511
os .mkdir ("extracted-db-archive" )
1451
1512
1452
1513
db_archive .extractall ("extracted-db-archive" )
1514
+
1453
1515
logger .info ("Extracted it all" )
1454
1516
1455
1517
# Copy over the files
0 commit comments