@@ -119,6 +119,35 @@ def rwif(*args):
119119 return rwif
120120
121121
122+ def get_total_counts (d ):
123+ """Get the sum of all "count" values of a nested dictionary"""
124+ return (
125+ (
126+ d ["count" ]
127+ if "count" in d else
128+ sum (map (get_total_counts , d .values ()))
129+ )
130+ if isinstance (d , dict ) else 0
131+ )
132+
133+
134+ def sort_file_failures (d ):
135+ """Get a sorted version of the file failures dictionary."""
136+ # This relies on dict iteration being the same as insertion order,
137+ # which is an implementation detail in CPython,
138+ # but OrderedDict is harder to serialize with pyyaml.
139+ return (
140+ dict (
141+ sorted (
142+ ((k , sort_file_failures (v )) for k , v in d .items ()),
143+ key = lambda pair : get_total_counts (pair [1 ]),
144+ reverse = True ,
145+ )
146+ )
147+ if isinstance (d , dict ) else d
148+ )
149+
150+
122151class FileFailures (PyPlugin ):
123152 def __init__ (self , panda ):
124153 self .panda = panda
@@ -735,7 +764,8 @@ def ioctl_default(self, filename, cmd, arg, ioctl_details):
735764 def dump_results (self ):
736765 # Dump all file failures to disk as yaml
737766 with open (pjoin (self .outdir , outfile_missing ), "w" ) as f :
738- yaml .dump (self .file_failures , f )
767+ out = sort_file_failures (self .file_failures )
768+ yaml .dump (out , f , sort_keys = False )
739769
740770 if hasattr (self , "symex" ):
741771 # Need to tell symex to export results as well
0 commit comments