From ea67f5dbca6557eb12bc1d4ec27b557520b70887 Mon Sep 17 00:00:00 2001 From: "David A. Wheeler" Date: Sat, 12 Aug 2017 19:33:49 -0400 Subject: [PATCH] Switch all print statements to print() functions Switch all print statements to print() functions per PEP 3105. Python 3 *only* supports print() functions, so this begins to move the code towards simultaneously supporting python 2 and 3. This implements "stage1" of futurize. In theory, "stage1" is supposed to be "low risk", but in fact a *large* number of manual fixes had to be made to make the program work again. Python 2's traditional print statement includes the "softspace" feature. This is "a semi-secret attribute on files currently used to tell print whether to insert a space before the first item". The print() function does not have the "softspace" feature, so there is no direct translation for any situation that depended on softspaces. Flawfinder used softspaces extensively, as they were convenient, so it took a little work to make print() functions work. Signed-off-by: David A. Wheeler --- flawfinder | 235 +++++++++++++++++++++++++++-------------------------- 1 file changed, 118 insertions(+), 117 deletions(-) diff --git a/flawfinder b/flawfinder index be573e5..eb0af45 100755 --- a/flawfinder +++ b/flawfinder @@ -49,6 +49,7 @@ # than Python 2.7. from __future__ import division +from __future__ import print_function import functools import sys import re @@ -244,7 +245,7 @@ def load_patch_info(input_patch_file): try: hPatch = open(input_patch_file, 'r') except BaseException: - print "Error: failed to open", h(input_patch_file) + print("Error: failed to open", h(input_patch_file)) sys.exit(1) patched_filename = "" # Name of new file patched by current hunk. @@ -258,7 +259,7 @@ def load_patch_info(input_patch_file): elif is_gnu_diff(sLine): fn_get_filename = gnu_diff_get_filename else: - print "Error: Unrecognized patch format" + print("Error: Unrecognized patch format") sys.exit(1) while True: # Loop-and-half construct. Read a line, end loop when no more @@ -328,18 +329,18 @@ def print_multi_line(text): prefix = " " starting_position = len(prefix) + 1 # - print prefix, + print(prefix, end='') position = starting_position # for w in text.split(): if len(w) + position >= width: - print - print prefix, + print() + print(prefix, end='') position = starting_position - print w, + print(' ', end='') + print(w, end='') position = position + len(w) + 1 - # This matches references to CWE identifiers, so we can HTMLize them. # We don't refer to CWEs with one digit, so we'll only match on 2+ digits. link_cwe_pattern = re.compile(r'(CWE-([1-9][0-9]+))([,()])') @@ -431,49 +432,49 @@ class Hit(object): self.show_csv() return if output_format: - print "
  • ", + print("
  • ", end='') sys.stdout.write(h(self.filename)) if show_columns: - print ":%(line)s:%(column)s:" % self, + print(":%(line)s:%(column)s:" % self, end='') else: - print ":%(line)s:" % self, + print(":%(line)s:" % self, end='') if output_format: - print "", + print(" ", end='') # Extra space before risk level in text, makes it easier to find: - print " [%(level)s]" % self, + print(" [%(level)s]" % self, end=' ') if output_format: - print "", - print "(%(category)s)" % self, + print(" ", end='') + print("(%(category)s)" % self, end=' ') if output_format: - print "", - print h("%(name)s:" % self), + print(" ", end='') + print(h("%(name)s:" % self), end='') main_text = h("%(warning)s. " % self) if output_format: # Create HTML link to CWE definitions main_text = link_cwe_pattern.sub( r'\1\3', main_text) if single_line: - print main_text, + print(main_text, end='') if self.suggestion: - print h(self.suggestion) + ".", - print h(self.note), + print(" " + h(self.suggestion) + ".", end='') + print(' ' + h(self.note), end='') else: if self.suggestion: main_text = main_text + h(self.suggestion) + ". " main_text = main_text + h(self.note) - print + print() print_multi_line(main_text) if output_format: - print "", - print + print(" ", end='') + print() if show_context: if output_format: - print "
    "
    -            print h(self.context_text)
    +                print("
    ")
    +            print(h(self.context_text))
                 if output_format:
    -                print "
    " + print("
    ") # The "hitlist" is the list of all hits (warnings) found so far. @@ -499,7 +500,7 @@ def add_warning(hit): def internal_warn(message): - print h(message) + print(h(message)) # C Language Specific @@ -1442,9 +1443,9 @@ def process_c_file(f, patch_infos): # This file isn't in the patch list, so don't bother analyzing it. if not quiet: if output_format: - print "Skipping unpatched file ", h(f), "
    " + print("Skipping unpatched file ", h(f), "
    ") else: - print "Skipping unpatched file", f + print("Skipping unpatched file", f) sys.stdout.flush() return @@ -1453,13 +1454,13 @@ def process_c_file(f, patch_infos): else: # Symlinks should never get here, but just in case... if (not allowlink) and os.path.islink(f): - print "BUG! Somehow got a symlink in process_c_file!" + print("BUG! Somehow got a symlink in process_c_file!") num_links_skipped = num_links_skipped + 1 return try: input = open(f, "r") except BaseException: - print "Error: failed to open", h(f) + print("Error: failed to open", h(f)) sys.exit(1) # Read ENTIRE file into memory. Use readlines() to convert \n if necessary. @@ -1472,9 +1473,9 @@ def process_c_file(f, patch_infos): if not quiet: if output_format: - print "Examining", h(f), "
    " + print("Examining", h(f), "
    ") else: - print "Examining", f + print("Examining", f) sys.stdout.flush() text = string.join(input.readlines(), "") @@ -1606,8 +1607,8 @@ def expand_ruleset(ruleset): if string.find(rule, "|") != -1: # We found a rule to expand. for newrule in string.split(rule, "|"): if newrule in ruleset: - print "Error: Rule %s, when expanded, overlaps %s" % ( - rule, newrule) + print("Error: Rule %s, when expanded, overlaps %s" % ( + rule, newrule)) sys.exit(1) ruleset[newrule] = ruleset[rule] del ruleset[rule] @@ -1620,18 +1621,18 @@ def display_ruleset(ruleset): sortedkeys = sorted(ruleset.keys()) # Now, print them out: for key in sortedkeys: - print key + "\t" + str( + print(key + "\t" + str( ruleset[key][1] - ) + "\t" + ruleset[key][2] # function name, default level, default warning + ) + "\t" + ruleset[key][2]) # function name, default level, default warning def initialize_ruleset(): expand_ruleset(c_ruleset) if showheading: - print "Number of rules (primarily dangerous function names) in C/C++ ruleset:", len( - c_ruleset) + print("Number of rules (primarily dangerous function names) in C/C++ ruleset:", len( + c_ruleset)) if output_format: - print "

    " + print("

    ") if list_rules: display_ruleset(c_ruleset) sys.exit(0) @@ -1653,20 +1654,20 @@ def display_header(): print( '') - print "" - print "" - print '' - print "Flawfinder Results" - print '' - print '' - print "" - print "" - print "

    Flawfinder Results

    " - print "Here are the security scan results from" - print 'Flawfinder version %s,' % version - print '(C) 2001-2017 David A. Wheeler.' + print("") + print("") + print('') + print("Flawfinder Results") + print('') + print('') + print("") + print("") + print("

    Flawfinder Results

    ") + print("Here are the security scan results from") + print('Flawfinder version %s,' % version) + print('(C) 2001-2017 David A. Wheeler.') else: - print "Flawfinder version %s, (C) 2001-2017 David A. Wheeler." % version + print("Flawfinder version %s, (C) 2001-2017 David A. Wheeler." % version) displayed_header = 1 @@ -1780,7 +1781,7 @@ def process_file_args(files, patch_infos): def usage(): - print """ + print(""" flawfinder [--help | -h] [--version] [--listrules] [--allowlink] [--followdotdir] [--nolink] [--patch filename | -P filename] @@ -1866,7 +1867,7 @@ flawfinder [--help | -h] [--version] [--listrules] For more information, please consult the manpage or available documentation. -""" +""") def process_options(): @@ -1944,19 +1945,19 @@ def process_options(): loadhitlist = value display_header() if showheading: - print "Loading hits from", value + print("Loading hits from", value) elif opt == "--savehitlist": savehitlist = value display_header() if showheading: - print "Saving hitlist to", value + print("Saving hitlist to", value) elif opt == "--diffhitlist": diffhitlist = value display_header() if showheading: - print "Showing hits not in", value + print("Showing hits not in", value) elif opt == "--version": - print version + print(version) sys.exit(0) elif opt in ['-h', '-?', '--help']: # We accept "-?" but do not document it. On Unix-like systems the @@ -1977,7 +1978,7 @@ def process_options(): # use "getopt.error" here so it's compatible with both # Python 1.5 and Python 2. except getopt.error as text: - print "*** getopt error:", text + print("*** getopt error:", text) usage() sys.exit(1) @@ -1993,7 +1994,7 @@ def process_files(): patch_infos = load_patch_info(patch_file) files = sys.argv[1:] if not files: - print "*** No input files" + print("*** No input files") return None process_file_args(files, patch_infos) return 1 @@ -2009,13 +2010,13 @@ def show_final_results(): for i in range(0, 6): # Initialize count_per_level count_per_level_and_up[i] = 0 if show_immediately or not quiet: # Separate the final results. - print + print() if showheading: if output_format: - print "

    Final Results

    " + print("

    Final Results

    ") else: - print "FINAL RESULTS:" - print + print("FINAL RESULTS:") + print() hitlist.sort() # Display results. The HTML format now uses #
      so that the format differentiates each entry. @@ -2025,125 +2026,125 @@ def show_final_results(): diff_file = open(diffhitlist) diff_hitlist = pickle.load(diff_file) if output_format: - print "
        " + print("
          ") for hit in hitlist: if hit not in diff_hitlist: hit.show() count_per_level[hit.level] = count_per_level[hit.level] + 1 count = count + 1 if output_format: - print "
        " + print("
      ") diff_file.close() else: if output_format: - print "
        " + print("
          ") for hit in hitlist: hit.show() count_per_level[hit.level] = count_per_level[hit.level] + 1 if output_format: - print "
        " + print("
      ") count = len(hitlist) # Done with list, show the post-hitlist summary. if showheading: if output_format: - print "

      Analysis Summary

      " + print("

      Analysis Summary

      ") else: - print - print "ANALYSIS SUMMARY:" + print() + print("ANALYSIS SUMMARY:") if output_format: - print "

      " + print("

      ") else: - print + print() if count > 0: - print "Hits =", count + print("Hits =", count) else: - print "No hits found." + print("No hits found.") if output_format: - print "
      " + print("
      ") # Compute the amount of time spent, and lines analyzed/second. # By computing time here, we also include the time for # producing the list of hits, which is reasonable. time_analyzing = time.time() - starttime if required_regex: - print "Hits limited to regular expression " + required_regex - print "Lines analyzed = %d" % sumlines, + print("Hits limited to regular expression " + required_regex) + print("Lines analyzed = %d" % sumlines, end='') if time_analyzing > 0 and not omit_time: # Avoid divide-by-zero. - print "in approximately %.2f seconds (%.0f lines/second)" % ( - time_analyzing, (sumlines / time_analyzing)) + print(" in approximately %.2f seconds (%.0f lines/second)" % ( + time_analyzing, (sumlines / time_analyzing))) else: - print + print() if output_format: - print "
      " - print "Physical Source Lines of Code (SLOC) = %d" % sloc + print("
      ") + print("Physical Source Lines of Code (SLOC) = %d" % sloc) if output_format: - print "
      " + print("
      ") # Output hits@each level. - print "Hits@level =", + print("Hits@level =", end='') for i in range(0, 6): - print "[%d] %3d" % (i, count_per_level[i]), + print(" [%d] %3d" % (i, count_per_level[i]), end='') if output_format: - print "
      " + print("
      ") else: - print + print() # Compute hits at "level x or higher" - print "Hits@level+ =", + print("Hits@level+ =", end='') for i in range(0, 6): for j in range(i, 6): count_per_level_and_up[ i] = count_per_level_and_up[i] + count_per_level[j] # Display hits at "level x or higher" for i in range(0, 6): - print "[%d+] %3d" % (i, count_per_level_and_up[i]), + print(" [%d+] %3d" % (i, count_per_level_and_up[i]), end='') if output_format: - print "
      " + print("
      ") else: - print + print() if sloc > 0: - print "Hits/KSLOC@level+ =", + print("Hits/KSLOC@level+ =", end='') for i in range(0, 6): - print "[%d+] %3g" % ( - i, count_per_level_and_up[i] * 1000.0 / sloc), + print(" [%d+] %3g" % ( + i, count_per_level_and_up[i] * 1000.0 / sloc), end='') if output_format: - print "
      " + print("
      ") else: - print + print() # if num_links_skipped: - print "Symlinks skipped =", num_links_skipped, "(--allowlink overrides but see doc for security issue)" + print("Symlinks skipped =", num_links_skipped, "(--allowlink overrides but see doc for security issue)") if output_format: - print "
      " + print("
      ") if num_dotdirs_skipped: - print "Dot directories skipped =", num_dotdirs_skipped, "(--followdotdir overrides)" + print("Dot directories skipped =", num_dotdirs_skipped, "(--followdotdir overrides)") if output_format: - print "
      " + print("
      ") if num_ignored_hits > 0: - print "Suppressed hits =", num_ignored_hits, "(use --neverignore to show them)" + print("Suppressed hits =", num_ignored_hits, "(use --neverignore to show them)") if output_format: - print "
      " - print "Minimum risk level = %d" % minimum_level + print("
      ") + print("Minimum risk level = %d" % minimum_level) if output_format: - print "
      " + print("
      ") if count > 0: - print "Not every hit is necessarily a security vulnerability." + print("Not every hit is necessarily a security vulnerability.") if output_format: - print "
      " - print "There may be other security vulnerabilities; review your code!" + print("
      ") + print("There may be other security vulnerabilities; review your code!") if output_format: - print "
      " - print "See 'Secure Programming for Linux and Unix HOWTO'" - print "(http://www.dwheeler.com/secure-programs) for more information." + print("
      ") + print("See 'Secure Programming for Linux and Unix HOWTO'") + print("(http://www.dwheeler.com/secure-programs) for more information.") else: - print "See 'Secure Programming for Linux and Unix HOWTO'" - print "(http://www.dwheeler.com/secure-programs) for more information." + print("See 'Secure Programming for Linux and Unix HOWTO'") + print("(http://www.dwheeler.com/secure-programs) for more information.") if output_format: - print "" - print "" + print("") + print("") def save_if_desired(): # We'll save entire hitlist, even if only differences displayed. if savehitlist: - print "Saving hitlist to", savehitlist + print("Saving hitlist to", savehitlist) f = open(savehitlist, "w") pickle.dump(hitlist, f) f.close() @@ -2162,4 +2163,4 @@ if __name__ == '__main__': try: flawfind() except KeyboardInterrupt: - print "*** Flawfinder interrupted" + print("*** Flawfinder interrupted")