flawfinder-2.0.19/000755 000765 000024 00000000000 14112766763 014703 5ustar00dwheelerstaff000000 000000 flawfinder-2.0.19/flawfinder.spec000644 000765 000024 00000002341 14112766010 017661 0ustar00dwheelerstaff000000 000000 Name: flawfinder Summary: Examines C/C++ source code for security flaws Version: 2.0.19 Release: 1%{?dist} License: GPLv2+ Group: Development/Tools URL: http://dwheeler.com/flawfinder/ Source: http://dwheeler.com/flawfinder/%{name}-%{version}.tar.gz Requires: python BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %description Flawfinder scans through C/C++ source code, identifying lines ("hits") with potential security flaws. By default it reports hits sorted by severity, with the riskiest lines first. %prep %setup -q %build make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT install -m755 -D flawfinder ${RPM_BUILD_ROOT}%{_bindir}/flawfinder install -m644 -D flawfinder.1 ${RPM_BUILD_ROOT}%{_mandir}/man1/flawfinder.1 %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc README.md ChangeLog COPYING flawfinder.ps %{_bindir}/* %{_mandir}/man1/* %changelog * Mon Aug 27 2007 Horst H. von Brand 1.27-2 - Fix specfile as per Fedora guidelines * Sat Feb 1 2003 Jose Pedro Oliveira - changed build architecture to noarch - replaced hardcoded directories by rpm macros - removed several rpmlint warnings/errors # vim:set ai ts=4 sw=4: flawfinder-2.0.19/flawfinder.py000755 000765 000024 00000314430 14112765756 017407 0ustar00dwheelerstaff000000 000000 #!/usr/bin/env python """flawfinder: Find potential security flaws ("hits") in source code. Usage: flawfinder [options] [source_code_file]+ See the man page for a description of the options.""" # The default output is as follows: # filename:line_number [risk_level] (type) function_name: message # where "risk_level" goes from 0 to 5. 0=no risk, 5=maximum risk. # The final output is sorted by risk level, most risky first. # Optionally ":column_number" can be added after the line number. # # Currently this program can only analyze C/C++ code. # # Copyright (C) 2001-2019 David A. Wheeler. # This is released under the # GNU General Public License (GPL) version 2 or later (GPL-2.0+): # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # This code is written to run on both Python 2.7 and Python 3. # The Python developers did a *terrible* job when they transitioned # to Python version 3, as I have documented elsewhere. # Thankfully, more recent versions of Python 3, and the most recent version of # Python 2, make it possible (though ugly) to write code that runs on both. # That *finally* makes it possible to semi-gracefully transition. from __future__ import division from __future__ import print_function import functools import sys import re import string import getopt import pickle # To support load/save/diff of hitlist import os import glob import operator # To support filename expansion on Windows import time import csv # To support generating CSV format import hashlib import json version = "2.0.19" # Program Options - these are the default values. # TODO: Switch to boolean types where appropriate. # We didn't use boolean types originally because this program # predates Python's PEP 285, which added boolean types to Python 2.3. # Even after Python 2.3 was released, we wanted to run on older versions. # That's irrelevant today, but since "it works" there hasn't been a big # rush to change it. show_context = 0 minimum_level = 1 show_immediately = 0 show_inputs = 0 # Only show inputs? falsepositive = 0 # Work to remove false positives? allowlink = 0 # Allow symbolic links? skipdotdir = 1 # If 1, don't recurse into dirs beginning with "." # Note: This doesn't affect the command line. num_links_skipped = 0 # Number of links skipped. num_dotdirs_skipped = 0 # Number of dotdirs skipped. show_columns = 0 never_ignore = 0 # If true, NEVER ignore problems, even if directed. list_rules = 0 # If true, list the rules (helpful for debugging) patch_file = "" # File containing (unified) diff output. loadhitlist = None savehitlist = None diffhitlist_filename = None quiet = 0 showheading = 1 # --dataonly turns this off output_format = 0 # 0 = normal, 1 = html. single_line = 0 # 1 = singleline (can 't be 0 if html) csv_output = 0 # 1 = Generate CSV csv_writer = None sarif_output = 0 # 1 = Generate SARIF report omit_time = 0 # 1 = omit time-to-run (needed for testing) required_regex = None # If non-None, regex that must be met to report required_regex_compiled = None ERROR_ON_DISABLED_VALUE = 999 error_level = ERROR_ON_DISABLED_VALUE # Level where we're return error code error_level_exceeded = False displayed_header = 0 # Have we displayed the header yet? num_ignored_hits = 0 # Number of ignored hits (used if never_ignore==0) def error(message): sys.stderr.write("Error: %s\n" % message) # Support routines: find a pattern. # To simplify the calling convention, several global variables are used # and these support routines are defined, in an attempt to make the # actual calls simpler and clearer. # filename = "" # Source filename. linenumber = 0 # Linenumber from original file. ignoreline = -1 # Line number to ignore. sumlines = 0 # Number of lines (total) examined. sloc = 0 # Physical SLOC starttime = time.time() # Used to determine analyzed lines/second. # Send warning message. This is written this way to work on # Python version 2.5 through Python 3. def print_warning(message): sys.stderr.write("Warning: ") sys.stderr.write(message) sys.stderr.write("\n") sys.stderr.flush() def to_json(o): return json.dumps(o, default=lambda o: o.__dict__, sort_keys=False, indent=2) # The following implements the SarifLogger. # We intentionally merge all of flawfinder's functionality into 1 file # so it's trivial to copy & use elsewhere. class SarifLogger(object): _hitlist = None TOOL_NAME = "Flawfinder" TOOL_URL = "https://dwheeler.com/flawfinder/" TOOL_VERSION = version URI_BASE_ID = "SRCROOT" SARIF_SCHEMA = "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json" SARIF_SCHEMA_VERSION = "2.1.0" CWE_TAXONOMY_NAME = "CWE" CWE_TAXONOMY_URI = "https://raw.githubusercontent.com/sarif-standard/taxonomies/main/CWE_v4.4.sarif" CWE_TAXONOMY_GUID = "FFC64C90-42B6-44CE-8BEB-F6B7DAE649E5" def __init__ (self, hits): self._hitlist = hits def output_sarif(self): tool = { "driver": { "name": self.TOOL_NAME, "version": self.TOOL_VERSION, "informationUri": self.TOOL_URL, "rules": self._extract_rules(self._hitlist), "supportedTaxonomies": [{ "name": self.CWE_TAXONOMY_NAME, "guid": self.CWE_TAXONOMY_GUID, }], } } runs = [{ "tool": tool, "columnKind": "utf16CodeUnits", "results": self._extract_results(self._hitlist), "externalPropertyFileReferences": { "taxonomies": [{ "location": { "uri": self.CWE_TAXONOMY_URI, }, "guid": self.CWE_TAXONOMY_GUID, }], }, }] report = { "$schema": self.SARIF_SCHEMA, "version": self.SARIF_SCHEMA_VERSION, "runs": runs, } jsonstr = to_json(report) return jsonstr def _extract_rules(self, hitlist): rules = {} for hit in hitlist: if not hit.ruleid in rules: rules[hit.ruleid] = self._to_sarif_rule(hit) return list(rules.values()) def _extract_results(self, hitlist): results = [] for hit in hitlist: results.append(self._to_sarif_result(hit)) return results def _to_sarif_rule(self, hit): return { "id": hit.ruleid, "name": "{0}/{1}".format(hit.category, hit.name), "shortDescription": { "text": self._append_period(hit.warning), }, "defaultConfiguration": { "level": self._to_sarif_level(hit.defaultlevel), }, "helpUri": hit.helpuri(), "relationships": self._extract_relationships(hit.cwes()), } def _to_sarif_result(self, hit): return { "ruleId": hit.ruleid, "level": self._to_sarif_level(hit.level), "message": { "text": self._append_period("{0}/{1}:{2}".format(hit.category, hit.name, hit.warning)), }, "locations": [{ "physicalLocation": { "artifactLocation": { "uri": self._to_uri_path(hit.filename), "uriBaseId": self.URI_BASE_ID, }, "region": { "startLine": hit.line, "startColumn": hit.column, "endColumn": len(hit.context_text) + 1, "snippet": { "text": hit.context_text, } } } }], "fingerprints": { "contextHash/v1": hit.fingerprint() }, "rank": self._to_sarif_rank(hit.level), } def _extract_relationships(self, cwestring): # example cwe string "CWE-119!/ CWE-120", "CWE-829, CWE-20" relationships = [] for cwe in re.split(',|/',cwestring): cwestr = cwe.strip() if cwestr: relationship = { "target": { "id": cwestr.replace("!", ""), "toolComponent": { "name": self.CWE_TAXONOMY_NAME, "guid": self.CWE_TAXONOMY_GUID, }, }, "kinds": [ "relevant" if cwestr[-1] != '!' else "incomparable" ], } relationships.append(relationship) return relationships @staticmethod def _to_sarif_level(level): # level 4 & 5 if level >= 4: return "error" # level 3 if level == 3: return "warning" # level 0 1 2 return "note" @staticmethod def _to_sarif_rank(level): #SARIF rank FF Level SARIF level Default Viewer Action #0.0 0 note Does not display by default #0.2 1 note Does not display by default #0.4 2 note Does not display by default #0.6 3 warning Displays by default, does not break build / other processes #0.8 4 error Displays by default, breaks build/ other processes #1.0 5 error Displays by default, breaks build/ other processes return level * 0.2 @staticmethod def _to_uri_path(path): return path.replace("\\", "/") @staticmethod def _append_period(text): return text if text[-1] == '.' else text + "." # The following code accepts unified diff format from both subversion (svn) # and GNU diff, which aren't well-documented. It gets filenames from # "Index:" if exists, else from the "+++ FILENAME ..." entry. # Note that this is different than some tools (which will use "+++" in # preference to "Index:"), but subversion's nonstandard format is easier # to handle this way. # Since they aren't well-documented, here's some info on the diff formats: # GNU diff format: # --- OLDFILENAME OLDTIMESTAMP # +++ NEWFILENAME NEWTIMESTAMP # @@ -OLDSTART,OLDLENGTH +NEWSTART,NEWLENGTH @@ # ... Changes where preceeding "+" is add, "-" is remove, " " is unchanged. # # ",OLDLENGTH" and ",NEWLENGTH" are optional (they default to 1). # GNU unified diff format doesn't normally output "Index:"; you use # the "+++/---" to find them (presuming the diff user hasn't used --label # to mess it up). # # Subversion format: # Index: FILENAME # --- OLDFILENAME (comment) # +++ NEWFILENAME (comment) # @@ -OLDSTART,OLDLENGTH +NEWSTART,NEWLENGTH @@ # # In subversion, the "Index:" always occurs, and note that paren'ed # comments are in the oldfilename/newfilename, NOT timestamps like # everyone else. # # Git format: # diff --git a/junk.c b/junk.c # index 03d668d..5b005a1 100644 # --- a/junk.c # +++ b/junk.c # @@ -6,4 +6,5 @@ main() { # # Single Unix Spec version 3 (http://www.unix.org/single_unix_specification/) # does not specify unified format at all; it only defines the older # (obsolete) context diff format. That format DOES use "Index:", but # only when the filename isn't specified otherwise. # We're only supporting unified format directly; if you have an older diff # format, use "patch" to apply it, and then use "diff -u" to create a # unified format. # diff_index_filename = re.compile(r'^Index:\s+(?P.*)') diff_git_filename = re.compile(r'^diff --git a/.* b/(?P.*)$') diff_newfile = re.compile(r'^\+\+\+\s(?P.*)$') diff_hunk = re.compile(r'^@@ -\d+(,\d+)?\s+\+(?P\d+)[, ].*@@') diff_line_added = re.compile(r'^\+[^+].*') diff_line_del = re.compile(r'^-[^-].*') # The "+++" newfile entries have the filename, followed by a timestamp # or " (comment)" postpended. # Timestamps can be of these forms: # 2005-04-24 14:21:39.000000000 -0400 # Mon Mar 10 15:13:12 1997 # Also, "newfile" can have " (comment)" postpended. Find and eliminate this. # Note that the expression below is Y10K (and Y100K) ready. :-). diff_findjunk = re.compile( r'^(?P.*)(' r'(\s\d\d\d\d+-\d\d-\d\d\s+\d\d:\d[0-9:.]+Z?(\s+[\-\+0-9A-Z]+)?)|' r'(\s[A-Za-z][a-z]+\s[A-za-z][a-z]+\s\d+\s\d+:\d[0-9:.]+Z?' r'(\s[\-\+0-9]*)?\s\d\d\d\d+)|' r'(\s\(.*\)))\s*$' ) def is_svn_diff(sLine): if sLine.find('Index:') != -1: return True return False def is_gnu_diff(sLine): if sLine.startswith('--- '): return True return False def is_git_diff(sLine): if sLine.startswith('diff --git a'): return True return False def svn_diff_get_filename(sLine): return diff_index_filename.match(sLine) def gnu_diff_get_filename(sLine): newfile_match = diff_newfile.match(sLine) if newfile_match: patched_filename = newfile_match.group('filename').strip() # Clean up filename - remove trailing timestamp and/or (comment). return diff_findjunk.match(patched_filename) return None def git_diff_get_filename(sLine): return diff_git_filename.match(sLine) # For each file found in the file input_patch_file, keep the # line numbers of the new file (after patch is applied) which are added. # We keep this information in a hash table for a quick access later. # def load_patch_info(input_patch_file): patch = {} line_counter = 0 initial_number = 0 try: hPatch = open(input_patch_file, 'r') except BaseException: print("Error: failed to open", h(input_patch_file)) sys.exit(10) patched_filename = "" # Name of new file patched by current hunk. sLine = hPatch.readline() # Heuristic to determine if it's a svn diff, git diff, or a GNU diff. if is_svn_diff(sLine): fn_get_filename = svn_diff_get_filename elif is_git_diff(sLine): fn_get_filename = git_diff_get_filename elif is_gnu_diff(sLine): fn_get_filename = gnu_diff_get_filename else: print("Error: Unrecognized patch format") sys.exit(11) while True: # Loop-and-half construct. Read a line, end loop when no more # This is really a sequence of if ... elsif ... elsif..., but # because Python forbids '=' in conditions, we do it this way. filename_match = fn_get_filename(sLine) if filename_match: patched_filename = filename_match.group('filename').strip() if patched_filename in patch: error("filename occurs more than once in the patch: %s" % patched_filename) sys.exit(12) else: patch[patched_filename] = {} else: hunk_match = diff_hunk.match(sLine) if hunk_match: if patched_filename == "": error( "wrong type of patch file : " "we have a line number without having seen a filename" ) sys.exit(13) initial_number = hunk_match.group('linenumber') line_counter = 0 else: line_added_match = diff_line_added.match(sLine) if line_added_match: line_added = line_counter + int(initial_number) patch[patched_filename][line_added] = True # Let's also warn about the lines above and below this one, # so that errors that "leak" into adjacent lines are caught. # Besides, if you're creating a patch, you had to at # least look at adjacent lines, # so you're in a position to fix them. patch[patched_filename][line_added - 1] = True patch[patched_filename][line_added + 1] = True line_counter += 1 else: line_del_match = diff_line_del.match(sLine) if line_del_match is None: line_counter += 1 sLine = hPatch.readline() if sLine == '': break # Done reading. return patch def htmlize(s): # Take s, and return legal (UTF-8) HTML. return s.replace("&", "&").replace("<", "<").replace(">", ">") def h(s): # htmlize s if we're generating html, otherwise just return s. return htmlize(s) if output_format else s def print_multi_line(text): # Print text as multiple indented lines. width = 78 prefix = " " starting_position = len(prefix) + 1 # print(prefix, end='') position = starting_position # for w in text.split(): if len(w) + position >= width: print() print(prefix, end='') position = starting_position print(' ', end='') print(w, end='') 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]+))([,()!/])') # This matches the CWE data, including multiple entries. find_cwe_pattern = re.compile(r'\(CWE-[^)]*\)') class Hit(object): """ Each instance of Hit is a warning of some kind in a source code file. See the rulesets, which define the conditions for triggering a hit. Hit is initialized with a tuple containing the following: hook: function to call when function name found. level: (default) warning level, 0-5. 0=no problem, 5=very risky. warning: warning (text saying what's the problem) suggestion: suggestion (text suggesting what to do instead) category: One of "buffer" (buffer overflow), "race" (race condition), "tmpfile" (temporary file creation), "format" (format string). Use "" if you don't have a better category. url: URL fragment reference. other: A dictionary with other settings. Other settings usually set: name: function name parameter: the function parameters (0th parameter null) input: set to 1 if the function inputs from external sources. start: start position (index) of the function name (in text) end: end position of the function name (in text) filename: name of file line: line number in file column: column in line in file context_text: text surrounding hit """ # Set default values: source_position = 2 # By default, the second parameter is the source. format_position = 1 # By default, the first parameter is the format. input = 0 # By default, this doesn't read input. note = "" # No additional notes. filename = "" # Empty string is filename. extract_lookahead = 0 # Normally don't extract lookahead. def __init__(self, data): hook, level, warning, suggestion, category, url, other, ruleid = data self.hook, self.level, self.defaultlevel = hook, level, level self.warning, self.suggestion = warning, suggestion self.category, self.url = category, url self.ruleid = ruleid # These will be set later, but I set them here so that # analysis tools like PyChecker will know about them. self.column = 0 self.line = 0 self.name = "" self.context_text = "" for key in other: setattr(self, key, other[key]) def __getitem__(self, X): # Define this so this works: "%(line)" % hit return getattr(self, X) def __eq__(self, other): return (self.filename == other.filename and self.line == other.line and self.column == other.column and self.level == other.level and self.name == other.name) def __ne__(self, other): return not self == other # Return CWEs def cwes(self): result = find_cwe_pattern.search(self.warning) return result.group()[1:-1] if result else '' def fingerprint(self): """Return fingerprint of stripped context.""" m = hashlib.sha256() m.update(self.context_text.strip().encode('utf-8')) return m.hexdigest() # Help uri for each defined rule. e.g. "https://dwheeler.com/flawfinder#FF1002" # return first CWE link for now def helpuri(self): cwe = re.split(',|!', self.cwes())[0] + ")" return link_cwe_pattern.sub( r'https://cwe.mitre.org/data/definitions/\2.html', cwe) # Show as CSV format def show_csv(self): csv_writer.writerow([ self.filename, self.line, self.column, self.defaultlevel, self.level, self.category, self.name, self.warning + ".", self.suggestion + "." if self.suggestion else "", self.note, self.cwes(), self.context_text, self.fingerprint(), version, self.ruleid, self.helpuri() ]) def show(self): if csv_output: self.show_csv() return if sarif_output: return if output_format: print("
  • ", end='') sys.stdout.write(h(self.filename)) if show_columns: print(":%(line)s:%(column)s:" % self, end='') else: print(":%(line)s:" % self, end='') if output_format: print(" ", end='') # Extra space before risk level in text, makes it easier to find: print(" [%(level)s]" % self, end=' ') if output_format: print(" ", end='') print("(%(category)s)" % self, end=' ') if output_format: 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, end='') if self.suggestion: print(" " + h(self.suggestion) + ".", end='') print(' ' + h(self.note), end='') else: if self.suggestion: main_text += h(self.suggestion) + ". " main_text += h(self.note) print() print_multi_line(main_text) if output_format: print(" ", end='') print() if show_context: if output_format: print("
    ")
                print(h(self.context_text))
                if output_format:
                    print("
    ") # The "hitlist" is the list of all hits (warnings) found so far. # Use add_warning to add to it. hitlist = [] def add_warning(hit): global hitlist, num_ignored_hits if show_inputs and not hit.input: return if required_regex and (required_regex_compiled.search(hit.warning) is None): return if linenumber == ignoreline: num_ignored_hits += 1 else: hitlist.append(hit) if show_immediately: hit.show() def internal_warn(message): print(h(message), file=sys.stderr) # C Language Specific def extract_c_parameters(text, pos=0): "Return a list of the given C function's parameters, starting at text[pos]" # '(a,b)' produces ['', 'a', 'b'] i = pos # Skip whitespace and find the "("; if there isn't one, return []: while i < len(text): if text[i] == '(': break elif text[i] in string.whitespace: i += 1 else: return [] else: # Never found a reasonable ending. return [] i += 1 parameters = [""] # Insert 0th entry, so 1st parameter is parameter[1]. currentstart = i parenlevel = 1 curlylevel = 0 instring = 0 # 1=in double-quote, 2=in single-quote incomment = 0 while i < len(text): c = text[i] if instring: if c == '"' and instring == 1: instring = 0 elif c == "'" and instring == 2: instring = 0 # if \, skip next character too. The C/C++ rules for # \ are actually more complex, supporting \ooo octal and # \xhh hexadecimal (which can be shortened), # but we don't need to # parse that deeply, we just need to know we'll stay # in string mode: elif c == '\\': i += 1 elif incomment: if c == '*' and text[i:i + 2] == '*/': incomment = 0 i += 1 else: if c == '"': instring = 1 elif c == "'": instring = 2 elif c == '/' and text[i:i + 2] == '/*': incomment = 1 i += 1 elif c == '/' and text[i:i + 2] == '//': while i < len(text) and text[i] != "\n": i += 1 elif c == '\\' and text[i:i + 2] == '\\"': i += 1 # Handle exposed '\"' elif c == '(': parenlevel += 1 elif c == ',' and (parenlevel == 1): parameters.append( p_trailingbackslashes.sub('', text[currentstart:i]).strip()) currentstart = i + 1 elif c == ')': parenlevel -= 1 if parenlevel <= 0: parameters.append( p_trailingbackslashes.sub( '', text[currentstart:i]).strip()) # Re-enable these for debugging: # print " EXTRACT_C_PARAMETERS: ", text[pos:pos+80] # print " RESULTS: ", parameters return parameters elif c == '{': curlylevel += 1 elif c == '}': curlylevel -= 1 elif c == ';' and curlylevel < 1: internal_warn( "Parsing failed to find end of parameter list; " "semicolon terminated it in %s" % text[pos:pos + 200]) return parameters i += 1 internal_warn("Parsing failed to find end of parameter list in %s" % text[pos:pos + 200]) return [] # Treat unterminated list as an empty list # These patterns match gettext() and _() for internationalization. # This is compiled here, to avoid constant recomputation. # FIXME: assumes simple function call if it ends with ")", # so will get confused by patterns like gettext("hi") + function("bye") # In practice, this doesn't seem to be a problem; gettext() is usually # wrapped around the entire parameter. # The ?s makes it posible to match multi-line strings. gettext_pattern = re.compile(r'(?s)^\s*' 'gettext' r'\s*\((.*)\)\s*$') undersc_pattern = re.compile(r'(?s)^\s*' '_(T(EXT)?)?' r'\s*\((.*)\)\s*$') def strip_i18n(text): """Strip any internationalization function calls surrounding 'text'. In particular, strip away calls to gettext() and _(). """ match = gettext_pattern.search(text) if match: return match.group(1).strip() match = undersc_pattern.search(text) if match: return match.group(3).strip() return text p_trailingbackslashes = re.compile(r'(\s|\\(\n|\r))*$') p_c_singleton_string = re.compile(r'^\s*L?"([^\\]|\\[^0-6]|\\[0-6]+)?"\s*$') def c_singleton_string(text): "Returns true if text is a C string with 0 or 1 character." return 1 if p_c_singleton_string.search(text) else 0 # This string defines a C constant. p_c_constant_string = re.compile(r'^\s*L?"([^\\]|\\[^0-6]|\\[0-6]+)*"$') def c_constant_string(text): "Returns true if text is a constant C string." return 1 if p_c_constant_string.search(text) else 0 # Precompile patterns for speed. p_memcpy_sizeof = re.compile(r'sizeof\s*\(\s*([^)\s]*)\s*\)') p_memcpy_param_amp = re.compile(r'&?\s*(.*)') def c_memcpy(hit): if len(hit.parameters) < 4: # 3 parameters add_warning(hit) return m1 = re.search(p_memcpy_param_amp, hit.parameters[1]) m3 = re.search(p_memcpy_sizeof, hit.parameters[3]) if not m1 or not m3 or m1.group(1) != m3.group(1): add_warning(hit) def c_buffer(hit): source_position = hit.source_position if source_position <= len(hit.parameters) - 1: source = hit.parameters[source_position] if c_singleton_string(source): hit.level = 1 hit.note = "Risk is low because the source is a constant character." elif c_constant_string(strip_i18n(source)): hit.level = max(hit.level - 2, 1) hit.note = "Risk is low because the source is a constant string." add_warning(hit) p_dangerous_strncat = re.compile(r'^\s*sizeof\s*(\(\s*)?[A-Za-z_$0-9]+' r'\s*(\)\s*)?(-\s*1\s*)?$') # This is a heuristic: constants in C are usually given in all # upper case letters. Yes, this need not be true, but it's true often # enough that it's worth using as a heuristic. # We check because strncat better not be passed a constant as the length! p_looks_like_constant = re.compile(r'^\s*[A-Z][A-Z_$0-9]+\s*(-\s*1\s*)?$') def c_strncat(hit): if len(hit.parameters) > 3: # A common mistake is to think that when calling strncat(dest,src,len), # that "len" means the ENTIRE length of the destination. # This isn't true, # it must be the length of the characters TO BE ADDED at most. # Which is one reason that strlcat is better than strncat. # We'll detect a common case of this error; if the length parameter # is of the form "sizeof(dest)", we have this error. # Actually, sizeof(dest) is okay if the dest's first character # is always \0, # but in that case the programmer should use strncpy, NOT strncat. # The following heuristic will certainly miss some dangerous cases, but # it at least catches the most obvious situation. # This particular heuristic is overzealous; it detects ANY sizeof, # instead of only the sizeof(dest) (where dest is given in # hit.parameters[1]). # However, there aren't many other likely candidates for sizeof; some # people use it to capture just the length of the source, but this is # just as dangerous, since then it absolutely does NOT take care of # the destination maximum length in general. # It also detects if a constant is given as a length, if the # constant follows common C naming rules. length_text = hit.parameters[3] if p_dangerous_strncat.search( length_text) or p_looks_like_constant.search(length_text): hit.level = 5 hit.note = ( "Risk is high; the length parameter appears to be a constant, " "instead of computing the number of characters left.") add_warning(hit) return c_buffer(hit) def c_printf(hit): format_position = hit.format_position if format_position <= len(hit.parameters) - 1: # Assume that translators are trusted to not insert "evil" formats: source = strip_i18n(hit.parameters[format_position]) if c_constant_string(source): # Parameter is constant, so there's no risk of # format string problems. # At one time we warned that very old systems sometimes incorrectly # allow buffer overflows on snprintf/vsnprintf, but those systems # are now very old, and snprintf is an important potential tool for # countering buffer overflows. # We'll pass it on, just in case it's needed, but at level 0 risk. hit.level = 0 hit.note = "Constant format string, so not considered risky." add_warning(hit) p_dangerous_sprintf_format = re.compile(r'%-?([0-9]+|\*)?s') # sprintf has both buffer and format vulnerabilities. def c_sprintf(hit): source_position = hit.source_position if hit.parameters is None: # Serious parameter problem, e.g., none, or a string constant that # never finishes. hit.warning = "format string parameter problem" hit.suggestion = "Check if required parameters present and quotes close." hit.level = 4 hit.category = "format" hit.url = "" elif source_position <= len(hit.parameters) - 1: source = hit.parameters[source_position] if c_singleton_string(source): hit.level = 1 hit.note = "Risk is low because the source is a constant character." else: source = strip_i18n(source) if c_constant_string(source): if not p_dangerous_sprintf_format.search(source): hit.level = max(hit.level - 2, 1) hit.note = "Risk is low because the source has a constant maximum length." # otherwise, warn of potential buffer overflow (the default) else: # Ho ho - a nonconstant format string - we have a different # problem. hit.warning = "Potential format string problem (CWE-134)" hit.suggestion = "Make format string constant" hit.level = 4 hit.category = "format" hit.url = "" add_warning(hit) p_dangerous_scanf_format = re.compile(r'%s') p_low_risk_scanf_format = re.compile(r'%[0-9]+s') def c_scanf(hit): format_position = hit.format_position if format_position <= len(hit.parameters) - 1: # Assume that translators are trusted to not insert "evil" formats; # it's not clear that translators will be messing with INPUT formats, # but it's possible so we'll account for it. source = strip_i18n(hit.parameters[format_position]) if c_constant_string(source): if p_dangerous_scanf_format.search(source): pass # Accept default. elif p_low_risk_scanf_format.search(source): # This is often okay, but sometimes extremely serious. hit.level = 1 hit.warning = ("It's unclear if the %s limit in the " "format string is small enough (CWE-120)") hit.suggestion = ("Check that the limit is sufficiently " "small, or use a different input function") else: # No risky scanf request. # We'll pass it on, just in case it's needed, but at level 0 # risk. hit.level = 0 hit.note = "No risky scanf format detected." else: # Format isn't a constant. hit.note = ("If the scanf format is influenceable " "by an attacker, it's exploitable.") add_warning(hit) p_dangerous_multi_byte = re.compile(r'^\s*sizeof\s*(\(\s*)?[A-Za-z_$0-9]+' r'\s*(\)\s*)?(-\s*1\s*)?$') p_safe_multi_byte = re.compile( r'^\s*sizeof\s*(\(\s*)?[A-Za-z_$0-9]+\s*(\)\s*)?' r'/\s*sizeof\s*\(\s*?[A-Za-z_$0-9]+\s*\[\s*0\s*\]\)\s*(-\s*1\s*)?$') def c_multi_byte_to_wide_char(hit): # Unfortunately, this doesn't detect bad calls when it's a #define or # constant set by a sizeof(), but trying to do so would create # FAR too many false positives. if len(hit.parameters) - 1 >= 6: num_chars_to_copy = hit.parameters[6] if p_dangerous_multi_byte.search(num_chars_to_copy): hit.level = 5 hit.note = ( "Risk is high, it appears that the size is given as bytes, but the " "function requires size as characters.") elif p_safe_multi_byte.search(num_chars_to_copy): # This isn't really risk-free, since it might not be the destination, # or the destination might be a character array (if it's a char pointer, # the pattern is actually quite dangerous, but programmers # are unlikely to make that error). hit.level = 1 hit.note = "Risk is very low, the length appears to be in characters not bytes." add_warning(hit) p_null_text = re.compile(r'^ *(NULL|0|0x0) *$') def c_hit_if_null(hit): null_position = hit.check_for_null if null_position <= len(hit.parameters) - 1: null_text = hit.parameters[null_position] if p_null_text.search(null_text): add_warning(hit) else: return add_warning(hit) # If insufficient # of parameters. p_static_array = re.compile(r'^[A-Za-z_]+\s+[A-Za-z0-9_$,\s\*()]+\[[^]]') def c_static_array(hit): # This is cheating, but it does the job for most real code. # In some cases it will match something that it shouldn't. # We don't match ALL arrays, just those of certain types (e.g., char). # In theory, any array can overflow, but in practice it seems that # certain types are far more prone to problems, so we just report those. if p_static_array.search(hit.lookahead): add_warning(hit) # Found a static array, warn about it. def cpp_unsafe_stl(hit): # Use one of the overloaded classes from the STL in C++14 and higher # instead of the = 4 and any(flag in hit.parameters[3] for flag in safe_load_library_flags)): return normal(hit) def normal(hit): add_warning(hit) # Ignore "system" if it's "system::" (that is, a C++ namespace such as # boost::system::...), because that produces too many false positives. # We ignore spaces before "::" def found_system(hit): follow_text = hit.lookahead[len(hit.name):].lstrip() if not follow_text.startswith('::'): normal(hit) # "c_ruleset": the rules for identifying "hits" in C (potential warnings). # It's a dictionary, where the key is the function name causing the hit, # and the value is a tuple with the following format: # (hook, level, warning, suggestion, category, {other}) # See the definition for class "Hit". # The key can have multiple values separated with "|". # For more information on Microsoft banned functions, see: # http://msdn.microsoft.com/en-us/library/bb288454.aspx c_ruleset = { "strcpy": (c_buffer, 4, "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)", "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)", "buffer", "", {}, "FF1001"), "strcpyA|strcpyW|StrCpy|StrCpyA|lstrcpyA|lstrcpyW|_tccpy|_mbccpy|_ftcscpy|_mbsncpy|StrCpyN|StrCpyNA|StrCpyNW|StrNCpy|strcpynA|StrNCpyA|StrNCpyW|lstrcpynA|lstrcpynW": # We need more info on these functions; I got their names from the # Microsoft "banned" list. For now, just use "normal" to process them # instead of "c_buffer". (normal, 4, "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)", "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)", "buffer", "", {}, "FF1002"), "lstrcpy|wcscpy|_tcscpy|_mbscpy": (c_buffer, 4, "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)", "Consider using a function version that stops copying at the end of the buffer", "buffer", "", {}, "FF1003"), "memcpy|CopyMemory|bcopy": (c_memcpy, 2, # I've found this to have a lower risk in practice. "Does not check for buffer overflows when copying to destination (CWE-120)", "Make sure destination can always hold the source data", "buffer", "", {}, "FF1004"), "strcat": (c_buffer, 4, "Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120)", "Consider using strcat_s, strncat, strlcat, or snprintf (warning: strncat is easily misused)", "buffer", "", {}, "FF1005"), "lstrcat|wcscat|_tcscat|_mbscat": (c_buffer, 4, "Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120)", "", "buffer", "", {}, "FF1006"), # TODO: Do more analysis. Added because they're in MS banned list. "StrCat|StrCatA|StrcatW|lstrcatA|lstrcatW|strCatBuff|StrCatBuffA|StrCatBuffW|StrCatChainW|_tccat|_mbccat|_ftcscat|StrCatN|StrCatNA|StrCatNW|StrNCat|StrNCatA|StrNCatW|lstrncat|lstrcatnA|lstrcatnW": (normal, 4, "Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120)", "", "buffer", "", {}, "FF1007"), "strncpy": (c_buffer, 1, # Low risk level, because this is often used correctly when FIXING security # problems, and raising it to a higher risk level would cause many false # positives. "Easily used incorrectly; doesn't always \\0-terminate or " "check for invalid pointers [MS-banned] (CWE-120)", "", "buffer", "", {}, "FF1008"), "lstrcpyn|wcsncpy|_tcsncpy|_mbsnbcpy": (c_buffer, 1, # Low risk level, because this is often used correctly when FIXING security # problems, and raising it to a higher risk levle would cause many false # positives. "Easily used incorrectly; doesn't always \\0-terminate or " "check for invalid pointers [MS-banned] (CWE-120)", "", "buffer", "", {}, "FF1009"), "strncat": (c_strncat, 1, # Low risk level, because this is often used correctly when # FIXING security problems, and raising it to a # higher risk level would cause many false positives. "Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120)", "Consider strcat_s, strlcat, snprintf, or automatically resizing strings", "buffer", "", {}, "FF1010"), "lstrcatn|wcsncat|_tcsncat|_mbsnbcat": (c_strncat, 1, # Low risk level, because this is often used correctly when FIXING security # problems, and raising it to a higher risk level would cause many false # positives. "Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120)", "Consider strcat_s, strlcat, or automatically resizing strings", "buffer", "", {}, "FF1011"), "strccpy|strcadd": (normal, 1, "Subject to buffer overflow if buffer is not as big as claimed (CWE-120)", "Ensure that destination buffer is sufficiently large", "buffer", "", {}, "FF1012"), "char|TCHAR|wchar_t": # This isn't really a function call, but it works. (c_static_array, 2, "Statically-sized arrays can be improperly restricted, " "leading to potential overflows or other issues (CWE-119!/CWE-120)", "Perform bounds checking, use functions that limit length, " "or ensure that the size is larger than the maximum possible length", "buffer", "", {'extract_lookahead': 1}, "FF1013"), "gets|_getts": (normal, 5, "Does not check for buffer overflows (CWE-120, CWE-20)", "Use fgets() instead", "buffer", "", {'input': 1}, "FF1014"), # The "sprintf" hook will raise "format" issues instead if appropriate: "sprintf|vsprintf|swprintf|vswprintf|_stprintf|_vstprintf": (c_sprintf, 4, "Does not check for buffer overflows (CWE-120)", "Use sprintf_s, snprintf, or vsnprintf", "buffer", "", {}, "FF1015"), "printf|vprintf|vwprintf|vfwprintf|_vtprintf|wprintf": (c_printf, 4, "If format strings can be influenced by an attacker, they can be exploited (CWE-134)", "Use a constant for the format specification", "format", "", {}, "FF1016"), "fprintf|vfprintf|_ftprintf|_vftprintf|fwprintf|fvwprintf": (c_printf, 4, "If format strings can be influenced by an attacker, they can be exploited (CWE-134)", "Use a constant for the format specification", "format", "", {'format_position': 2}, "FF1017"), # The "syslog" hook will raise "format" issues. "syslog": (c_printf, 4, "If syslog's format strings can be influenced by an attacker, " "they can be exploited (CWE-134)", "Use a constant format string for syslog", "format", "", {'format_position': 2}, "FF1018"), "snprintf|vsnprintf|_snprintf|_sntprintf|_vsntprintf": (c_printf, 4, "If format strings can be influenced by an attacker, they can be " "exploited, and note that sprintf variations do not always \\0-terminate (CWE-134)", "Use a constant for the format specification", "format", "", {'format_position': 3}, "FF1019"), "scanf|vscanf|wscanf|_tscanf|vwscanf": (c_scanf, 4, "The scanf() family's %s operation, without a limit specification, " "permits buffer overflows (CWE-120, CWE-20)", "Specify a limit to %s, or use a different input function", "buffer", "", {'input': 1}, "FF1020"), "fscanf|sscanf|vsscanf|vfscanf|_ftscanf|fwscanf|vfwscanf|vswscanf": (c_scanf, 4, "The scanf() family's %s operation, without a limit specification, " "permits buffer overflows (CWE-120, CWE-20)", "Specify a limit to %s, or use a different input function", "buffer", "", {'input': 1, 'format_position': 2}, "FF1021"), "strlen|wcslen|_tcslen|_mbslen": (normal, # Often this isn't really a risk, and even when it is, at worst it # often causes a program crash (and nothing worse). 1, "Does not handle strings that are not \\0-terminated; " "if given one it may perform an over-read (it could cause a crash " "if unprotected) (CWE-126)", "", "buffer", "", {}, "FF1022"), "MultiByteToWideChar": # Windows (c_multi_byte_to_wide_char, 2, # Only the default - this will be changed in many cases. "Requires maximum length in CHARACTERS, not bytes (CWE-120)", "", "buffer", "", {}, "FF1023"), "streadd|strecpy": (normal, 4, "This function does not protect against buffer overflows (CWE-120)", "Ensure the destination has 4 times the size of the source, to leave room for expansion", "buffer", "dangers-c", {}, "FF1024"), "strtrns": (normal, 3, "This function does not protect against buffer overflows (CWE-120)", "Ensure that destination is at least as long as the source", "buffer", "dangers-c", {}, "FF1025"), "realpath": (normal, 3, "This function does not protect against buffer overflows, " "and some implementations can overflow internally (CWE-120/CWE-785!)", "Ensure that the destination buffer is at least of size MAXPATHLEN, and" "to protect against implementation problems, the input argument " "should also be checked to ensure it is no larger than MAXPATHLEN", "buffer", "dangers-c", {}, "FF1026"), "getopt|getopt_long": (normal, 3, "Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20)", "Check implementation on installation, or limit the size of all string inputs", "buffer", "dangers-c", {'input': 1}, "FF1027"), "getwd": (normal, 3, "This does not protect against buffer overflows " "by itself, so use with caution (CWE-120, CWE-20)", "Use getcwd instead", "buffer", "dangers-c", {'input': 1}, "FF1028"), # fread not included here; in practice I think it's rare to mistake it. "getchar|fgetc|getc|read|_gettc": (normal, 1, "Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20)", "", "buffer", "dangers-c", {'input': 1}, "FF1029"), "access": # ???: TODO: analyze TOCTOU more carefully. (normal, 4, "This usually indicates a security flaw. If an " "attacker can change anything along the path between the " "call to access() and the file's actual use (e.g., by moving " "files), the attacker can exploit the race condition (CWE-362/CWE-367!)", "Set up the correct permissions (e.g., using setuid()) and " "try to open the file directly", "race", "avoid-race#atomic-filesystem", {}, "FF1030"), "chown": (normal, 5, "This accepts filename arguments; if an attacker " "can move those files, a race condition results. (CWE-362)", "Use fchown( ) instead", "race", "", {}, "FF1031"), "chgrp": (normal, 5, "This accepts filename arguments; if an attacker " "can move those files, a race condition results. (CWE-362)", "Use fchgrp( ) instead", "race", "", {}, "FF1032"), "chmod": (normal, 5, "This accepts filename arguments; if an attacker " "can move those files, a race condition results. (CWE-362)", "Use fchmod( ) instead", "race", "", {}, "FF1033"), "vfork": (normal, 2, "On some old systems, vfork() permits race conditions, and it's " "very difficult to use correctly (CWE-362)", "Use fork() instead", "race", "", {}, "FF1034"), "readlink": (normal, 5, "This accepts filename arguments; if an attacker " "can move those files or change the link content, " "a race condition results. " "Also, it does not terminate with ASCII NUL. (CWE-362, CWE-20)", # This is often just a bad idea, and it's hard to suggest a # simple alternative: "Reconsider approach", "race", "", {'input': 1}, "FF1035"), "tmpfile": (normal, 2, "Function tmpfile() has a security flaw on some systems (e.g., older System V systems) (CWE-377)", "", "tmpfile", "", {}, "FF1036"), "tmpnam|tempnam": (normal, 3, "Temporary file race condition (CWE-377)", "", "tmpfile", "avoid-race", {}, "FF1037"), # TODO: Detect GNOME approach to mktemp and ignore it. "mktemp": (normal, 4, "Temporary file race condition (CWE-377)", "", "tmpfile", "avoid-race", {}, "FF1038"), "mkstemp": (normal, 2, "Potential for temporary file vulnerability in some circumstances. Some older Unix-like systems create temp files with permission to write by all by default, so be sure to set the umask to override this. Also, some older Unix systems might fail to use O_EXCL when opening the file, so make sure that O_EXCL is used by the library (CWE-377)", "", "tmpfile", "avoid-race", {}, "FF1039"), "fopen|open": (normal, 2, "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)", "", "misc", "", {}, "FF1040"), "umask": (normal, 1, "Ensure that umask is given most restrictive possible setting (e.g., 066 or 077) (CWE-732)", "", "access", "", {}, "FF1041"), # Windows. TODO: Detect correct usage approaches and ignore it. "GetTempFileName": (normal, 3, "Temporary file race condition in certain cases " "(e.g., if run as SYSTEM in many versions of Windows) (CWE-377)", "", "tmpfile", "avoid-race", {}, "FF1042"), # TODO: Need to detect varying levels of danger. "execl|execlp|execle|execv|execvp|popen|WinExec|ShellExecute": (normal, 4, "This causes a new program to execute and is difficult to use safely (CWE-78)", "try using a library call that implements the same functionality " "if available", "shell", "", {}, "FF1043"), # TODO: Need to detect varying levels of danger. "system": (found_system, 4, "This causes a new program to execute and is difficult to use safely (CWE-78)", "try using a library call that implements the same functionality " "if available", "shell", "", {'extract_lookahead': 1}, "FF1044"), # TODO: Be more specific. The biggest problem involves "first" param NULL, # second param with embedded space. Windows. "CreateProcessAsUser|CreateProcessWithLogon": (normal, 3, "This causes a new process to execute and is difficult to use safely (CWE-78)", "Especially watch out for embedded spaces", "shell", "", {}, "FF1045"), # TODO: Be more specific. The biggest problem involves "first" param NULL, # second param with embedded space. Windows. "CreateProcess": (c_hit_if_null, 3, "This causes a new process to execute and is difficult to use safely (CWE-78)", "Specify the application path in the first argument, NOT as part of the second, " "or embedded spaces could allow an attacker to force a different program to run", "shell", "", {'check_for_null': 1}, "FF1046"), "atoi|atol|_wtoi|_wtoi64": (normal, 2, "Unless checked, the resulting number can exceed the expected range " "(CWE-190)", "If source untrusted, check both minimum and maximum, even if the" " input had no minus sign (large numbers can roll over into negative" " number; consider saving to an unsigned value if that is intended)", "integer", "dangers-c", {}, "FF1047"), # Random values. Don't trigger on "initstate", it's too common a term. "drand48|erand48|jrand48|lcong48|lrand48|mrand48|nrand48|random|seed48|setstate|srand|strfry|srandom|g_rand_boolean|g_rand_int|g_rand_int_range|g_rand_double|g_rand_double_range|g_random_boolean|g_random_int|g_random_int_range|g_random_double|g_random_double_range": (normal, 3, "This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327)", "Use a more secure technique for acquiring random values", "random", "", {}, "FF1048"), "crypt|crypt_r": (normal, 4, "The crypt functions use a poor one-way hashing algorithm; " "since they only accept passwords of 8 characters or fewer " "and only a two-byte salt, they are excessively vulnerable to " "dictionary attacks given today's faster computing equipment (CWE-327)", "Use a different algorithm, such as SHA-256, with a larger, " "non-repeating salt", "crypto", "", {}, "FF1049"), # OpenSSL EVP calls to use DES. "EVP_des_ecb|EVP_des_cbc|EVP_des_cfb|EVP_des_ofb|EVP_desx_cbc": (normal, 4, "DES only supports a 56-bit keysize, which is too small given today's computers (CWE-327)", "Use a different patent-free encryption algorithm with a larger keysize, " "such as 3DES or AES", "crypto", "", {}, "FF1050"), # Other OpenSSL EVP calls to use small keys. "EVP_rc4_40|EVP_rc2_40_cbc|EVP_rc2_64_cbc": (normal, 4, "These keysizes are too small given today's computers (CWE-327)", "Use a different patent-free encryption algorithm with a larger keysize, " "such as 3DES or AES", "crypto", "", {}, "FF1051"), "chroot": (normal, 3, "chroot can be very helpful, but is hard to use correctly (CWE-250, CWE-22)", "Make sure the program immediately chdir(\"/\"), closes file descriptors," " and drops root privileges, and that all necessary files" " (and no more!) are in the new root", "misc", "", {}, "FF1052"), "getenv|curl_getenv": (normal, 3, "Environment variables are untrustable input if they can be" " set by an attacker. They can have any content and" " length, and the same variable can be set more than once (CWE-807, CWE-20)", "Check environment variables carefully before using them", "buffer", "", {'input': 1}, "FF1053"), "g_get_home_dir": (normal, 3, "This function is synonymous with 'getenv(\"HOME\")';" "it returns untrustable input if the environment can be" "set by an attacker. It can have any content and length, " "and the same variable can be set more than once (CWE-807, CWE-20)", "Check environment variables carefully before using them", "buffer", "", {'input': 1}, "FF1054"), "g_get_tmp_dir": (normal, 3, "This function is synonymous with 'getenv(\"TMP\")';" "it returns untrustable input if the environment can be" "set by an attacker. It can have any content and length, " "and the same variable can be set more than once (CWE-807, CWE-20)", "Check environment variables carefully before using them", "buffer", "", {'input': 1}, "FF1055"), # These are Windows-unique: # TODO: Should have lower risk if the program checks return value. "RpcImpersonateClient|ImpersonateLoggedOnUser|CoImpersonateClient|" "ImpersonateNamedPipeClient|ImpersonateDdeClientWindow|ImpersonateSecurityContext|" "SetThreadToken": (normal, 4, "If this call fails, the program could fail to drop heightened privileges (CWE-250)", "Make sure the return value is checked, and do not continue if a failure is reported", "access", "", {}, "FF1056"), "InitializeCriticalSection": (normal, 3, "Exceptions can be thrown in low-memory situations", "Use InitializeCriticalSectionAndSpinCount instead", "misc", "", {}, "FF1057"), # We have *removed* the check for EnterCriticalSection. # The page from the "book Writing Secure Code" describes # EnterCriticalSection as something that will not throw errors on XP, # .NET Server, and later. Windows XP EOL in April 8, 2014, # .Net Server EOL 14 July 2015, so users of those systems will have # larger security issues anyway. # My thanks to rgetz for reporting this. For details, see: # https://github.com/david-a-wheeler/flawfinder/issues/19 # "EnterCriticalSection": # (normal, 3, "On some versions of Windows, exceptions can be thrown in low-memory situations", # "Use InitializeCriticalSectionAndSpinCount instead", # "misc", "", {}), "LoadLibrary": (normal, 3, "Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20)", "Use LoadLibraryEx with one of the search flags, or call SetSearchPathMode to use a safe search path, or pass a full path to the library", "misc", "", {'input': 1}, "FF1058"), "LoadLibraryEx": (load_library_ex, 3, "Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20)", "Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders", "misc", "", {'input': 1}, "FF1059"), "SetSecurityDescriptorDacl": (c_hit_if_null, 5, "Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), " "which would even forbid administrator access (CWE-732)", "", "misc", "", {'check_for_null': 3}, "FF1060"), "AddAccessAllowedAce": (normal, 3, "This doesn't set the inheritance bits in the access control entry (ACE) header (CWE-732)", "Make sure that you set inheritance by hand if you wish it to inherit", "misc", "", {}, "FF1061"), "getlogin": (normal, 4, "It's often easy to fool getlogin. Sometimes it does not work at all, because some program messed up the utmp file. Often, it gives only the first 8 characters of the login name. The user currently logged in on the controlling tty of our program need not be the user who started it. Avoid getlogin() for security-related purposes (CWE-807)", "Use getpwuid(geteuid()) and extract the desired information instead", "misc", "", {}, "FF1062"), "cuserid": (normal, 4, "Exactly what cuserid() does is poorly defined (e.g., some systems use the effective uid, like Linux, while others like System V use the real uid). Thus, you can't trust what it does. It's certainly not portable (The cuserid function was included in the 1988 version of POSIX, but removed from the 1990 version). Also, if passed a non-null parameter, there's a risk of a buffer overflow if the passed-in buffer is not at least L_cuserid characters long (CWE-120)", "Use getpwuid(geteuid()) and extract the desired information instead", "misc", "", {}, "FF1063"), "getpw": (normal, 4, "This function is dangerous; it may overflow the provided buffer. It extracts data from a 'protected' area, but most systems have many commands to let users modify the protected area, and it's not always clear what their limits are. Best to avoid using this function altogether (CWE-676, CWE-120)", "Use getpwuid() instead", "buffer", "", {}, "FF1064"), "getpass": (normal, 4, "This function is obsolete and not portable. It was in SUSv2 but removed by POSIX.2. What it does exactly varies considerably between systems, particularly in where its prompt is displayed and where it gets its data (e.g., /dev/tty, stdin, stderr, etc.). In addition, some implementations overflow buffers. (CWE-676, CWE-120, CWE-20)", "Make the specific calls to do exactly what you want. If you continue to use it, or write your own, be sure to zero the password as soon as possible to avoid leaving the cleartext password visible in the process' address space", "misc", "", {'input': 1}, "FF1065"), "gsignal|ssignal": (normal, 2, "These functions are considered obsolete on most systems, and very non-portable (Linux-based systems handle them radically different, basically if gsignal/ssignal were the same as raise/signal respectively, while System V considers them a separate set and obsolete) (CWE-676)", "Switch to raise/signal, or some other signalling approach", "obsolete", "", {}, "FF1066"), "memalign": (normal, 1, "On some systems (though not Linux-based systems) an attempt to free() results from memalign() may fail. This may, on a few systems, be exploitable. Also note that memalign() may not check that the boundary parameter is correct (CWE-676)", "Use posix_memalign instead (defined in POSIX's 1003.1d). Don't switch to valloc(); it is marked as obsolete in BSD 4.3, as legacy in SUSv2, and is no longer defined in SUSv3. In some cases, malloc()'s alignment may be sufficient", "free", "", {}, "FF1067"), "ulimit": (normal, 1, "This C routine is considered obsolete (as opposed to the shell command by the same name, which is NOT obsolete) (CWE-676)", "Use getrlimit(2), setrlimit(2), and sysconf(3) instead", "obsolete", "", {}, "FF1068"), "usleep": (normal, 1, "This C routine is considered obsolete (as opposed to the shell command by the same name). The interaction of this function with SIGALRM and other timer functions such as sleep(), alarm(), setitimer(), and nanosleep() is unspecified (CWE-676)", "Use nanosleep(2) or setitimer(2) instead", "obsolete", "", {}, "FF1069"), # Input functions, useful for -I "recv|recvfrom|recvmsg|fread|readv": (normal, 0, "Function accepts input from outside program (CWE-20)", "Make sure input data is filtered, especially if an attacker could manipulate it", "input", "", {'input': 1}, "FF1070"), # Unsafe STL functions that don't check the second iterator "equal|mismatch|is_permutation": (cpp_unsafe_stl, # Like strlen, this is mostly a risk to availability; at worst it # often causes a program crash. 1, "Function does not check the second iterator for over-read conditions (CWE-126)", "This function is often discouraged by most C++ coding standards in favor of its safer alternatives provided since C++14. Consider using a form of this function that checks the second iterator before potentially overflowing it", "buffer", "", {}, "FF1071"), # TODO: detect C++'s: cin >> charbuf, where charbuf is a char array; the problem # is that flawfinder doesn't have type information, and ">>" is safe with # many other types. # ("send" and friends aren't todo, because they send out.. not input.) # TODO: cwd("..") in user's space - TOCTOU vulnerability # TODO: There are many more rules to add, esp. for TOCTOU. } template_ruleset = { # This is a template for adding new entries (the key is impossible): "9": (normal, 2, "", "", "tmpfile", "", {}), } def find_column(text, position): "Find column number inside line." newline = text.rfind("\n", 0, position) if newline == -1: return position + 1 return position - newline def get_context(text, position): "Get surrounding text line starting from text[position]" linestart = text.rfind("\n", 0, position + 1) + 1 lineend = text.find("\n", position, len(text)) if lineend == -1: lineend = len(text) return text[linestart:lineend] def c_valid_match(text, position): # Determine if this is a valid match, or a false positive. # If false positive controls aren't on, always declare it's a match: i = position while i < len(text): c = text[i] if c == '(': return 1 elif c in string.whitespace: i += 1 else: if falsepositive: return 0 # No following "(", presume invalid. if c in "=+-": # This is very unlikely to be a function use. If c is '=', # the name is followed by an assignment or is-equal operation. # Since the names of library functions are really unlikely to be # followed by an assignment statement or 'is-equal' test, # while this IS common for variable names, let's declare it invalid. # It's possible that this is a variable function pointer, pointing # to the real library function, but that's really improbable. # If c is "+" or "-", we have a + or - operation. # In theory "-" could be used for a function pointer difference # computation, but this is extremely improbable. # More likely: this is a variable in a computation, so drop it. return 0 return 1 return 0 # Never found anything other than "(" and whitespace. def process_directive(): "Given a directive, process it." global ignoreline, num_ignored_hits # TODO: Currently this is just a stub routine that simply removes # hits from the current line, if any, and sets a flag if not. # Thus, any directive is considered the "ignore" directive. # Currently that's okay because we don't have any other directives yet. if never_ignore: return hitfound = 0 # Iterate backwards over hits, to be careful about the destructive iterator # Note: On Python 2 this is inefficient, because the "range" operator # creates a list. We used to use "xrange", but that doesn't exist # in Python3. So we use "range" which at least works everywhere. # If speed is vital on Python 2 we could replace this with xrange. for i in range(len(hitlist) - 1, -1, -1): if hitlist[i].filename == filename and hitlist[i].line == linenumber: del hitlist[i] # DESTROY - this is a DESTRUCTIVE iterator. hitfound = 1 # Don't break, because there may be more than one. num_ignored_hits += 1 if not hitfound: ignoreline = linenumber + 1 # Nothing found - ignore next line. # Characters that can be in a string. # 0x4, 4.4e4, etc. numberset = string.hexdigits + "_x.Ee" # Patterns for various circumstances: p_whitespace = re.compile(r'[ \t\v\f]+') p_include = re.compile(r'#\s*include\s+(<.*?>|".*?")') p_digits = re.compile(r'[0-9]') p_alphaunder = re.compile(r'[A-Za-z_]') # Alpha chars and underline. # A "word" in C. Note that "$" is permitted -- it's not permitted by the # C standard in identifiers, but gcc supports it as an extension. p_c_word = re.compile(r'[A-Za-z_][A-Za-z_0-9$]*') # We'll recognize ITS4 and RATS ignore directives, as well as our own, # for compatibility's sake: p_directive = re.compile(r'(?i)\s*(ITS4|Flawfinder|RATS):\s*([^\*]*)') max_lookahead = 500 # Lookahead limit for c_static_array. def process_c_file(f, patch_infos): global filename, linenumber, ignoreline, sumlines, num_links_skipped global sloc filename = f linenumber = 1 ignoreline = -1 cpplanguage = (f.endswith(".cpp") or f.endswith(".cxx") or f.endswith(".cc") or f.endswith(".hpp")) incomment = 0 instring = 0 linebegin = 1 codeinline = 0 # 1 when we see some code (so increment sloc at newline) if (patch_infos is not None) and (f not in 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), "
    ") else: print("Skipping unpatched file", f) sys.stdout.flush() return if f == "-": my_input = sys.stdin 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!") num_links_skipped += 1 return try: my_input = open(f, "r") except BaseException: print("Error: failed to open", h(f)) sys.exit(14) # Read ENTIRE file into memory. Use readlines() to convert \n if necessary. # This turns out to be very fast in Python, even on large files, and it # eliminates lots of range checking later, making the result faster. # We're examining source files, and today, it would be EXTREMELY bad practice # to create source files larger than main memory space. # Better to load it all in, and get the increased speed and reduced # development time that results. if not quiet: if output_format: print("Examining", h(f), "
    ") else: print("Examining", f) sys.stdout.flush() # Python3 is often configured to use only UTF-8, and presumes # that inputs cannot have encoding errors. # The real world isn't like that, so provide a prettier warning # in such cases - with some hints on how to solve it. try: text = "".join(my_input.readlines()) except UnicodeDecodeError as err: print('Error: encoding error in', h(f)) print(err) print() print('Python3 requires input character data to be perfectly encoded;') print('it also requires perfectly correct system encoding settings.') print('Unfortunately, your data and/or system settings are not.') print('Here are some options:') print('1. Run: PYTHONUTF8=0 python3 flawfinder') print(' if your system and and data are all properly set up for') print(' a non-UTF-8 encoding.') print('2. Run: PYTHONUTF8=0 LC_ALL=C.ISO-2022 python3 flawfinder') print(' if your data has a specific encoding such as ISO-2022') print(' (replace "ISO-2022" with the name of your encoding,') print(' and optionally replace "C" with your native language).') print('3. Run: PYTHONUTF8=0 LC_ALL=C.ISO-8859-1 python3 flawfinder') print(' if your data has an unknown or inconsistent encoding') print(' (ISO-8859-1 encoders normally allow anything).') print('4. Convert all your source code to the UTF-8 encoding.') print(' The system program "iconv" or Python program "cvt2utf" can') print(' do this (for cvt2utf, you can use "pip install cvt2utf").') print('5. Run: python2 flawfinder') print(' (That is, use Python 2 instead of Python 3).') print('Some of these options may not work depending on circumstance.') print('In the long term, we recommend using UTF-8 for source code.') print('For more information, see the documentation.') sys.exit(15) i = 0 while i < len(text): # This is a trivial tokenizer that just tries to find "words", which # match [A-Za-z_][A-Za-z0-9_]*. It skips comments & strings. # It also skips "#include <...>", which must be handled specially # because "<" and ">" aren't usually delimiters. # It doesn't bother to tokenize anything else, since it's not used. # The following is a state machine with 3 states: incomment, instring, # and "normal", and a separate state "linebegin" if at BOL. # Skip any whitespace m = p_whitespace.match(text, i) if m: i = m.end(0) if i >= len(text): c = "\n" # Last line with no newline, we're done else: c = text[i] if linebegin: # If at beginning of line, see if #include is there. linebegin = 0 if c == "#": codeinline = 1 # A directive, count as code. m = p_include.match(text, i) if m: # Found #include, skip it. Otherwise: #include i = m.end(0) continue if c == "\n": linenumber += 1 sumlines += 1 linebegin = 1 if codeinline: sloc += 1 codeinline = 0 i += 1 continue i += 1 # From here on, text[i] points to next character. if i < len(text): nextc = text[i] else: nextc = '' if incomment: if c == '*' and nextc == '/': i += 1 incomment = 0 elif instring: if c == '\\' and (nextc != "\n"): i += 1 elif c == '"' and instring == 1: instring = 0 elif c == "'" and instring == 2: instring = 0 else: if c == '/' and nextc == '*': m = p_directive.match(text, i + 1) # Is there a directive here? if m: process_directive() i += 1 incomment = 1 elif c == '/' and nextc == '/': # "//" comments - skip to EOL. m = p_directive.match(text, i + 1) # Is there a directive here? if m: process_directive() while i < len(text) and text[i] != "\n": i += 1 elif c == '"': instring = 1 codeinline = 1 elif c == "'": instring = 2 codeinline = 1 else: codeinline = 1 # It's not whitespace, comment, or string. m = p_c_word.match(text, i - 1) if m: # Do we have a word? startpos = i - 1 endpos = m.end(0) i = endpos word = text[startpos:endpos] # print "Word is:", text[startpos:endpos] if (word in c_ruleset) and c_valid_match(text, endpos): if ((patch_infos is None) or ((patch_infos is not None) and (linenumber in patch_infos[f]))): # FOUND A MATCH, setup & call hook. # print "HIT: #%s#\n" % word # Don't use the tuple assignment form, e.g., a,b=c,d # because Python (least 2.2.2) does that slower # (presumably because it creates & destroys temporary tuples) hit = Hit(c_ruleset[word]) hit.name = word hit.start = startpos hit.end = endpos hit.line = linenumber hit.column = find_column(text, startpos) hit.filename = filename hit.context_text = get_context(text, startpos) hit.parameters = extract_c_parameters(text, endpos) if hit.extract_lookahead: hit.lookahead = text[startpos: startpos + max_lookahead] hit.hook(hit) elif p_digits.match(c): while i < len(text): # Process a number. # C does not have digit separator if p_digits.match(text[i]) or (cpplanguage and text[i] == "'"): i += 1 else: break # else some other character, which we ignore. # End of loop through text. Wrap up. if codeinline: sloc += 1 if incomment: error("File ended while in comment.") if instring: error("File ended while in string.") def expand_ruleset(ruleset): # Rulesets can have compressed sets of rules # (multiple function names separated by "|". # Expand the given ruleset. # Note that this "for" loop modifies the ruleset while it's iterating, # so we *must* convert the keys into a list before iterating. for rule in list(ruleset.keys()): if "|" in rule: # We found a rule to expand. for newrule in rule.split("|"): if newrule in ruleset: print("Error: Rule %s, when expanded, overlaps %s" % ( rule, newrule)) sys.exit(15) ruleset[newrule] = ruleset[rule] del ruleset[rule] # To print out the set of keys in the expanded ruleset, run: # print `ruleset.keys()` def display_ruleset(ruleset): # First, sort the list by function name: sortedkeys = sorted(ruleset.keys()) # Now, print them out: for key in sortedkeys: print(key + "\t" + str( ruleset[key][1] ) + "\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)) if output_format: print("

    ") if list_rules: display_ruleset(c_ruleset) sys.exit(0) # Show the header, but only if it hasn't been shown yet. def display_header(): global displayed_header if csv_output: csv_writer.writerow([ 'File', 'Line', 'Column', 'DefaultLevel', 'Level', 'Category', 'Name', 'Warning', 'Suggestion', 'Note', 'CWEs', 'Context', 'Fingerprint', 'ToolVersion', 'RuleId', 'HelpUri' ]) return if sarif_output: return if not showheading: return if not displayed_header: if output_format: 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-2019 David A. Wheeler.') else: print("Flawfinder version %s, (C) 2001-2019 David A. Wheeler." % version) displayed_header = 1 c_extensions = { '.c': 1, '.h': 1, '.ec': 1, '.ecp': 1, # Informix embedded C. '.pgc': 1, # Postgres embedded C. '.C': 1, '.cpp': 1, '.CPP': 1, '.cxx': 1, '.cc': 1, # C++ '.CC': 1, '.c++': 1, # C++. '.pcc': 1, # Oracle C++ '.pc': 1, # Oracle SQL-embedded C '.sc': 1, # Oracle Pro*C pre-compiler '.hpp': 1, '.H': 1, # .h - usually C++. } def maybe_process_file(f, patch_infos): # process f, but only if (1) it's a directory (so we recurse), or # (2) it's source code in a language we can handle. # Currently, for files that means only C/C++, and we check if the filename # has a known C/C++ filename extension. If it doesn't, we ignore the file. # We accept symlinks only if allowlink is true. global num_links_skipped, num_dotdirs_skipped if os.path.isdir(f): if (not allowlink) and os.path.islink(f): if not quiet: print_warning("Skipping symbolic link directory " + h(f)) num_links_skipped += 1 return base_filename = os.path.basename(f) if (skipdotdir and len(base_filename) > 1 and (base_filename[0] == ".")): if not quiet: print_warning("Skipping directory with initial dot " + h(f)) num_dotdirs_skipped += 1 return for dir_entry in os.listdir(f): maybe_process_file(os.path.join(f, dir_entry), patch_infos) # Now we will FIRST check if the file appears to be a C/C++ file, and # THEN check if it's a regular file or symlink. This is more complicated, # but I do it this way so that there won't be a lot of pointless # warnings about skipping files we wouldn't have used anyway. dotposition = f.rfind(".") if dotposition > 1: extension = f[dotposition:] if extension in c_extensions: # Its name appears to be a C/C++ source code file. if (not allowlink) and os.path.islink(f): if not quiet: print_warning("Skipping symbolic link file " + h(f)) num_links_skipped += 1 elif not os.path.isfile(f): # Skip anything not a normal file. This is so that # device files, etc. won't cause trouble. if not quiet: print_warning("Skipping non-regular file " + h(f)) else: # We want to know the difference only with files found in the # patch. if ((patch_infos is None) or (patch_infos is not None and (f in patch_infos))): process_c_file(f, patch_infos) def process_file_args(files, patch_infos): # Process the list of "files", some of which may be directories, # which were given on the command line. # This is handled differently than anything not found on the command line # (i.e. through recursing into a directory) because flawfinder # ALWAYS processes normal files given on the command line. # This is done to give users control over what's processed; # if a user really, really wants to analyze a file, name it! # If user wants to process "this directory and down", just say ".". # We handle symlinks specially, handle normal files and directories, # and skip the rest to prevent security problems. "-" is stdin. global num_links_skipped for f in files: if (not allowlink) and os.path.islink(f): if not quiet: print_warning("Skipping symbolic link " + h(f)) num_links_skipped += 1 elif os.path.isfile(f) or f == "-": # If on the command line, FORCE processing of it. # Currently, we only process C/C++. # check if we only want to review a patch if ((patch_infos is not None and f in patch_infos) or (patch_infos is None)): process_c_file(f, patch_infos) elif os.path.isdir(f): # At one time flawfinder used os.path.walk, but that Python # built-in doesn't give us enough control over symbolic links. # So, we'll walk the filesystem hierarchy ourselves: maybe_process_file(f, patch_infos) elif not os.path.exists(f): if not quiet: # Help humans avoid a long mysterious debugging session. # Sometimes people copy/paste from HTML that has a leading # en dash (\u2013 aka 0xE2 0x80 0x93) or # em dash (\u2014 aka 0xE2 0x80 0x94) instead of the # correct dash marker (in an attempt to make things "pretty"). # These symbols *look* like the regular dash # option marker, but they are not the same characters. # If there's no such file, give a special warning, # because otherwise this can be extremely # difficult for humans to notice. We'll do the check in # this odd way so it works on both Python 2 and Python 3. # (Python 3 wants \u...). # Note that we *only* make this report if the file doesn't # exist - if someone asks to process a file with this crazy # name, and it exists, we'll process it without complaint. if (h(f).startswith("\xe2\x80\x93") or h(f).startswith("\xe2\x80\x94") or h(f).startswith(u"\u2013") or h(f).startswith(u"\u2014")): print_warning( "Skipping non-existent filename starting with em dash or en dash " + h(f)) else: print_warning("Skipping non-existent file " + h(f)) else: if not quiet: print_warning("Skipping non-regular file " + h(f)) def usage(): print(""" flawfinder [--help | -h] [--version] [--listrules] [--allowlink] [--followdotdir] [--nolink] [--patch filename | -P filename] [--inputs | -I] [--minlevel X | -m X] [--falsepositive | -F] [--neverignore | -n] [--context | -c] [--columns | -C] [--dataonly | -D] [--html | -H] [--immediate | -i] [--singleline | -S] [--omittime] [--quiet | -Q] [--loadhitlist F] [--savehitlist F] [--diffhitlist F] [--] [source code file or source root directory]+ The options cover various aspects of flawfinder as follows. Documentation: --help | -h Show this usage help. --version Show version number. --listrules List the rules in the ruleset (rule database). Selecting Input Data: --allowlink Allow symbolic links. --followdotdir Follow directories whose names begin with ".". Normally they are ignored. --nolink Skip symbolic links (ignored). --patch F | -P F Display information related to the patch F (patch must be already applied). Selecting Hits to Display: --inputs | -I Show only functions that obtain data from outside the program; this also sets minlevel to 0. -m X | --minlevel=X Set minimum risk level to X for inclusion in hitlist. This can be from 0 (``no risk'') to 5 (``maximum risk''); the default is 1. --falsepositive | -F Do not include hits that are likely to be false positives. Currently, this means that function names are ignored if they're not followed by "(", and that declarations of char- acter arrays aren't noted. Thus, if you have use a vari- able named "access" everywhere, this will eliminate refer- ences to this ordinary variable. This isn't the default, because this also increases the likelihood of missing important hits; in particular, function names in #define clauses and calls through function pointers will be missed. --neverignore | -n Never ignore security issues, even if they have an ``ignore'' directive in a comment. --regex PATTERN | -e PATTERN Only report hits that match the regular expression PATTERN. Selecting Output Format: --columns | -C Show the column number (as well as the file name and line number) of each hit; this is shown after the line number by adding a colon and the column number in the line (the first character in a line is column number 1). --context | -c Show context (the line having the "hit"/potential flaw) --dataonly | -D Don't display the headers and footers of the analysis; use this along with --quiet to get just the results. --html | -H Display as HTML output. --immediate | -i Immediately display hits (don't just wait until the end). --sarif Generate output in SARIF format. --singleline | -S Single-line output. --omittime Omit time to run. --quiet | -Q Don't display status information (i.e., which files are being examined) while the analysis is going on. --error-level=LEVEL Return a nonzero (false) error code if there is at least one hit of LEVEL or higher. If a diffhitlist is provided, hits noted in it are ignored. This option can be useful within a continuous integration script, especially if you mark known-okay lines as "flawfinder: ignore". Usually you want level to be fairly high, such as 4 or 5. By default, flawfinder returns 0 (true) on a successful run. Hitlist Management: --savehitlist=F Save all hits (the "hitlist") to F. --loadhitlist=F Load hits from F instead of analyzing source programs. --diffhitlist=F Show only hits (loaded or analyzed) not in F. For more information, please consult the manpage or available documentation. """) def process_options(): global show_context, show_inputs, allowlink, skipdotdir, omit_time global output_format, minimum_level, show_immediately, single_line global csv_output, csv_writer, sarif_output global error_level global required_regex, required_regex_compiled global falsepositive global show_columns, never_ignore, quiet, showheading, list_rules global loadhitlist, savehitlist, diffhitlist_filename global patch_file try: # Note - as a side-effect, this sets sys.argv[]. optlist, args = getopt.getopt(sys.argv[1:], "ce:m:nih?CSDQHIFP:", [ "context", "minlevel=", "immediate", "inputs", "input", "nolink", "falsepositive", "falsepositives", "columns", "listrules", "omittime", "allowlink", "patch=", "followdotdir", "neverignore", "regex=", "quiet", "dataonly", "html", "singleline", "csv", "error-level=", "sarif", "loadhitlist=", "savehitlist=", "diffhitlist=", "version", "help" ]) for (opt, value) in optlist: if opt in ("--context", "-c"): show_context = 1 elif opt in ("--columns", "-C"): show_columns = 1 elif opt in ("--quiet", "-Q"): quiet = 1 elif opt in ("--dataonly", "-D"): showheading = 0 elif opt in ("--inputs", "--input", "-I"): show_inputs = 1 minimum_level = 0 elif opt in ("--falsepositive", "falsepositives", "-F"): falsepositive = 1 elif opt == "--nolink": allowlink = 0 elif opt == "--omittime": omit_time = 1 elif opt == "--allowlink": allowlink = 1 elif opt == "--followdotdir": skipdotdir = 0 elif opt == "--listrules": list_rules = 1 elif opt in ("--html", "-H"): output_format = 1 single_line = 0 elif opt in ("--minlevel", "-m"): minimum_level = int(value) elif opt in ("--singleline", "-S"): single_line = 1 elif opt == "--csv": csv_output = 1 quiet = 1 showheading = 0 csv_writer = csv.writer(sys.stdout) elif opt == "--sarif": sarif_output = 1 quiet = 1 showheading = 0 elif opt == "--error-level": error_level = int(value) elif opt in ("--immediate", "-i"): show_immediately = 1 elif opt in ("-n", "--neverignore"): never_ignore = 1 elif opt in ("-e", "--regex"): required_regex = value # This will raise an exception if it can't be compiled as a # regex: required_regex_compiled = re.compile(required_regex) elif opt in ("-P", "--patch"): # Note: This is -P, so that a future -p1 option can strip away # pathname prefixes (with the same option name as "patch"). patch_file = value # If we consider ignore comments we may change a line which was # previously ignored but which will raise now a valid warning # without noticing it now. So, set never_ignore. never_ignore = 1 elif opt == "--loadhitlist": loadhitlist = value display_header() if showheading: print("Loading hits from", value) elif opt == "--savehitlist": savehitlist = value display_header() if showheading: print("Saving hitlist to", value) elif opt == "--diffhitlist": diffhitlist_filename = value display_header() if showheading: print("Showing hits not in", value) elif opt == "--version": print(version) sys.exit(0) elif opt in ('-h', '-?', '--help'): # We accept "-?" but do not document it because we don't # want to encourage its use. # Unix-like systems with typical shells expand glob # patterns, so the question mark in "-?" should be escaped, # and many forget that. usage() sys.exit(0) # For DOS/Windows, expand filenames; for Unix, DON'T expand them # (the shell will expand them for us). Some sloppy Python programs # always call "glob", but that's WRONG -- on Unix-like systems that # will expand twice. Python doesn't have a clean way to detect # "has globbing occurred", so this is the best I've found: if os.name in ("windows", "nt", "dos"): sys.argv[1:] = functools.reduce(operator.add, list(map(glob.glob, args))) else: sys.argv[1:] = args # In Python 2 the convention is "getopt.GetoptError", but we # 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) usage() sys.exit(16) if output_format == 1 and list_rules == 1: print('You cannot list rules in HTML format') sys.exit(20) def process_files(): """Process input (files or hitlist); return True if okay.""" global hitlist if loadhitlist: f = open(loadhitlist, "rb") hitlist = pickle.load(f) return True else: patch_infos = None if patch_file != "": patch_infos = load_patch_info(patch_file) files = sys.argv[1:] if not files: print("*** No input files") return None process_file_args(files, patch_infos) return True def hitlist_sort_key(hit): """Sort key for hitlist.""" return (-hit.level, hit.filename, hit.line, hit.column, hit.name) def show_final_results(): global hitlist global error_level_exceeded count = 0 count_per_level = {} count_per_level_and_up = {} # Name levels directly, to avoid Python "range" (a Python 2/3 difference) possible_levels = (0, 1, 2, 3, 4, 5) for i in possible_levels: # Initialize count_per_level count_per_level[i] = 0 for i in possible_levels: # Initialize count_per_level_and_up count_per_level_and_up[i] = 0 if show_immediately or not quiet: # Separate the final results. print() if showheading: if output_format: print("

    Final Results

    ") else: print("FINAL RESULTS:") print() hitlist.sort(key=hitlist_sort_key) # Display results. The HTML format now uses #
      so that the format differentiates each entry. # I'm not using
        , because its numbers might be confused with # the risk levels or line numbers. if diffhitlist_filename: diff_file = open(diffhitlist_filename, 'rb') diff_hitlist = pickle.load(diff_file) if output_format: print("
          ") for hit in hitlist: if not diffhitlist_filename or hit not in diff_hitlist: count_per_level[hit.level] = count_per_level[hit.level] + 1 if hit.level >= minimum_level: hit.show() count += 1 if hit.level >= error_level: error_level_exceeded = True if output_format: print("
        ") if diffhitlist_filename: diff_file.close() # Done with list, show the post-hitlist summary. if showheading: if output_format: print("

        Analysis Summary

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

        ") else: print() if count > 0: print("Hits =", count) else: print("No hits found.") if output_format: 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, 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))) else: print() if output_format: print("
        ") print("Physical Source Lines of Code (SLOC) = %d" % sloc) if output_format: print("
        ") # Output hits@each level. print("Hits@level =", end='') for i in possible_levels: print(" [%d] %3d" % (i, count_per_level[i]), end='') if output_format: print("
        ") else: print() # Compute hits at "level x or higher" print("Hits@level+ =", end='') for i in possible_levels: for j in possible_levels: if j >= i: 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 possible_levels: print(" [%d+] %3d" % (i, count_per_level_and_up[i]), end='') if output_format: print("
        ") else: print() if sloc > 0: print("Hits/KSLOC@level+ =", end='') for i in possible_levels: print(" [%d+] %3g" % ( i, count_per_level_and_up[i] * 1000.0 / sloc), end='') if output_format: print("
        ") else: print() # if num_links_skipped: print("Symlinks skipped =", num_links_skipped, "(--allowlink overrides but see doc for security issue)") if output_format: print("
        ") if num_dotdirs_skipped: print("Dot directories skipped =", num_dotdirs_skipped, "(--followdotdir overrides)") if output_format: print("
        ") if num_ignored_hits > 0: print("Suppressed hits =", num_ignored_hits, "(use --neverignore to show them)") if output_format: print("
        ") print("Minimum risk level = %d" % minimum_level) if output_format: print("
        ") else: print() if count > 0: print("Not every hit is necessarily a security vulnerability.") print("You can inhibit a report by adding a comment in this form:") print("// flawfinder: ignore") print("Make *sure* it's a false positive!") print("You can use the option --neverignore to show these.") if output_format: print("
        ") else: print() print("There may be other security vulnerabilities; review your code!") if output_format: print("
        ") print("See 'Secure Programming HOWTO'") print("(https://dwheeler.com/secure-programs) for more information.") else: print("See 'Secure Programming HOWTO'") print("(https://dwheeler.com/secure-programs) for more information.") if output_format: print("") print("") def save_if_desired(): # We'll save entire hitlist, even if only differences displayed. if savehitlist: if not quiet: print("Saving hitlist to", savehitlist) f = open(savehitlist, "wb") pickle.dump(hitlist, f) f.close() def flawfind(): process_options() display_header() initialize_ruleset() if process_files(): if sarif_output: print(SarifLogger(hitlist).output_sarif()) else: show_final_results() save_if_desired() return 1 if error_level_exceeded else 0 def main(): try: sys.exit(flawfind()) except KeyboardInterrupt: print("*** Flawfinder interrupted") if __name__ == '__main__': main() flawfinder-2.0.19/test/000755 000765 000024 00000000000 14056167132 015652 5ustar00dwheelerstaff000000 000000 flawfinder-2.0.19/ChangeLog000644 000765 000024 00000106162 14112766602 016453 0ustar00dwheelerstaff000000 000000 2021-08-29 David A. Wheeler * Version 2.0.19 * Fix so we send error messages to stderr instead of stdout. Originally we sent some to stdout by mistake, which could mess up results since the error messages would be mixed up with the results. 2021-06-24 David A. Wheeler * Version 2.0.18 * Fix SARIF output. SARIF output is new to flawfinder, and there was a subtle error in its generation that causes GitHub to reject the SARIF file. 2021-06-02 David A. Wheeler * Version 2.0.17 * Fix the distributed tarball, which didn't include the key source file due to the earlier file restructure. * Minor code style fix, which simplifies the code slightly. * Update date in manual page to 2021. That's important because the documentation now includes information on `--sarif`. 2021-05-31 David A. Wheeler * Version 2.0.16 * The distributed source file is now flawfinder.py, not flawfinder. This is part of a change that improves improve cross-platform ease-of-use by using entry_points. That said, "make install" will still install it as "flawfinder" (so those who install it via "make install" will see no change). Many thanks to Ben Spoor! * Added support for generating SARIF output, use --sarif. A big thanks to Yong Yan for this work! * Track curly brace level to reduce some problems, my thanks to Greg Myers for the work! * Improved handling of Git patch format, thanks to Robin Geffroy. 2021-01-11 David A. Wheeler * Version 2.0.15 * Fixed some release problems in 2.0.14. * Improved handling of LoadLibraryEx; flawfinderr no longer complains about certain constructs that are known to be safe (eliminating some false positives). 2021-01-09 David A. Wheeler * Version 2.0.14 * If there are >0 hits, tell users how to ignore them as part of the tool output. * Various Windows improvments. Ignore LoadLibraryEx if its third parameter is LOAD_LIBRARY_SEARCH_SYSTEM32, as this is safe, and remove the rule for InitialCriticalSection (this is no longer a vulnerability on current widely-used versions of Windows) * Various C++ improvements. Add .hpp support for C++, ignore "system::" to reduce false positives, treat ' as digit separator when file extension is a C++ file (for C++14). * I had some release problems; this is identified as 2.0.14 (skipping a few minor numbers) to ensure that the version number uniquely identifies a specific release. 2020-02-17 David A. Wheeler * Version 2.0.11 * Provide a much more detailed error report, including recommended solutions, when character encoding problems hit. As Python3 has slowly gained in popularity, its failure to provide useful built-ins to handle real-world character encoding problems hurts more people. (E.g., many files don't comply with *any* character set encoding standard, and Python3 can't read them without enabling options that are wrong for others.) We can at least provide much more detailed feedback to help explain the various options available. 2019-06-22 David A. Wheeler * Version 2.0.10 * Use binary mode when reading a diffhitlist. My thanks to Michał Górny, who both reported the problem and provided the patch! 2019-05-19 David A. Wheeler * Version 2.0.9 * Fixes a serious defect in --diffhitlist 2019-05-17 Labidurie Jerome * Fixed a serious defect in --diffhitlist option and added a unit test 2019-01-21 David A. Wheeler * Version 2.0.8 * Don't warn if memcpy call includes sizeof(first arg). Thanks to Michael Clark for this improvement! * Bugfix (banned function _ftcsat should be _ftcscat). Thanks to Lucas Ramage for reporting this! * Documentation tweaks. Make it clear that GitHub issues and pull requests are supported, and use ~~~~ in markdown to ease copy-and-paste from documentation. 2018-09-30 David A. Wheeler * Incorporate many small improvements from nickthetait * Fix a number of bugs reported by philipp * Update URLs for www.dwheeler.com -> dwheeler.com 2018-04-04 David A. Wheeler * Version 2.0.6 2018-01-26 David A. Wheeler * Small fixes * Update cwe.mitre.org URLs to use https 2017-11-16 David A. Wheeler * add detection of crypt_r function * add detection of errant equal, mismatch, and is_permutation * update CWE, risk, and discussion for C++14 STL functions * Always report hit counts correctly, even if ignored using -m * Update www.dwheeler.com URLs to use https 2017-09-02 David A. Wheeler * Version 2.0.4 * Switch from distutils to setuptools * Directly support "pip" installs 2017-08-26 David A. Wheeler * Version 2.0.2 * Flawfinder can now run on either Python 2.7 or 3 * Added more tests * Implemented additional code cleanups recommended by Pylint * Modified documentation in various ways to clarify things 2017-08-13 David A. Wheeler * Version 2.0.1 * Tranform many internal constructs to work on Python 2 or 3, with the eventual goal of making it run on either. 2017-07-29 David A. Wheeler * Version 2.0.0 * Change version numbers to use Semantic Versioning (x.y.z) * Add support for generating CSV (comma-separated value) format, to make this tool easier to integrate into larger toolsuites. * Fixed a number of issues - and even a few bugs - found by the Python static analysis tool pylint. * Document in CONTRIBUTING.md how to contribute to the project. * Change version number to 2.0.0, because we have a subtle interface change that won't affect most people but it *may* affect those who use postprocess flawfinder data on CWEs. The fundamental issue is that in some cases a hit corresponds to multiple CWEs. As a result, in some cases flawfinder will list a sequence of CWEs in the format "more-general/more-specific", where the CWE actually being mapped is followed by a "!". This is always done whenever a flaw is not mapped directly to a top 25 CWE, but the mapping is related to such a CWE. So "CWE-119!/CWE-120" means that the vulnerability is mapped to CWE-119 and that CWE-120 is a subset of CWE-119. In contrast, "CWE-362/CWE-367!" means that the hit is mapped to CWE-367, a subset of CWE-362. Note that this is a subtle syntax change from flawfinder version 1.31; in flawfinder version 1.31, the form "more-general:more-specific" meant what is now listed as "more-general!/more-specific", while "more-general/more-specific" meant "more-general/more-specific!". Tools can handle both the version 1.31 and the current format, if they wish, by noting that the older format did not use "!" at all. These mapping mechanisms simplify searching for certain CWEs. 2014-08-03 David A. Wheeler * Release version 1.31, a set of small improvements mostly CWE-related. * Note that flawfinder is officially CWE-compatible. * Support GNU make install conventions (prefix, bindir, DESTDIR, etc.). The older program-specific conventions are still supported, but the documentation emphasizes using the standard conventions instead. * Simplified installation text. * Added more wide character function rules. * Add reference to info at "http://www.dwheeler.com/secure-programs". * Document that hitlists should be trusted to be loaded or diffed. These are implented using Python's pickle module, and that module presumes the data is from a trustworthy source. In the expected use case this is fine... but it needed to be documented. * Tweak/improve mappings to CWE. E.G., strlen() better maps to CWE-126 (buffer over-read). In a few cases the CWE mappings weren't reported as such; that is now fixed. CWEs are actually a hierarchy; expose a little of this so people can more easily search on them. * Improved error detection and reporting. In particular, error messages are sent to standard errors, filenames listed but non-existent trigger a separate warning, and there's a warning about non-existent filenames listed on the command line that begin with the UTF-8 long dash sequence (users might not notice the difference between long dash and dash, and this can happen in some cases when copying and pasting). * Add "-H" option as synonym for "--html". 2014-07-19 David A. Wheeler * Release 1.29, primarily for CWE improvements. * Multi-line formatting is faster and formats better. * Documentation about CWEs has been improved. * HTML format includes links from CWE identifiers to their definitions. * Tweak CWE mappings, e.g., strlen maps to CWE-126 (buffer over-read). * Option "--listrules" now gives default warning and is tab-delimited. * Regression test suite now also tests the generated HTML. 2014-07-13 David A. Wheeler * Release 1.28 * Common Weakness Enumeration (CWE) references are now included in most hits * Handle files not ending in newline (thanks to Alexis Wilke) * Documentation clarifications * Added support for "git diff" in patchfile processing * Handles unbalanced double-quotes in sprintf * Fix incorrect time executed report * Fix bug to allow "flawfinder ." (fix bug#3) * Fix ignore directive when filenames differ (fix bug#6) 2007-01-16 David A. Wheeler * Release version 1.27 2007-01-16 Sebastien Tandel * Fix Debian bug #268236. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=268236 This complains that flawfinder crashes when presented with a file it cannot read. The patch obviously can't prevent the problem, since the tool can't review what it can't read, but at least it halts with a cleaner error message. 2007-01-15 cmorgan * Fixed Debian bug #271287 (flawfinder). See: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=271287 Fixed skipping newlines when line ended with \, which caused incorrect line number reporting. Skip multiple whitespace at one time. 2007-01-15 David A. Wheeler * Modified Sebastien Tandel's code so that it also supports GNU diff (his code worked only for svn diff) * When using a patchfile, skip analysis of any file not listed in the patchfile. 2007-01-15 Sebastien Tandel * By default, now skips directories beginning with "." (this makes it work nicely with many SCM systems). Added "--followdotdir" option if you WANT it to enter such directories. * Fixed divide-by-zero when no code found (not exactly common in normal use, but anyway!) 2004-06-15 David A. Wheeler * Released version 1.26. * NOTE: Due to an error on my part, the tar file for version 1.25 was for a short period (after 2004-06-05) actually version 1.26, incorrectly labelled as 1.25. My sincere apologies!! Please upgrade to 1.26, since that way you'll be SURE to get the right version. 2004-06-04 David A. Wheeler * Reviewed and modified Jared's code somewhat, and added support for _TEXT() as well as _T(). See http://www.rpi.edu/~pudeyo/articles/unicode.html for more info on Microsoft's approach to internationalization involving TCHAR. * Wrote ChangeLog entries for Jared's code. 2004-06-04 Jared Robinson (jarrob, at, symantec.com) * Added more support for Microsoft's approach to internationalization. Thus, it accepts _T() just like gettext(), and adds many more functions: _getts(), vswprintf(), _stprintf(), _vstprintf(), vwprintf(), vfwprintf(), _vtprintf(), _ftprintf(), _vftprintf(), _sntprintf(), _vsntprintf(), _ftscanf(), _gettc(). In this approach, TCHAR and various macros are typically used. In particular, _T() of tchar.h converts character strings to long character strings, if _UNICODE is defined (this makes TCHAR a long 16-bit character). Thus, T() is: #ifdef _UNICODE #define _T(x) L ## x #else #define _T(x) x #endif 2004-06-02 David A. Wheeler * Added two new rules for GLib functions, "g_get_home_dir" and "g_get_tmp_dir", per a suggestion by Steve Kemp, lead of the Debian Security Auditing Project. This closes the wishlist item in Debian bug report #250432 (see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=250432). Contributors - please email wishlist items to me; I can't monitor every distribution's local bug tracking system. PLEASE tell upstream developers when there's a bug/wishlist item, we can't fix it if we don't know. * Added curl_getenv(). Kemp's suggestion reminded me to search for other getenv()-like functions, and that one popped up. * Added several rules for input functions (for -I) - recv, recvfrom, recvmsg, fread, and readv. * Tightened the false positive test slightly; if a name is followed by = or - or + it's unlikely to be a function call, so it'll be quietly discarded. * Modified the summary report format slightly. * Modified the getpass text to remove an extraneous character, thanks to a bug report from Joerg Beyer (job, at, webde-ag.de) * Modified installation instructions to clarify how to set INSTALL_DIR at run-time so it installs elsewhere. It uses the standard GNU conventions, but not everyone knows about them. By default, it installs in /usr/local. Just use normal make overrides to change that, e.g., make INSTALL_DIR=/usr INSTALL_DIR_MAN=/usr/share/man install I do NOT use the ?= macro-setting commands in the makefile, because that's not standard (e.g., it's not in SUSv3), so while that would work in GNU make, it wouldn't work in others. 2004-05-31 David A. Wheeler * Released version 1.25. 2004-05-30 David A. Wheeler * Added more rules for finding problems by examining the Red Hat Linux 9 documentation (the man3 man pages), looking for phrases like "do not use", "security", and "obsolete". Thus, added rules for cuserid, getlogin, getpass, mkstemp, getpw, memalign, as well as the obsolete functions gsignal, ssignal, ulimit, usleep. * Modified text for strncat to clarify it. My thanks to Christian Biere, christianbiere, at, gmx.de, for reporting the problem. * Added lengthy text to the manual to explain exactly how to use flawfinder with vim and emacs. This should also help integrate flawfinder into other text editors/IDEs. * Fixed error in --columns format, so that the output is simply "filename:linenumber:columnnumber" when --columns (-C) is used. * Eliminated "Number of" phrase in the footer report (it was redundant anyway) * Added more statistical information to the footer report. * Changed makefile to simplify running tests. * Tests now autogenerate html and txt versions. * Added shortcut single-letter commands (-D for --dataonly, -Q for --quiet, -C for --columns), so that invoking from editors is easier. * Tries to autoremove some false positives. In particular, a function name followed immediately by "=" (ignoring whitespace) is automatically considered to be a variable and NOT a function, and thus doesn't register as a hit. There are exotic cases where this won't be correct, but they're pretty unlikely in real code. * Added a "--falsepositive" (-F) option, which tries to remove many more likely false positives. The current heuristic is: if -F is enabled, any function name must be followed by "(" (ignoring whitespace) to be considered a possible hit; otherwise, it's thrown away. Thus, if you often use variable names that are also the names of risky functions, like "access", you might consider using this option. Note that flawfinder uses simple lexical analysis; eliminating many more false positives would require deeper code analysis (to examine type information, buffer size declarations, etc.). This option also disables reporting of static character buffer arrays. This -F option and the autoremoving of false positives above is in response to a problem report from Mike Ruscher (Mike.Ruscher, at, cse-cst.gc.ca), though the approach and code is my own. This may not completely solve Mr. Ruscher's problem, but it's a start. * Documented that flawfinder output can be misunderstood if there are source filenames whose names contain newline, linefeed, or colon. Source filenames shouldn't have such characters anyway; while flawfinder can handle them, many other tools can't. * Modified the documentation to make it clear in the synopsis which one-letter flags are short for which long names. * Modified "make install" script slightly so that it creates directories that don't yet exist when installing. My thanks to Joerg Beyer (job, at webde-ag.de) for reporting the problem and suggesting a solution. This solution requires that "mkdir" support the "-p" option, which shouldn't be a problem for nearly all users. 2003-10-29 David A. Wheeler * Released version 1.24. * Fixed an incredibly obscure parsing error that caused some false positives. If a constant C string, after the closing double-quote, is followed by a \ and newline (instead of a comma), the string might not be recognized as a constant string (thus triggering warnings about non-constant values in some cases). This kind of formatting is quite ugly and rare. My thanks to Sascha Nitsch (sascha, at spsn.ath.cx) for pointing this bug out and giving me a test case to work with. * Added a warning for readlink. The implementation and warning are mine, but the idea of warning about readlink came from Stefan Kost (kost, at imn.htwk-leipzig.de). Thanks!! 2003-09-27 David A. Wheeler * Released version 1.23. Minor bugfixes. 2003-09-27 David A. Wheeler * Fixed subtle bug - in some circumstances single character constants wouldn't be parsed correctly. My thanks to Scott Renfro (scottdonotspam, at, renfro.org) for notifying me about this bug. Scott Renfro also sent me a patch; I didn't use it (the patch didn't handle other cases), but I'm grateful since it illustrated the problem. * Fixed documentation bug in man page. The option "--minlevel=X" must be preceded by two dashes, as are all GNU-style long options. The man page accidentally only had one dash in the summary (it was correct elsewhere); it now correctly shows both dashes. * Modified man page to list filename extensions that are interpreted as C/C++. * Removed index.html from distribution - it's really only for the website. 2003-03-08 David A. Wheeler * Released version 1.22. Output format slightly changed (colon added), so that it's compatible with tools that expect compiler warnings in the typical format "filename:line-number: warning". To get the fully expected format (all in one line), use "-S". Also, improved RPM packaging. 2003-03-08 David A. Wheeler * Changed makefile to be consistent with new RPM packaging approach. * Changed makefile: now for testing, will automatically uninstall old sloccount when creating rpm. Also (for me), make my_install works (well, it helps me anyway). 2003-02-01 Jose Pedro Oliveira * Improved RPM packaging. 2003-09-22 Jukka A. Ukkonen * Recommended an extra colon in the output format, so that the output format would like like typical compiler output (and thus more compatible with existing tools that report warnings). 2002-09-07 David A. Wheeler * Released version 1.21, with the following changes: * Improved the default output so it creates multiple formatted lines instead of single very long lines for each hit. Use the new "--singleline" (-S) option to get the original "long line" format. * Removed duplicate "getpass" entry in the ruleset; this didn't hurt anything, but was unnecessary. Thanks to the user who gave me that feedback, wish I'd kept your email address so I could credit you properly :-). * Added a short tutorial to man page. * Fixed initial upper/lower case on many entries in the ruleset. * Allow "--input" as a synonym for "--inputs". 2002-07-07 David A. Wheeler * Released version 1.20, with many more changes: * Entries have been added to the database to detect file openings and static character array definitions. * The HTML format has been significantly improved. * Joerg Beyer provided several nice improvements to flawfinder, including a timing report. * Now Flawfinder by default skips symbolic links, and always skips special files, to counter attackers who insert malicious files in their source code directories. * The documentation has been improved in various ways. 2002-07-05 David A. Wheeler * Completely rewrote the functions handling opening the files/directories named on the command line and when walking down the directory tree. This was in part to handle a new security requirement for source code web hosting services, which may analyze code written by someone else AND then send reports to someone else who doesn't have the same rights to view files as the analysis program. It's the last part that's different - the attacker may control the code being analyzed and insert non-regular files or symbolic links to "bad" files like /etc/passwd (to expose its contents) or /dev/zero (to stall analysis). These are annoying but not really a problem when the analyst is running on his OWN machine. To deal with this, now flawfinder NEVER opens a file type that isn't a file or directory, and it skips symbolic links by default (though this can be changed), no matter if they're listed at the top or inside a directory descendent. This is actually reasonable behavior for everyone, since others may be analyzing programs that they don't trust either. * Added open() and fopen() as entries, now it has 127 entries in the database. Modified test code to test it. * Warning messages about skipping symlinks and files that aren't regular files are now controlled by --quiet instead of --dataonly; since --quiet controls printing status messages this seems more reasonable. * Changed the format of the HTML output - now it creates a list. The ending is now in regular type, instead of

        ...
        . This seemed too look nicer. * Reworked Beyer's patch that prints speed somewhat, e.g., to print floating point time (on small programs or fast machines the time would be reported as "0") and to avoid divide-by-zero on systems where time really is reported as zero. * Added "--omittime", so that the regression test results won't vary depending on the time the analysis takes. * Fixed minor bug: now the filename "-" works to mean standard input. This is rarely used, since usually files are analyzed instead. * Modified documentation to make clear that in many circumstances you need to copy the source code to a separate area. I removed the reference to "--nolink", since this is now the default. * Modified makefile to generate correct-results.html and correct-results.txt, so that (1) there will be a standard to compare with and (2) the web page has a demo. 2002-07-05 Joerg Beyer * Tiny patch to report the number of lines analyzed and the analysis speed in lines/second. 2002-07-04 David A. Wheeler * Changed Joerg Beyer's patch that gives a nicer error message if an invalid option flag is given. Now the patch also works in Python 1.5. This involved using getopt.error instead of getopt.GetoptError. * Added a comment explicitly documenting that flawfinder is written to run under both Python 1.5 and Python 2. Lots of systems only include Python 1.5, or use Python 1.5 as the default Python (e.g., Red Hat 7.2). Someday that won't be a concern, but there's no reason it can't easily port between the two for a while. * Ran PyChecker and modified code to eliminate the errors it reports. 2002-07-03 David A. Wheeler * Changed the default to IGNORE symbolic links, and added the --allowlink option to use symbolic links. This is a safer default, and few people will really want to follow symbolic links anyway. * Added option --dataonly to suppress headers and footers; use this along with --quiet to get "just the facts" (e.g., when processing the output with other tools). This was inspired by a comment from A.T. Hofkamp. 2002-07-03 Joerg Beyer * Various small patches - thanks!! There were as follows: * If you call flawfinder without input, state that there was no input, not state that there's no hit. * If interrupted with Control-C, flawfinder now prints cleanly that it was interrupted. * Print a nicer error message if an invalid option flag is given. * Just for completeness' sake, I'm including two of the patches: --- flawfinder_orig Wed Jul 3 09:56:34 2002 +++ flawfinder Wed Jul 3 10:25:49 2002 @@ -1216,10 +1216,15 @@ if loadhitlist: f = open(loadhitlist) hitlist = pickle.load(f) else: - for f in sys.argv[1:]: + files = sys.argv[1:] + if not files: + print "*** no input files" + return None + for f in files: process_dir_or_file(f) + return 1 def show_final_results(): global hitlist count = 0 @@ -1275,11 +1280,14 @@ def flawfind(): process_options() display_header() initialize_ruleset() - process_files() - show_final_results() - save_if_desired() + if process_files(): + show_final_results() + save_if_desired() Detect control-C: --- flawfinder_orig Wed Jul 3 09:56:34 2002 +++ flawfinder Wed Jul 3 09:58:37 2002 @@ -1281,5 +1281,8 @@ save_if_desired() if __name__ == '__main__': - flawfind() + try: + flawfind() + except KeyboardInterrupt: + print "*** Flawfinder interrupted" --- flawfinder_orig Wed Jul 3 09:56:34 2002 +++ flawfinder Wed Jul 3 09:58:37 2002 @@ -1280,6 +1280,9 @@ show_final_results() save_if_desired() if __name__ == '__main__': - flawfind() + try: + flawfind() + except KeyboardInterrupt: + print "*** Flawfinder interrupted" 2002-07-02 David A. Wheeler * Added detection of static arrays of char, wchar_t, and TCHAR. * Fixed typo in makefile uninstall script. My thanks to Andrew Dalgleish for pointing this out. * Modified installation to be friendlier to Cygwin. My thanks to Andrew Dalgleish for pointing this out, too. One step involved creating PYTHONEXT in the makefile and documenting it, which was no problem. A more surprising problem was that the INSTALL file needed to be renamed to "INSTALL.txt", because otherwise "make install" thinks that everything is already installed. This is a nasty problem caused by Windows' type insensitivity conflicting with normal Unix standards... this should really be noted somewhere in various standard documents!! I eventually added a ".PHONY:" target to the makefile, which also solves the problem when using GNU make. * Fixed ChangeLog - the 2002 dates were accidentally 2001. 2002-07-02 David A. Wheeler * Changed correct-results so that the version numbers are right. * Created "make test-is-correct" which moves the test results into the "correct-results" file. 2002-07-02 David A. Wheeler * Released version 1.01. * Bugfix: Programs with getopt() or getopt_long() could trigger a problem with flawfinder itself. Now fixed. * Added the --nolink option, and a detailed description in the man page. Basically, this foils attacks where malicious programmers insert into their source tree symbolic links to files like /etc/passwd or /dev/zero. You still need to copy source code files into a separate area if you are worried about malicious programmers; see the new man page discussion about this. 2002-07-01 David A. Wheeler * Released version 1.00, a major step forward. * I have significantly enlarged the database, from 55 rules to 122 rules. Making the database this large is such a major improvement in its usefulness that I've bumped the version number up to 1.00. A number are from my book, while others are suggested by "Writing Secure Code" by Howard and LeBlanc (for the Windows-specific issues). * Added HTML generation support. * Significantly enlarged the test suite. 2002-5-6 David A. Wheeler * Released version 0.22, a very minor improvement. * Modified the report about %s in scanf when a limit for %s was provided; some found the error report very confusing. My thanks to Agustin.Lopez, who asked a question that led me to this understanding. 2001-12-18 David A. Wheeler * Released version 0.21. * Fixed an error in the database entry for syslog(3), which would cause incorrect hits. This resolves the Debian bug "Bug#124009: flawfinder: wrong reports of format fulnerabilities for syslog". * Added simple "INSTALL" file. * Fixed documentation, documenting --version and fixing a format problem with "--neverignore". * I accidentally wrote over version 0.20 with version 0.21's contents. Sigh. 2001-12-11 David A. Wheeler * Released version 0.20. * Added --version, which prints JUST the version number without actually analyzing any programs. 2001-11-08 David A. Wheeler * Fixed MANIFEST.in to include "flawfinder.1*"; that way the compressed man page is included when using MANIFEST.in. Thanks to Jon Nelson for noting this. The effect of this is quite tiny - my tar file & rpm files already included the compressed man page, so this error affects very few people. Note also that this just meant that only the uncompressed man page was in the MANIFEST, so I don't expect that this error had any user-visible effects other than a few more K of man page space (and with multi-Gigabyte drives, that's hard to notice). 2001-11-04 David A. Wheeler * Released version 0.19 * Fixed a minor bug - flawfinder didn't realize that multiline strings passed to gettext() are still constant strings. My thanks to "Arthur", who reported this bug, and Adam Lazur (Debian) who passed it on to me. This closes Debian Bug#118025. * Minor change - precomputed internationalization pattern for a minor performance improvement. * Output a reminder that not all hits are actually security vulnerabilities, as well as that there may be other vulnerabilities. The documentation mentioned this too, but including that in the output of the program makes it clearer (apparantly some expect flawfinder to perform amazing magic far beyond the possible). I think ALL programs like this should include this reminder; otherwise sane software developers somehow expect programs like this to work miracles, instead of simply reporting likely spots based on heuristics. 2001-11-03 David A. Wheeler * Added a "help" option and support for DistUtils, as well as modification of the RPM spec file so it can be built by non-root. My thanks to Jon Nelson for the patches to do this. * Added "syslog" to the vulnerability database. My thanks to Dave Aitel for this contribution. * Generate and install compressed man page, rather than uncompressed. My thanks to Marius Tomaschewski for this suggestion. 2001-10-29 David A. Wheeler * Released version 0.17. * Created an RPM package, to simplify installation. * Accepts RATS' "ignore" directive, as well as ITS4's, for compatibility's sake with RATS. * Trivial change: shortened processing status phrase to "Processing" so long filenames are more likely to fit on one line. * Modified the man page, in the hopes that the new one is even easier to understand. 2001-10-28 David A. Wheeler * Released version 0.16. * Added support for directories. If a directory (instead of a file) is given on the command line as something to examine, C/C++ files in that directory and its subdirectories (recursively) are examined. This should make it easy to analyze entire projects, and to make it easy to integrate flawfinder into project websites. * Added to the vulnerability database: randomizing functions & getenv. * Reports the number of hits at the end. * Minor cleanup of text output. * Print "processing" status every time a file is opened; this is flushed, so that monitoring the status with "less" works well. * Added the "--quiet" option, so that status information can be suppressed. 2001-06-06 David A. Wheeler * Added support for file globbing on Windows/NT/DOS (it's not needed for Cygwin - it's only needed when run natively). File globbing characters are correctly ignored in Unix-like ("posix") systems, since the Unix shell does this for us. 2001-05-29 David A. Wheeler * Fixed manual page to close the "/*" comment with "*/". 2001-05-29 David A. Wheeler * Fixed a bug in directive handling, now directives work properly. I only noticed this AFTER release of 0.14, sigh. * Fixed the ChangeLog, to note the addition of --neverignore. * Released version 0.15. 2001-05-29 David A. Wheeler * Fixed a minor problem in string handling; a string containing \\ followed immediately by the double-quote mark (end of the string) wasn't correctly handled. Now it is. * Added information in the documentation describing how to ignore hits on a specific line (a comment directive). Flawfinder has always had this ability (since 0.12), but now it's documented. Before, you had to read the test file test.c or the actual flawfinder code to learn about this ability. * Added the "--neverignore" / "-n" option. * Having a number of conversations with John Viega comparing RATS and flawfinder, with the goal of finding a way to coordinate and have a "best of breed" scanner. This hasn't produced a concrete result, but Viega will soon post a comparison paper that I've had input on. * Released version 0.14. 2001-05-25 David A. Wheeler * Fixed a minor error in that parameter parser; previously it might have trouble with embedded preprocessor commands in the middle of parameter lists. * Added this ChangeLog. * Released version 0.13. 2001-05-21 David A. Wheeler * Initial release of flawfinder version 0.12. flawfinder-2.0.19/Dockerfile000644 000765 000024 00000000477 14066157606 016703 0ustar00dwheelerstaff000000 000000 # Container image that runs your code FROM python:3 # Copies your code file from your action repository to the filesystem path `/` of the container COPY entrypoint.sh /entrypoint.sh RUN pip install flawfinder # Code file to execute when the docker container starts up (`entrypoint.sh`) ENTRYPOINT ["/entrypoint.sh"] flawfinder-2.0.19/makefile000644 000765 000024 00000014221 14112765765 016404 0ustar00dwheelerstaff000000 000000 # Flawfinder. # Released under the General Public License (GPL) version 2 or later. # (C) 2001-2021 David A. Wheeler. # See "release_process.md" for release process, including # how to change version numbers. NAME=flawfinder VERSION=2.0.19 RPM_VERSION=1 VERSIONEDNAME=$(NAME)-$(VERSION) ARCH=noarch SAMPLE_DIR=/usr/src/linux-2.2.16 # Flawfinder has traditionally used INSTALL_DIR, INSTALL_DIR_BIN, and # INSTALL_DIR_MAN. Here we add support for GNU variables like prefix, etc.; # users who override the older flawfinder-specific variable names will # not notice any changes. We define exec_prefix oddly so we can # quietly merge these 2 systems: prefix=/usr/local INSTALL_DIR=$(prefix) exec_prefix=$(INSTALL_DIR) bindir=$(exec_prefix)/bin INSTALL_DIR_BIN=$(bindir) datarootdir=$(INSTALL_DIR)/share mandir=$(datarootdir)/man man1dir=$(mandir)/man1 INSTALL_DIR_MAN=$(man1dir) FLEX=flex # For Cygwin on Windows, set PYTHONEXT=.py # (EXE=.exe would be needed on some systems, but not for flawfinder) EXE= PYTHONEXT= # EXE=.exe # PYTHONEXT=.py # The rpm build command. "rpmbuild" for rpm version 4.1+ # (e.g., in Red Hat Linux 8), "rpm" for older versions. RPMBUILD=rpmbuild DESTDIR= TESTDIR=test/ all: flawfinder.pdf flawfinder.1.gz chmod -R a+rX * # We use the "-p" option of mkdir; some very old Unixes # might not support this option, but it's a really common option # and required by SUSv3 (and probably earlier, I haven't checked). MKDIR_P=mkdir -p INSTALL_PROGRAM=cp -p INSTALL_DATA=cp -p # This installer doesn't install the compiled Python bytecode. # It doesn't take long to compile the short Python code, so # it doesn't save much time, and having the source code available # makes it easier to see what it does. It also avoids the # (admittedly rare) problem of bad date/timestamps causing the # compiled code to override later uncompiled Python code. install: -$(MKDIR_P) "$(DESTDIR)$(INSTALL_DIR_BIN)" $(INSTALL_PROGRAM) flawfinder.py "$(DESTDIR)$(INSTALL_DIR_BIN)/flawfinder$(PYTHONEXT)" chmod a+x "$(DESTDIR)$(INSTALL_DIR_BIN)/flawfinder$(PYTHONEXT)" -$(MKDIR_P) "$(DESTDIR)$(INSTALL_DIR_MAN)" $(INSTALL_DATA) flawfinder.1 "$(DESTDIR)$(INSTALL_DIR_MAN)/flawfinder.1" uninstall: rm -f "$(DESTDIR)$(INSTALL_DIR_BIN)/flawfinder$(PYTHONEXT)" rm -f "$(DESTDIR)$(INSTALL_DIR_MAN)/flawfinder.1" flawfinder.1.gz: flawfinder.1 gzip -c9 < flawfinder.1 > flawfinder.1.gz flawfinder.ps: flawfinder.1 man -t ./flawfinder.1 > flawfinder.ps flawfinder.pdf: flawfinder.ps which ps2pdf # Ensure we have ps2pdf installed (from ghostscript) ps2pdf flawfinder.ps flawfinder.pdf # Not built by default, since man2html is not widely available # and the PDF is prettier. flawfinder.html: flawfinder.1 man2html flawfinder.1 | tail -n +3 > flawfinder.html clean: rm -f *.pyc rm -f flawfinder-$(VERSION).tar.gz rm -f cwe.c cwe rm -f *.tar *.exe ./cwe distribute: clean flawfinder.pdf flawfinder.ps rm -fr build dist flawfinder.egg-info ,tempdir chmod -R a+rX * mkdir ,tempdir cp -r -p [a-zA-Z]* ,tempdir rm -f ,tempdir/*.tar.gz rm -f ,tempdir/*.rpm mv ,tempdir flawfinder-$(VERSION) # Nobody else needs "update" either. rm -f ,tempdir/update # Don't need compressed version of document. rm -f ,tempdir/flawfinder.1.gz # Don't include (out of date) index.html rm -f ,tempdir/index.html tar cvfz flawfinder-$(VERSION).tar.gz flawfinder-$(VERSION) chmod ugo+r flawfinder-$(VERSION).tar.gz rm -fr flawfinder-$(VERSION) dist: distribute # This *creates* a PyPi distribution package. Use "upload-pypi" to upload it pypi: python setup.py bdist_wheel --universal # NOTE: Only do this after running "make pypi" & being satisfied with it # Use "-r pypitest" to upload to pypitest. upload-pypi: twine upload dist/* time: echo "Timing the program. First, time taken:" time ./flawfinder.py $(SAMPLE_DIR)/*/*.[ch] > /dev/null echo "Lines examined:" wc -l $(SAMPLE_DIR)/*/*.[ch] | tail -2 test: cd $(TESTDIR); $(MAKE) test # Usual check routine. Run all tests using *both* python2 and python3. check: cd $(TESTDIR); $(MAKE) check # Run "make test-is-correct" if the results are as expected. test-is-correct: cd $(TESTDIR); $(MAKE) test-is-correct profile: /usr/lib/python1.5/profile.py ./flawfinder.py > profile-results $(SAMPLE_DIR)/*/*.[ch] > profile-results rpm: distribute chmod -R a+rX * cp $(VERSIONEDNAME).tar.gz /usr/src/redhat/SOURCES cp flawfinder.spec /usr/src/redhat/SPECS cd /usr/src/redhat/SPECS $(RPMBUILD) -ba flawfinder.spec chmod a+r /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm chmod a+r /usr/src/redhat/SRPMS/$(VERSIONEDNAME)-$(RPM_VERSION)*.src.rpm # cp -p /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm . # cp -p /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm $(VERSIONEDNAME)-$(RPM_VERSION).noarch.rpm cp -p /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm . cp -p /usr/src/redhat/SRPMS/$(VERSIONEDNAME)-$(RPM_VERSION)*.src.rpm . chown --reference=README.md *.rpm # Install, for testing. Ignore the "not installed" message here, # unless you already installed it; we're just removing any old copies: -rpm -e flawfinder rpm -ivh /usr/src/redhat/RPMS/$(ARCH)/$(VERSIONEDNAME)-$(RPM_VERSION)*.rpm echo "Use rpm -e $(NAME) to remove the package" chown --reference=. *.rpm # This is a developer convenience target, not intended for general use. my-install: flawfinder.pdf flawfinder.ps test cp -p $(VERSIONEDNAME).tar.gz \ flawfinder flawfinder.1 makefile \ flawfinder.pdf flawfinder.ps ChangeLog \ $(TESTDIR)/test.c $(TESTDIR)/test2.c $(TESTDIR)/test-results.txt $(TESTDIR)/test-results.html \ /home/dwheeler/dwheeler.com/flawfinder/ # This is intended to be a local capability to list CWEs cwe.c: cwe.l $(FLEX) -o cwe.c cwe.l cwe: cwe.c $(CC) -o cwe cwe.c -lfl show-cwes: cwe ./cwe < flawfinder.py | sort -u -V pylint: pylint flawfinder .PHONY: install clean test check profile test-is-correct rpm \ uninstall distribute my-install show-cwes pylint # When I switch to using "DistUtils", I may need to move the MANIFEST.in # file into a subdirectory (named flawfinder-versionnumber). # I can then create all the distribution files by just typing: # python setup.py bdist_rpm flawfinder-2.0.19/release_process.md000644 000765 000024 00000003207 14055234564 020400 0ustar00dwheelerstaff000000 000000 # Release process Here's information on how to release an update to flawfinder. ## Changing version number Ensure that the version number is the intended final value. Make sure every release has a unique version number. To change version number, edit the following files: makefile flawfinder.py flawfinder.spec setup.py index.html # in dwheeler.com/flawfinder Then run several times: ~~~~ make test ; make test-is-correct # update version number in tests ~~~~ ## Test it ~~~~ make check # Run tests in Python 2 and 3 ~~~~ ## Commit it ~~~~ git commit -asv ~~~~ ## Tag version Once you're sure this is the *real* version, tag it: ~~~~ git tag VERSION git push --tags origin # SourceForge git push --tags github # GitHub ~~~~ ## Create tarball Run: ~~~~ make distribute ~~~~ ## Post tarball Then post the tarball flawfinder-VERSION.tar.gz to the usual places: * SourceForge "files" directory, and set it to be the default download. * dwheeler.com/flawfinder Do this *before* creating the PyPi distribution package for pip. ## Post to pip First, install the programs to create a PyPi distribution package if they are not already installed. On Cygwin first run: ~~~~ python -m ensurepip pip install --upgrade pip pip install wheel pip install twine ~~~~ Then create a PyPi distribution package (for Python2 and Python3): ~~~~ make pypi ~~~~ Now upload the PyPi distribution package: ~~~~ make upload-pypi ~~~~ ## After it's uploaded Change the version number in the repo NOW, so that there will not be two different released versions with the same version number. See the list at the beginning of this document for the list of files to change. flawfinder-2.0.19/INSTALL.md000644 000765 000024 00000011462 13774402305 016327 0ustar00dwheelerstaff000000 000000 # Installing flawfinder You can install flawfinder a number of different ways. Choose the approach that's most convenient for you! The options (described below) are (1) pip, (2) package for Unix-like system, (3) source install, and (4) run directly. ## 1. PIP For many, the simple approach is to first install Python (2.7 or something reasonable in the 3.X series). Then use `pip` to install flawfinder (this will normally download the package): ~~~~ pip install flawfinder ~~~~ One advantage for using pip is that you'll generally get the *current* released version. ## 2. PACKAGE FOR UNIX-LIKE SYSTEM (including Cygwin): If you use an RPM-based system (e.g., Red Hat) or deb-based system (e.g., Debian), you can use their respective RPM or debian installation program and just install it; then ignore the rest of these instructions. For a ports-based system where you have a current port, just use that. This will work out-of-the-box; it may not be the most recent version. One way to accomplish this is: ~~~~ sudo apt install flawfinder ~~~~ ## 3. TARBALL (SOURCE INSTALL) QUICK START: The quick way to install flawfinder from the tarball is to unpack the tarball and type in something like this on the command line: ~~~~ sudo make prefix=/usr install ~~~~ Omit prefix=/usr to install in /usr/local instead. Omit "sudo" if you are already root. Note that this installation approach follows the usual install conventions as described below, including prefix= and DESTDIR. Not enough? Here are more detailed step-by-step instructions and options. * Download the "tarball" and uncompress it. GNU-based systems can run `tar xvzf flawfinder-.tar.gz` to do so, then move into the newly created directory with `cd flawfinder-` If that doesn't work (e.g., you have an old tar program), use: `gunzip flawfinder-.tar.gz` `tar xvf flawfinder-.tar` `cd flawfinder-` * Decide where you want to put it. Flawfinder normally installs everything in /usr/local, with the program in /usr/local/bin and the man page in /usr/local/share/man/man1, per GNU conventions. You can override this when installing (with "make install") by setting some environment variables. You can do this by setting traditional GNU variables, e.g., "prefix" = prefix of all files, default /usr/local "bindir" = directory for binaries, default $(prefix)/bin (the program "flawfinder" is put here) "datarootdir" = data for shared data, by default $(prefix)/share "mandir" = directory for all man pages, default $(datarootdir)/man "man1dir" = directory for all man1 pages, default $(mandir)/man1 (the man page "flawfinder.1" is put here). Given the previous definitions, its default is $(prefix)/share/man/man1 It is common to override "prefix" with "/usr" instead. You can also use the older flawfinder makefile variables to control installation; you can set: `INSTALL_DIR` = prefix, default $(prefix); `INSTALL_DIR_BIN` = program location, default `$(bindir)`; `INSTALL_DIR_MAN` = manual location, default `$(man1dir)`. Note that the default of `INSTALL_DIR_MAN` has changed; at one time it was `$(prefix)/man/man1`, but now it is `$(prefix)/share/man/man1` * If you're using Cygwin on Windows, you can install it using "make install" but you need to tell the makefile to use the .py extension whenever you use make. This will be another make install override. If you'll just install it, do this: `make PYTHONEXT=.py install` If you don't want to pass the "PYTHONEXT" extension each time, you can change the file "makefile" to remember this. Just change the line beginning with "PYTHONEXT=" so that it reads as follows: PYTHONEXT=.py * Now install it, giving whatever overrides you need. Currently it really only installs two files, an executable and a man page (documentation). In most cases, you'll need to be root, so run this first: `su` Then give the `make install` command appropriate for your system. For an all-default installation, which is what you need for most cases: make install (you need to be root; `make uninstall` reverses it). To install in /usr (the program in /usr/bin, the manual in /usr/man): `make prefix=/usr install` or alternatively, using the older flawfinder conventions: `make INSTALL_DIR=/usr install` To install in /usr on Cygwin: `make prefix=/usr PYTHONEXT=.py install` To put the binaries in /usr/bin, and the manuals under /usr/local/share/man (common for Red Hat Linux), do: `make prefix=/usr mandir=/usr/local/share/man install` The installer and uninstaller honor `DESTDIR`. ## 4. DIRECT EXECUTION You can also simply run the program in the directory you've unpacked it into. It's a simple Python program, just type into a command line: ~~~~ ./flawfinder FILES-OR-DIRECTORY ~~~~ flawfinder-2.0.19/MANIFEST.in000644 000765 000024 00000000367 13774402305 016437 0ustar00dwheelerstaff000000 000000 include COPYING include README.md include announcement include ChangeLog include flawfinder.1* include flawfinder.pdf include flawfinder.ps include flawfinder include makefile include setup.cfg include setup.py include test.c include test_result flawfinder-2.0.19/cwe.l000644 000765 000024 00000000545 13774402305 015632 0ustar00dwheelerstaff000000 000000 %{ /* cwe by David A. Wheeler (http://www.dwheeler.com). This prints anything of the form CWE-# */ #include #include #include void out(char *text) { fputs(text,stdout); } void outchar(char c) { fputc(c, stdout); } %} %% CWE-[1-9][0-9]* { out(yytext); outchar('\n'); } . { } \n { } %% flawfinder-2.0.19/._flawfinder.pdf000644 000765 000024 00000000260 14056170370 017720 0ustar00dwheelerstaff000000 000000 Mac OS X  2~°ATTR°  com.apple.lastuseddate#PSÑÈ`U>´#flawfinder-2.0.19/PaxHeader/flawfinder.pdf000644 000765 000024 00000000033 14056170370 021452 xustar00dwheelerstaff000000 000000 27 mtime=1622733048.835478 flawfinder-2.0.19/flawfinder.pdf000644 000765 000024 00000254125 14056170370 017516 0ustar00dwheelerstaff000000 000000 %PDF-1.4 %Çì¢ %%Invocation: path/gs -P- -dSAFER -dCompatibilityLevel=1.4 -q -P- -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sstdout=? -sOutputFile=? -P- -dSAFER -dCompatibilityLevel=1.4 ? 5 0 obj <> stream xœ­Z]sÛF–}ׯ@éEP"BèÆ·§æ!ëÈ3žJ­ÝdKJM 1EkkßöÕóSü÷ÜþB"C¹j*U‰BÝ·ïÇ9çÞÆïŽï1ǧÔçëß¹?ùý„‰OõŸùÚùë“Ë }p½<‘?fNÂ$ ëõ‰ûæ‡ïίÿyÂ/K³ß^/NXz s®w'7îÏoÞ¾ûþêíËnÏ7U~Î"w÷¹^­Cþzý·“ ãžzrôsZwæ{œeÎõVd°ÂË"2dâÏ$sfA,{'Œðéw,ò¢,PËýxEŸà¾ú‰3cœ¾ö¥‰ÿ²úâTÅ9 qš¹ŸÊy^UO¾r6M_Ô}™WNWÌ·mÙ?9âAÏgaìî:çÖ=]•}wŠs–µÓ5Ûv^8ófQˆCŽÍ‡Ù3ãÔdäÇÿ~÷Óûo?JS3eªø‰0JãÆg #/ ´ËÝ›ÉÓ^ø¾þòË—UQm&®È¼dxüÇsýàŠ>ç^$#`ò€y<öõ~½1ÎVÈ<û,–?¹çÌw‹¶+›Z8äÙ¢!÷Õ—/Š5«²ëÛmUtÏ<ÃM2º¿Š‚φ ™*Ä1”9ëib/’ï—½‡¯ý¢]æUWlš®ìKûèQh»Þ:ºíaÛ ‡¢óf|zø<µðElÉ:Ó`ƪ_WÐG-Ùÿ¯‡öx¿Ê åz],ʼŸðY„ÕÓcºlV°#öØ1žÚÑåm¹œ8·¥¥¬œœ'/­œ®¬ï«dz:f‹¼C^þøoQ0£Y—}_JÉð\pBÉ™éz¿oËbÐ~lV9t¢¿ï?Ññ¬y¦‹v ðJx¾§î¬*4„ r Á¢þËÄ@ã¶~øáê¿®~PL¡¯z±J¬š|fˆôùT¡Dôš1ìÍ^¿¼ ‹§‘éò5ûžÿùtÀD¤?‹þÝ.ÊåòK@c£ýn$C¦|úÂP8-e™ôš(µ§fKUßÔúƹ;ç¾»-«}A·ìw4ÀË"ÆÝ¼-» ÊÑ™ç5=†X8ƒ.“Eˆþ1 ’Q‚³å{‚MVãöß[ö+ Á¼A}1vå,J8'rß.…ù¢Õ²¥áŒƒUãx Ë]>ª–xÀy ÕÓé'ÐH2‰c‘e÷íHGd¾Ú67°{1î&ƒÐešéˆÞp¥K•¨Ī©«]±€÷ÇQ Àqu@Fîl=è`‡^—Ž,ë«.?#x Ù! c„ &Iolç<¦BwÙ £¤䱯ÙU ˜¯p΂. æmžoáÜ=9y÷ŸÎét†üˆ\ÎléÊ_±=%‚=íkm#J€Ã³úÁSÕµ…^”M.<èÁû²êQôRÝ[䎘ð GPA(FÕ®&¿8À—÷øe³éAIžŒƒf?Èš=—,ê)mÕ%€бØÎ K8ü&‹ø•éìÿnS q¨d}0ôZg·® Åþ‹µZ  ’l°M‹5R(]ºîAl`*d_GpÙ5­ŠV[v"_¨~ˆCuÅ‹…Ò¹ô300„Ñ20ÁéVp3Ý(íjçsÛõ¨ÒØGޱؽ†sé§š‹Ð)NDá¾.õwL~©á²ëìº8c&%/yIdH%T÷u0°„Ü€øí~ß’õwm>8'ÿúº3têÆç¡¾k¬÷E/¼GPÓï¬×ê"r€{afåeÀÕ–%ŠeLò½„7Û:§Í«ò‰ñ{ä8PR ‚ðj/Ê÷YºmòŽ”n´¥1„YØ9Š]ˆ×“S¸Äà CÓ‚¸OŠÜhô`AJlP¬h‹gfxÄ=2êíú.CÍ.ı,réVJ‚wYÿÁ±%÷ ‰ ÓÏî­dÕ”¥ZOQ‘¥<}ÅF‹F6#Ô˜ýHH¡9ÄŽtß?®o]åó\_ý"þïBÔù±œ· ÉRTý%b‡:]Tôü³ÓHk‰¼Oõ£æ|ޤó(Mf,©Aµ³mÞ´Ô\Ä=ùU¾?‘%1R‘ ™J–ä¡âAŸÅ^ÆB÷]Ӯśú•ŠÌ¼!Ø3™ lj„Õ& +'‚&|”ï-9t§Öµ‰f‹ô9Yܸ6E|2ÈèeŽ?·¯}]i&²E®gÄ Œnò£¸t7õƒz’7¼cÈ ©õ8n c!p<¿aĜݪ±ûÊlg=ßjÜ%†<¶*ïW ©dvÒ ´INwêItdž+ı̖ Õ$Û‘]Ù­(ò$tÿJ:´èæm)ÓI –Žk‹Ák ~}ª8íšÇÜÚšÙ½Sï¼–%ñ³LjXÌ­ ’dÞ"¨‰¯E+ ðøúç+à ÒrzÃÓÂ1¶2NUË碽u;)AùxbUt4€-Ên¾ÀwWÈâ±bºL‰4Æ3µÚE7Ä é”hý'%W ¦¡QãS‹¥Ðš‰?ÏKQR8Í ®€|/AÌäú D—ûÜó”J©à¸ 7ÑHûr pzóãÇÙ]^×Åâ×SœyQÎÑÌñ¢Fh¤.J©ŽäoÌ~HÍ;©¬ hý z]çÕsßo^]^®»Eí­õo<@ÉeQ϶ݥâ§Ë»;ž¦!úŸ¼Û|rä°I˜°$XA•,¨¬1VxÔ®¨îù%ßYõhÚϬ6’ˆÝ?FÕ´€l0[QXij¹ê%(CÛó~+b’É㶪‘zw%Äò“a´m‹8Z^Ø™ž°AÌPkañH]Ð()ÜóÅY`é~CÈÚºMªüÏ€(¾5³ã¡2CïU¤¶õBHW$¶¯œûnl]þ2 2‡té…¡ƒ„¾‘“ü;/…Ú“þ¼ÒëF*Mx,03®Æôýç-ÕœTîe¾öÎw¦…NÒÀ°«~AqîNJtù1¾ýj )N|GÍŸ“o6’ê„­>‰^kzŒjÏP²ˆê±¯&è¼êEEPŽšÎI… ïú™îºäêƒñj"ø±ì‹µ<8#ÉÂc%¤Ð¢ï¡é÷¤È¢ÂDÅÚX|íTÍ\T\''óU1 GÖ¹|ƒŽnKå]Jóa¡Å¸U5“Âm[HL ™a!_²óÒabxŸ«Ë„XµÁM¡¹M¡<5Õ\/TùdHÒåK}¦GÓ¾Ëð-ŸÏ‹ MDç»­ûvÛÑÿÂU­Ò†> °„³ª6ß™*!§–Ü´ ,¦Sƒ­ ¸Ž ó õ›í¢¤½r-F/ŒàXçíÃø á±`Ù ÐgDíN8̧ia@Ìô º­E'Ð5ÒU¨šÑ`¨ë›#ÆšyY‹²¸ôZ{Z¤² ˼Hߺëä6î5mìÑähó•).y(~1ÖÒvD'ÇüÐ ütxˆ«‡jÝ8+ñ ÄSë:'“Óm7¨àަ‘”;(ÞM!™x&éˆ"§ä°S€r©ÿ¨Å/ u ;o§—4xkÅ þîiî"a¯¿¡©pWTKM½›ÑÈK‹±Š/¦NÚˆõ¶ëŸ÷ÃYDZE+ š–”ŒŠZcJ¾®ÍEJ¿³.—-ÖýG³´+qx©õF¾ Ë¢íÔ½+Ö½’È¡–›qô\±ýõÿ]Z»¡¯nKÜË7ãÝ23\¨TÂ;2_©f¼ò,f¢×xÁnßX»ùüènÎ7—cÇÏ"Ô#½q7쨇?) ÷ æö #ƒxJñ 6?ÓÏ‹îăÍÝè†xu>3Bë} ›©r.Èi T+ôô>d˜éCžÊæâôíõÇð•œXøîœ$|ÆÜë¯NU¶  ׉b° Í´}©q5hµêH´’½?ÎÝ%mÙŸiºárdš@ÃqsèÍhj3(¥¦ëJq×C°Ðmç+ „»¶©ï/öôvõXæpz!àxk¤†­Ê9Q¿pv«R^–Ì‚0–ZMG©Þ[ s·DA´õ¤ËÌè¾6‹W4ûÑžû¦¶´Œb¸ES«°0¯GÏt§fˆú©²=Ê'8«‰ÿ{´‚[>ònr|ÓËbh`?|frúÜäñˆÛžíg‘zI€îbE?0oêåV¼˜&Àžúæ]‡ %2!ï4±=-]#eG[QdÍ`deþ¾=—sÞ}–xi7Ú!1ºbJ"{ŠˆŠö‰„"kÏ÷oÛÚècç~‰¹LäÃÕõÉßñÏÿgzrûendstream endobj 6 0 obj 4680 endobj 15 0 obj <> stream xœ•ZÛ’ÛF’}ﯨè—F‡š0ªp­uìƒV5£°½V;ÝŽ0H€M¬@€€jq¾Aú”þÇ=Y7\𒵡Q"ʬ¬Ì“'3ë_,ð9 èùÜì/öpñ¯ ®¾eæc³gÿu{ñݯ)}q»½Ðs– –F»Ý_x¯ß¾¼¾ýß žú2“~½-.xù)g·wÞï¯ßüôÃß~½÷øý5{]ç×<ö?5EÙ1zõÛ\„RøæÍÙã´î*L±–d«0Q¿Ó $NøIpýRà§’f>öeÏò†UÍPvM^³"òuÞ—l“×uY°aW²?Õ:Yè‹,5ÂÿìŽuÙ—Ãý ?Φ"„qõ½zÛ<ɪ¢l†êämÍf¨Ú¦ÇïùÀòÒÚý¾mÔ6„ÈüH¦lÅ…²Ÿ`S´Þ&WÚ¶[Ö—›cW 'öYm1à ©Ñ,ò¹yü±÷Ùí®¤¢À¸µ¸[¯ò¦È»bÔ°ÙÔÇ‚ Âê¼ÓÆ‹ýP&ã›™>ª‡’5Çý„6Eµ½‘/e̽mÙa—ìдYØóеëºÜ÷7êüV"ýLr»9è%R¥Œ–]5lÝ;öP6e‡×«¾?–ÆN:§ý!ßÀdÊT0»€B› .¹/ciÎæôŠ~ Ô0‡u5’¥Ô÷¾{õâ)öÐåû–÷챬kúÌ'»êå¦ú´a¿5ÕÇU]½W÷#œ®–£L»ŠDêÇíŽ+ˆc%Æe¿«·R?cûVÕ­ ƒØù%ëœW”J 8âÉÚ1ª¯ÝQú‰öd‚8RBqàìé©®úA*k´$ëÊCÛ ½òGú‘6¢³Ò>’¡¢É&ÒHŸ´^†ö‚w«ŽåöšÃ”A$½üX¬«ú÷¬.õñ$bew.ýÔîøCéÎC"„déB?Nµ©j¸êË^ÙJúÒY…ÔÐ4ð§‚åke9'…Ü:‹çbÌ¢ QÞM9{;I”ý…‚^wšxò"èFA±k=ngÎ'bó}{„ «.öPÍT‰oü-{húqiáG£ÌöØmŒ3°{&ÇðŠ ÜmÚ¢dŸê’Ý{ð¡ÍŽ á„­aPkTߪ·ð—kð#ÇO2ë¬îªáÆl‚üúÄøÙaºŸeZêÕËGŸI m0ZÍ´g1Â8%VF$(c°¶ÒR‡º¤çi•Øç‘…áÓaj™èèíÊ¢êu~‚÷Y]hÉŠ0§ö¨ŒÐïZ½Ë(ÑÁ*@¥¯vÜ#9 ÿ;¯JÒ™)rª’S ¼’™MNÛ®ÝC Ò ž\Àhe2L'` ³‹;ïéÉ®ÁcémÒ¾zž' $·o5ݸZ² žÈ)Û¨(ÅôÈaÄ¡mëg®’Þв¾Ý—”Š|-uêÔÈ»ARPîï¬Ú#;GpÇk©2²ðÚî}ÏÖ'V´$HK×[ ƒTÌÅ…W+À!&R »Æ:|¬Pô½Zî•Mõï\å—{¯_$€˜ ô·š#Çl:ý^‡±zOé2P„÷tþuÛ¾§¯àKêQEöâÈ'zè W6L!±‚–\û^ÂýxŠ{I¢žvtîÞ;8LPê0ØÉå\ó=©J­ 3Yò+OÎsØ{2j…uiÕ_5ÇådEu‰æ8·ï”QÞܾ‹nØã®ÚìX^÷-‘P½ dŒ$MÆ]Ä6 ŸÁq"Z¡œœ™*ððLؼj²÷x@>3ÛˆS?L"çŸN€Ù̉¤â g—±÷1ßWM©ià†ÃáešŒ „JÒÇÁ©3)ì O­VUöC…s+_ÐØ)¢Ä£Ñý~k,Í™KªÂèŽX{å0†>BË2^Ø7ÖöEDá,ŽdV|júö°Ù\ÙE5hM\êì§ùI&Ù¸¦¡ºy×c~Îz S›:onˆ(3 aW´e¯lôݯœÛ2(#õ&Câ&URì§a*N— þ¿›Ãt„áÎà©Ö x=M­ ì”Ê…îÞfSöÊøUc0*jå­ ErL&±ÄúL÷:¶ÁºŽaÐе5ûl)˜ÆfS„˜\šWoX1ÓN„Ž„›G˜ËÅÅ{xf­Ö°}úf¾ž×S§È21²ýX8AÃé7~$ïî˼Óü‡°f¤wŽ5•몮†Š˜sg}–R©É‘‹¨É´†ŠUÏ &<—§á,·Â³ðY~½óêö&ôCŽê©Sþ£v#ˆ"Ù£2ï[@ô ¬;öŠ€E Cãyjb*ý,vž`Þ²I¡BÓ”äyW骢8nJ j3S‘ÇH4ŽYŸ&œ|€‹ÑÓ2 4€1P¨¶‡é– =æ öBB¢çì¥ßNR¡Ýby6†êqIfæöɼªG£”Ól`ª#„‚®„&Ž•.Œd ÄÓ‡­ŒÃñÌJs…|ö³Z. ¹0 5„h¶±ƒæ:(ÅÄ‘=¢=”–37Ät¬W:yóÚLÈ–ˆ ”dˆG®¯9åÛ4óŽÊ´V 1¿ß;4OÓÈî.5»+ Ÿ½QP%ÄQê¶d„x¤o»Eè0…ŸQºxJó>0¸ªùg{ =P(â…§¤ñó:;\_ ˜:’¡Wn&ù¡tÕy»?TDãïD³Pô®O:ÍÆB–Ît Ï\wZ²@Ù ÝyªR“È4ôËîJÓŰI.j®PºŒ2f)ªÅ¨3Y™1”¦@5lJލ†p¶³ºÇPü€K£;MVf*ý0Mì^‡‡:]PS!º·H-‘À}¾é°`ù©©t¯BIûf[Úéè4àIpð  VµoÁ¬ûö°¡Ú|PÉw‘º8u âqo†!wMR9"!L# Í3]{\ƒñûø6s9âòURF¾©ÌGǶ·GÓÚ1ª¢<ÐS¹h÷@=³_ªrGÜ0mœ¼>õÄôÔ‘¦7uƒ`g5„ƒÌr€]åmí÷GÒMuÜÔv¼— ªrðÔ  ‘n ?Ÿ¦¤$äéH‚ Ó©ËÜjÙJ@Ê“EÛʼnXÆP«b(‘©× “B‘îÊÍ;o§;“´`F©ìjx¨H E¤0[¶€bê~£2•V&CV©eèÉÄÍAd3é0Ëöñ˜ú\„¸©U7rÇag,%ž½»B½g:vX9[è(2'#?ÎÊk™ðñXt\ôG‰Wª½øIÑì|VH>%ËxËç‹n¼ S“;ʦ‡§Þ_¯K [$ƒ¼À÷>O›äIJçBÝmÎDjF ‡Ê[Ûœ&%ÔOÙ†Ô5UòMôuIvQöUWú׫˜Z|¨~ßf'¬ª¨¨âkM–¢ÆbŠã›Ùf$!MG-µ~AbäpNδæj…å‘ÏEXRð T@¶Û÷y‘[ÂããlÓÜe mÅ–úí¡4بäK ã××ýý;Wuºb¢–èÕ—ÚZ*×Ñ lÞñeiF@ıi æ$‚/ÄyS·Òj%) ÕaâGã*ºU° %õ „óµóãÉ“iº9teÜ[åÕ6¨‰â\ø·µ57rב@’M–Þiiú©/š-d”<Óˆ’±zˆhŒHÄø{j*N³]véo.oð÷Ný]nÌÇA}ð]n‚¾'2™tuŒy—þ+õèæ _yõË/úÿ?êÏ/ô§^ù•~ú`þ»So^]ú?^*Ó‡äV©š™¸Ö¼=>ÕWL‚)yýóÉdøT&Ö7ç›WûYÂt…Wæj`Pº>§àÓœi²ºQOÕŽ®u©˜DŒ‹„°06oܶlÒ[Íü”ÛÖ­×ÍQ-E ¹~ÑvÔ¥ÆVº›13éÐNvïÙ*¾Ð.%„NãJ&j*@àìEŠX2pÁ*>3Ê«xCNkO 5 -°*3Gy ÎÞͦ@ª[ªú’k@ò–!ü÷yw²ÝƒzèU‹´d«˜*¡ö-ÈËXëBtÊ]Í™YÏX^¹ºÑè‚Qõº;¡› ¤ð*Sp{ï͠鵃uËRƒ¡ÔŰg4‘¡ŸÐßïìt.L¸~*u3úÈ7ŠÞÿ€ìý[W ½©5q~ܰ§ÚvªÕÀ`§ë£T5òmwFjÏa¤ö\¯&3fm¹ÑæÞ{÷öçW÷×$leI/b”¤9‰>d¥‹Ï^š2!‹b-ÈèÌž&¦Ú4²Iˆ>ئmVë:oÞߨš­ÒЬ&>‚3·jZ›“**¿â÷6³¹RV:£³¹]²H™ovn>¦é¢ÝP! ö±‡ gœûŒä;¯¾÷ÔfƒLx\ï;Ò;“m£ C7îÞêé@2ž’Y› (A5­êL±Ë»à™ì.mÈwÓ})7‡;Ãò?˜¼Ôñ$~ÍJP¿{“øruKWBÕ.Í%gºNu0ñebûéèËäPôW ]Ù¢†€çB95»²ì›¤ò/H½›ˆ•s± `@âBµ1-yPæˆ; ÍÔíã`'i"¢2ÆÚãÑ#ˆy*§ý#îx×ó ~6¶æ }"J–®Ÿqòfîäªø Æâ‹kuËIñÅ-uÌÆ¹V­ VŽz§«G;ÓµV×ó^0’`˜=`K`í³xEºq|{²•sAª@‘2ô^ìfUó8ý ËÕƒdT›MŸÛuéC1DôÿÒÄ»‰È0ÞM>Ç«.šÂ¦B{ÚXÓ4nc´*Çp?¯ËˆÌtÝE(ŽÐ~ñ\Q«dä…é¥ò2;b}œÅä¢!\”ÏÀ);»»€N›:‚Ü릆–“{¤¡¶tõ°Ó´ÆÆN˜j k¢¼0ú«¨™3>)Òõ¿ÄøL¥ Rnd’Q Kˆu©š¸½9öKRàÒùòê õ­¡¯';¸•@Çô#T%PÅ5ÕI‡Ä–êû§MûnPÿ×]ÑÊ„ôj%T½îZfç¼\˜²‘gÙ›2HÎàY;5[2¶L:cµÅ„)Œ,û£ƒ»d\w5¯éº×Ù¤:Ô•¦^<…¹E¥Ér”€úúGCÅ"3Zž˜!uC¼7["Ëš‡+ÿpä}P®£i‘~o/Ô$Y5jÉ0-xo5…á« Ð%WÄÇæ‚ÄÖZÂñ@Åt¯¸¤n*#WMÛ•—¦M2ÇTÀ¬©€ef]éJ7;úF¥ îL<¿$]¿yÔK“PÅ=Çá|o($“‘¸·ž›—ý¦«Ög.]űŸ\þª?CTyysÌŒIÅ­8Þ7ˆÃÌ•Ë 8Õðiï˜MõÈb<-¼3Ÿß‹š ×a@…uäµkõÏ,^YMÖ–¡Óªk…»¥´ÕöŠ@a£IAÚve.¹”Å÷³z ]ژ㦘zzÒüm’RõtfÛŠü(>ÇV±­ˆ€Yæµ›y2rSÒÐt«ÀJ¥…ª² ¾ÄÊζè+›¢×›jO{ÎM\¬À ý,žÐ0‘ sµ› Îö°ŸžÍtPÖÄ"ü–[v;ÝDŸŽ&ó±K0ŠlÚÐsÊ4Tõ€iûå )tŽÇDN.›u4ðÎ 2•Y,g,I3$j]ÒkZª+m[k—þÊ¥ ࣽQ3X”yO›¦kÈúZ0î¡£ûøª…1hþ^5ÇöØ`ÒCÔ0èOýPî}34ÝŒT™lnûŸÖtLCSE#“9Žpœô—Pˆñ(µ5` ¬&׊àÔ ØìÊÍ{F7¨ ¥¯ ¼kùzOOe×µÝÓ"~#šlH¹ôtþ|D>K/Ôx}›ks°Ãœ]YXÑ*rÃJÿÁ¿aöÆÙY-8`$ËþÒEëÿŒ4yPw°ÕÍIZD® †cGCjë¼Ff3§¹óf­úOhùܱ)?ƒXiɘÎò¥ˆò»TÄtÆ—xùضRéö:Ž=ë'yÊ OeúuëÞLÆ;N]IóSìïh/ ±¿ÿôûû/oY]mÊùà¼X@‡!¨%ZçƒâÜxòƒxa¯Ì¿*Dé쪂éyˆÉô+ˆ ÓQWÚÌ¥+}™Ë^çs·º§—¬*®ÛcmZû¶1Ó·ÛáQ¡4iN:Õ÷¡ñ¨‚m%ðÖ,JÃüx–ºRégZî^î;V½¿†ÀŽm»ÒÊ PH±áñ>ÏÜ£¹X&¯éåwNAÕVÄ“¯5QA¡‹ÄVቹJJ÷fmÍÞýO$ÍãåB,R¨ •"¦qŒ2Œ¾:,@½'f·Ivy¿l¶$tß#Y$åTœ‰énB[_º _ sÒÙ]ÍÞ…#„îj×ÏÇVã´hd:zfÒ˜ÏÆÏ—ö$74íe¾ª±·DB5HQš¢hv í4éÏE\GzêÍ]@ιwûî†Æ&4=à º×Áî‡9»oÇ 6k´ bUÞé í7± ¤ ØJAÆ7œ$®l¶*X¡« ö²º‘ö#Â8üz%‚4Ýò„õ·Û‹ÿÆŸÿqËiendstream endobj 16 0 obj 5216 endobj 19 0 obj <> stream xœZ]sÛF²}ׯ˜7»"Œ|'uǺіåZJÝ­Šn•@b(".Zbj‚óSüïé餽›­<Ø&™þ8}út3ÿ/E@ÿÙ?×»‹@<]üãBšO…ýc½ßÝ_¼zŸÒ÷› ~XŠT‰4ŠÄýî»~÷zqÿÛ…Lý<Ë3|{_^È0òS)îŸ/~õþ÷úæ§ïß¾ðäÃB\×ÅBÆÞó§¦Ô Wÿïþoa®|ûæÉãtî«÷9îöó˜®_Føkš‹e˜ÐÃßðÝû›·×âþ—û…̼Û÷7¯ß™S'«ñôR*süºÓ—t®òÓ(÷ë ¥|%e¯ï‹}Ð72ó3•Øo_E9ß×Uz#ôBFð8޼—b·¯µh7bÛš‹éèœHC?Si~þƒN^"â±9=öc•åöËâyºVúñhЯ‡jW=m±ÒâÐëÒ_,cùYz7»â©j´¶Å ŽíAl cÃtMøI:'bvÂûˆW¦q–Ì噣ÞV‹7¯Þüõ¯¢oÝZ‹u[j±i;ãF¨RØ»À~–˜„{}»ÓbßµO]±M±Ó¥x9þþûQšðÙMYË‘Ì,ˆíÛªÃah»ª¨¯ÄÁxœøQž8üÕµ¹4Rø4R££¸¢ï» F—‹8ðƒ )l‡žBVˆ_šêeYW,È^‘ÂiöÝO BRÂÀ]}ì½»ýé/zñ®j/Wâv¯›ï"$üX¬oïÄß9.2}•´À N#“Œ›‰çð»j`]X•U§×ÁqŽ;f˜†YR ‰5ëêxbo:V ýÕ„i~^H …Šðº$d¯ŠU}ýPt¨Hànp€BŒg£Ü{ÄsÕ”–ÀIº(=Û4€"³p›Ã9—#þ‡©ŠXú*ségâ´–€›=ðn u_žIìÞÔú<ÅKy>Rš¤èÎC= †×öWbhQ>E}ü]›h»b&Ë:½oáv+`m¨~Gœëªˆÿö-ŠoMm-9—A$Dgp£º;¯ TÝö¸H#ï±Ö}y44˜Ä’‚wùÛèdæ'2‰cK XåƒÉ™Œ@ÀèØN÷ð³§Ì!k #iÝi"Œo˜r°_Œ,ð«÷Ǽ_1ýSqüÂQ6Þ|5Ì$“ÈNÍÂJi¡[7‡f=T&º¨‚B”È©öô1ÑAÛ4ÚÄ*ç­•™©RDé9B<Ó(áH©?Ñ!J Ãk>pPLÂ+‚ü¨Œã1Þ’,8ÀªNÎxþõt Ý>v‰‚y"˜ó„9áÙÑZv·+jâ@pAOø5”ÈPú‘ŠOP| !h PNŠäT€Z#ê3åŠ3«¥­3¤tŽÎ 5öh@¡Bkéŧ®¾ÕÆi ¹!yä‡Ò…ÈNž¨ç ( z¯v8¼CEåU –vã”ÞˆóÙ¡^¿Ÿ§,J¦”N»¾±"£Á°Ü?ž$OT’ym÷<·¼dœŸÜ#Э[pks`Œ/e ´M´ê'*æ{ :ªÚ„¡;›ÃÌ䩯æƒÏn8NÓåEclªÉcsYõû4‰É”ü5la@¥én(Ðt]ÖOg˜¦N¼Ù¤ƒ~ÔW©¡]„( tËn;c…â8º$Þ_ü(;¥ä,Ó ‹áŸ?ïªæ ‰$íâ8?3*γ/Œ"›f‰ ÓÌÖ…}™š÷Å)ú0,ÕÝÄ,6i²ÐÍ ZÅ\+tEÛ•USr»ÁÆd'P¡WÔpnßöh“§±Vh®q~áXþ¥cýl®AÌ3'÷=½.(vÍ»¨ÁIˆÐ’+Ê(€\Ég˜°Dòˆ${Q·-P}°éf±•ÀÌp ».ç$R™¤V…4OºkýH¶†¡GÆÜ^Cl™/–zמv%ÃccÃÌí©¨ónº9†JÝŒN³7LV¬¨^HÑ›bI1¦®XʶaA"1ù„.æƒs9=ꢞÍ8:âKT:Ê—Ð]GSäCñJÁØXôÚ¨‚²]C7¤N¬HÆó<ÿbÌá1VA.Ÿw4½0¿“ŒäÂ…øÏ623qƒ•MëRúÌn]+ž¾èB# ¢'Ï:cŽHšœÛíÊ?ÜÒs˜ØrDÌü÷,pÂÈ»=›Å1}L ,\ø®©uZ¸†}ÿÍ«W%€®A1êEƹç¯ÛÝ+3½é¥Õ¦à'3[âŸã\þ±B“†\@ÙU͆ZwëF<“p…é|†Ó·VwñÐñèH#è¶Á¬AÀ ×ÍÑ©b«âYš+«÷ìtX þâNƒ\êè`Ûn×뢇Q¦™º¹ØùÈÊp³l ì¤Ê‡¥G±­hö¾BÁ¬ZõÊVö¨˜Zz–¢ë-•Û9»q¢„7üõ¸üÉ¿ÈÕ3 #¡m >`œ¡0òéù4HTO;ˆ„‹£³'YØhwTbÚk†öê ø¼ž7ê49…濲Õ}syòrúyâXœ9›‚8s_@C·åaÍüæ[šP ÑÒ„Ò„v4vÕôâ7š¶xõáD ¦u¾[åYU¥¬l¬6º)©4ºìˆþL‘võÀ‡†¦yìÕ_x‡H5I+H¿ÕSCuþ—WV.ž¼¤~•ŽÖ{^Ùlºv7 O:‹Ì9ìi›`l= ûÃàR |œpÁIR#ég*›Jž~5§2KÇ…•;®µ«;-¬¡ÃS+VˆL6xeeöU³QÜ*ÑŒŒ‚Ði»¯fÙF ËÓéN0 Üâ!ßÖïxPŒ¹n¬›ÓòUÊ)¡Ó²…A<ç‡YIœL¬¤r^Ù˜ÕAZkž¶Oõ@T4v8ÊMëÊC3&YX‘¨Û0ˆ¼Mu22&ã6‹Îç.„– ÉÛЍŒÊ8g¶HúܸÔô®y®!å1vœ1ˆvÔ¾;3MÒîf\Óg:Ÿ±Í’7$|= D¼Á±=|ªÔsÚà¼ÏŸíã¬i®œ~² D`žô|ë¯ÜdF[¿oÌ ±ååù¿X\ŒWñFl\]¸ÛWÃõ R®ày ·å’Šr;hñ¬ÑOÌ|àð0†üЧc2>æeº¬†¶ãf< ´ÁG•˜«ÏÖ× 9®¿þÍÙî èfÚ…ïÇ ˜3šê[#±Œ³öUÇòþ¾·m £ Ùi¢¨øÎe„˜ ÛåyÔb»«´A«šu}0J„‘–¦ÐR3¼¸Ùa>Žƒý2çÌî,DPµ|Š8E¼î4%á‡ûßAÄ›p汇"£Üú‚ÉL<И´9Ôf‹ÏŒ ã³@ÍÖ‘•ÄûŽfÜmGÁþaa²v» )!S¹÷úîæNÜ ˆÇZ¼¶ÚC¼·K¶Z~³È×ãªÆ„fܽ~sç$&²É¸ƒ•‘ÝÁÞ³:pž½Ð¦ÒŒÇüÚIÊx=³¢m[h ?âv“ÉRc€­ý/`š/ô¼ÛŸïonº;UA³“¾^5àùyþyK7uc*Y±RM­0bðÙCJµ†eiìïÚýÙä!M™_^ÆëX<7ãazÅ€†h–ñl^Vv,ê!©×3–(‹¡¸ö#¶kK÷Á›}Fnšò.+K Êí ídë/5N–æ¸ü¸zXfìuGÿ¤{ÌúÕ™ˆ¬·¿ä ¦ŽY?Ir6œà@jvKú5ÌîÉñ¼Ra6uá“•• iØ›¶Ùý’`/ºÒ •ý¡{6>5&桟oïnþÄÞôýA‹”£êFZŠS Å[¾-RÍReÞã/ƒâð4~åhÄFu­ä+0È8°ÑLÍ þÒ™h;ñ¸Â +óyLŠºo]@xøß?ý‚QžÈņëÁ+Û´á²,ú­Í ¬œ9ÎÜî¹hoAiýüùl´H1ƒŽ>ðÓöW e´ÇlBŒ¡[¦ÐâX¨„šmL?nÌå@>®^æ);»1T’‹oÄ»jÕ™§‰Gk—÷Ê~b8ÍéWRy?Í¡¨]Ž˜³gêp•Çd¡óMýùWïg« ^ã:ŒOÊ÷ÉÔ¨¸3h³ *ãq¤óÞpp&hoÓòø?FH?YÙcˆwYÌk5…”p¯–ga“|‚ëiŸ‰^kúÏW‘ZH“qƒ\öÖö/B& ßêObF—±²³7”½‘¿oPóDïh`0ÝÅlàd£ÇÕùZ³ÿô±ÛWö<ÔÅ;€Û„'ö£hÒ’îFKìÀ ãÐyõdÏŠÆdþ;q[‘ÄëËçfAM/‘fQÒJç‘ÕG@³mìò¸\Òšë¿>š“~³*êƒv¿}å¼mN¤I´{ç 9ý|Ò=ÎJ‚èwÌã9×.ö?pŠ=Ÿƒäúˆ½‰£ôš*&èÌÕ::–ºõ´X#æDãä5-–IíÒ§™À²$KI«Ås¡fw |0X¦þŒé`f6®€oíp »ÆVaþÇ 1³ýïèiYæô<½q¶ü€ªŒÆÕè—~×YËôgt¦Gþ…{àùŸõLª‚À†ˆI¬|?oþ&}#H1jlu½?uÈH$ú7€ÄHGk›YËÍÁhr þ¿¡%K¤Ü .ßÞ_üþûa†Öendstream endobj 20 0 obj 3980 endobj 23 0 obj <> stream xœ…ZÛ’ÛÆ}߯˜Ò‹À‹ܭʃmI‰].'±7凥« C и,MÃæSô9=7€Üݨô ‹ÌôtŸîsºáßYàsÐówy¸ Øöæ÷®~eæ¯òÀ¾¹¿¹û)¥î77z1g©`i±ûÃ÷ñ‡¯÷ÿ¹á©Ÿgy†§÷Õ #?åìþtóàýòñ»ßøiåñÕ‚}Ü {§§¦’£W½ÿþ&Ì…oÞ¼XNûÞý”›³oûæì6LÔÊÏ;ýÜÚ–f‹Ÿw-=~ÌîËû!„yvéQ y®d¬×[ÉVÞNî0¶n6mw(†ºmü+SòÀ€³[‘Ár¼ÿà}þü¸à'»ëÕµž›ö l\qïÔã¬ÿŒý€³†dx?ö%fÖŒ‡5ÜT4“êY†ÞõÐûfgp¦À’}Ýݸ—ýË~Æ::?`¥:|ÝìÚO‹öÅaìɦW¦XÒÕÛ-lÙŒVws{ŠCÝ('-i£ºc•Ü(ûDûqOgFÊÉŸXW÷ŸØ^’}·À ŠT”øœ[QœŠ®©›-.\7å~¬è¿É ßþòÕ•l†úIv+÷_²zÊãq_—Åz/é‡b¿gC±¾íå±èŠAVþâ6Bø#óî­/• n­Æ]½?³¦8Èžµvl:'œo«¢ËÛ±‡×›’<Ü+ DšGÂÝ-IÔŽ?âU,ØÐÉcÛÁ´=Í û—žF¶Ð>ϼ]ÌÂfqn4•Ý‘ž!'¹Ÿ#ýmNÓ{œck›€Žƒv>Ò‹õíA²þ(Ëú©de[Iv(Îl-YUoT¦ä"õ6²ƒWèrº ͪ.ñËQ6*ŠÈä˜ÂŸ.!Jœnò˜ì¢çúW3 ¨ˆû©Ã÷à Ò6×={ë˜ 3î}ÛÖu#Ù©vìó{ʹYÕ²¦%˜‘‰1^Ñ蘌ýXìÙN(~ÊÂDï^Þˆ$ö‡}ÿã¼H…IÄ/¢‘"äp‹-)¦˜êê䙭ܹ¡ÈðJ,õ}ÊáKe3HF<6]{@<ŠxZ‚y¯®¨*³øÚû*¡ôÑ&«žä¾zV£²Y¹ô~–{ HcíwÍqØûbPwÜZIiЪjñÐ;íëæÓ+…ÕûšV*'9.õcªÐ/…–˜äᩪ žŠŽ¤ ìχu‹dgt\ÿ¡ ¯0JàþS}<$èä8EæØß·Í[kŽ0 ã ’7Ìh(ð£8Ì'ƒt•ì)—¹öH‰¯‘É3à%›jI›*®÷vº&ô¢)öç?ÉÁ*©ÖgÖRáÆ…Ša(JUäs‘(´`ɸ¯·‡¢1©“Å*yD˜¢(Û<9s³“0vE(ŒµÙ;œ¨€SäÏc×¢f‚X(Õ } ¥>èÇ%Xé(‹{\Y¥ÓìòL6Tyµ›§E~ cÙGýгÈ:u"ýN΋‘¬·él“Ü`±ã^ÒgþÉÒ4‡Œ{ꦗÝp ƒ¡5…ž28šÅFèªüfýXîXѳ;9”wÇ¢ïO˜g/‹O ™Î`źu±x"®ap[ÙIp +XYwå¸/:¶oÛã’vu¹›a:ú`½]¼uPç“Âñ#‘éËÒmt|þ 9©T¶e¡ëƆý¦nÅyèÛ\ñ~ƒ•W4’û °˜Í“)1È’¶Aš¨b²%÷ÒKTÜR¢´PÊj€€ 5‘ñØÓ—ц@µ«Aÿk›aöÅ[¥:üX¨”¼ÿ˃7mµò´bû‰–/O[-ˆVbáGY<#r ‘„&<Åh¨ÎL«‚øÓ¤l§îì{”QÛm!÷ @økú3‘O†óqØJ.„a•Ǻ”³+Oú[©Žöî°î-åVîJòŒë?Þý CHþö«Õêpî‡QI´ á&3³z³Z•íâßgäZ˜ ­ÃøzßO¹ˆ Ës?*»2H2Gžô¢F“ãG@—³–„ì¥ÆÓI«Ç•ÄV½¢×åv$)¿bQKˆÄ€<Î!þ_yN¼6)›ö‚áªv¨êî9ÇMHNõ©èH¤An»ñ8íZä³Ö‘ké`³­5oü7¤RAR`@Ì’z¾ÑZ½éÉjÉ¥FÝ!FÉå‰)-ÁDgçf.XU®¬ ¶çÜ’Z!¤®×)ÛfèÚ=ib]P_˜:«8Ùù8×£|Vd24pi±ëoëáŽ`ç÷ÍéöµŠmˆJd‰‹,Ôz|¬Qr(*£D@·gâZ5Íö?³Véx¤p‹§íØéZ>«ëZBõÈ‚æK½[Ó*óbãCÒis¿Ó!òÙßÑÀ!r%y—^ÊCÔY‹y~Y¯WØ®ê^)’ÆÈ¥4%˜ÌV›pž×¾w:?Ör‡lÓÊ5îÅ&A2O£#…ëÂäñ¥–Xư-\BÍǤûl:‘’ùb:ÁcÇb(wÕãÜ,Š‚Ù<k\˺C»ÞÓ®‘Ûÿyµ%iq'*^ßÒ ¸Mœ@³Ð‘ø fid7©`D©„ö"£-\ÓZLL»è2 ‘Ð6È'Í'lW=ðF‘’š U"kÍŽ}m¥êÖî7•”Dïø„•ªâ÷eW¯%éeã¶¾äü¥Q\P>UÙì9í7Ç)ìz‰)§ˆ]XɹˆjZ⮛è£]®mqaQ—í¶©‰xǦ&«©S$©P‰·jec •¡ÿNímЧŦÎLËbê¢^Ô‰ øÛÿfoÌ®4rÒ E õ=js»ˆRºpêýnä|Y€?x¨)ÍD¡§7KöÅHYL¯¤HÖ4Ëmú‰\‹è Ö!hoPÀØÌ ¥la'"3·|˜+Û©ðÀ¡‡zøõ åšLsï£n%©r]€jïX±Ñ÷ãÁâip!Ù&V‡¬¥lôt„šÃÖ*W3¨Èf Ú]¼ÜÒ¶9, g}Aj'%{ÔM˺iUª¥î:鿆+D'd_â ´ã*áVž™"E¾ ÃÊ›1vËΧɹ ”YêÂJ °¯Ñ1¨I…¡K­áPù=¢\4#<; ÊÑ”ò)W©¥:Öàz,“’×®rëÁkê…zx–á63øAÔˆi4$Bn»ÛÉáThA>¬$Í=Ô ƒº S?NÄÆÓ$Z;ØØöRÄD¹Ü5‡="a'Çå>:[/\BçêgÙl,åFÙ<™!ƒî›HÌGæëaO!g{ÓÁÈNW_žƒJ¸ëî£\×¶­l$ ê®¶zêúA•#¾Îñ߸&Çt’Y2_kQÇm³ÄŒ%I^†³~ИBçºi™Ó˜8Ur,áæOsêLÒÌ¥jhˆÜt…#€ S~…£,O_ÁQ–ûi_ã(œŠÉób|PÿT;ó AƒeµòE9h!âNDN¦Ž½eín„|O“ܾ鯰ãñ(»;£OÀÊ©›Ýéà!Õ2©Fºl–EKwP‘òé-º,¥žgC®•·Z±ÇÞgw¦>wDqêFª‘êâ¼Å^±Œº,¬O¨5vÍïf3o~ƒØ¡Ió 4RQ–òH\¿òÀ/ºä¥P¹˜f×úˆ ÈQ÷ª3cƒT4Ü¡¾ ÄýDW´<¡¾¥øz¢˜¥~”Ž Û9ngƒ(ÍyÔG*ΫŻWR™Îy"²™^°Êí «²iè¢ïÓUl?0»‹èj^ª•ºSJcÛɹœ­3Å 3à”O\žd:J*ÅJÕrÈû™©Ü,R I¥h[–cGcâNöP—4œµ£PUþ÷Ö‡ƒ¬jëö2¿"TêÜÑZdN o\²k+T·é&•™)£~ǯL*ôC–þP ÙsøS]·ãê˜fÊéô ýÎÆ&bîž¡í¸í*Ð_íh¹D½;©ê^ƒ¿\BŠÔ´Íý®™íïún›q¡Þ×}† GWR¾z1Óìí•~Oi”ÛjÒ´Ãe“E ±4¤¸g´ƒ& ÑämìódúØaŠþtoú¼%Ö{º‘€e"½ºŸ'Ìr=®bªFÂp£œ†v¤(£Ü 55’‚Pì¨s$È-’¬/@ãc§'8ºŸqà»y’MèPûµ›* çî+DÛ}ZZÙ¥?þÄ J¹sÇzÔ]Aå&¢¶GŸ°ùy0k޲(·Be.›Ü¬ J}ô%~ì±íã¹ÙY8\WE,ïendstream endobj 24 0 obj 3623 endobj 27 0 obj <> stream xœYÛŽÛF}Ÿ¯hh†ZH »yGDZ7 'k ›3 ˜¦ZŠTxþaöSü{ª»Ù$å ÌÃŒÄfuu]Î9Õó'ó\Î<ú1¿óãÇö7Þpõ-3¿ò#û~sóÍû˜¾ØìnôbÎbÁâ `›ãóúí‹åæ÷»i’&xºÙÞp?pcÎ6ç›;ç××oÞýðêý½Ãï—ìu™-y蜟ª­l½úßÍO7~*\óæl9Ùýæ}jö^ûièÆ)[û­ôȼóA–2ïŠjÏ~,º–u5û¡hOev¡wgk.”ÙÏŸ‹êÔw­r5Ân›·øòÍòvr8ØÕ>|8Ôêu7d›ü†‡®Ï=ažÕ#O= C¦©yP•¶ë+8SWpäu¬þÔeEŶY—±]SY Š­ÄSÉNM½o²ã·øP´,+ÛšµG8U)i5r£ð=orâZê Ä<Ð[Š EB§öTd•ŸÂsÃÈÀý"ª± k‘PTT¨f.(B—ûCr žvÀ÷­Nù¶Í¹1ž¸AâyÃ{¿]í 7 au­‚ëã•„˜®C¾wë•çH….‰Ž‚Xû#kŠövÎD¸Q¥WñLéíg#š"¢žpêßvcH}óâaUݰ¢Ê˾Eêñ;]Y´»\‡~yC9γŠ}’ºö ¸ó±ª•«·ê›$œ[4 Š9TËh[Ä®HÍ–ÎÇcöX¬Õ±üIl¥{ºë†Ãâ2ö­ª¹­Ü-áP*¢ÄÉú²cðŠ»Êþ´"¢Y5ìP›òT·EWLk" \/ñø—5±žŒyýüzž¹¡Ó4?ÑÿP³ªîtÑ!ÕÍÔDY#YYü±äžëyiâHô"CTŽó(t£XŒcUä4›{­²`‰]>/åIæQÆNë²—}ÓȪ+/¦Rè ¥n8”€³ê¬Ä°píÀQf4 HÁªì(*­rÏCß&yâú(ˆ@±¯êFnY±£DÒú˜»C_nÕwhÛowÞ£˜î견—"t=.„s†•O¶¸w+–U[íÏVæeÖd¼êËø”wé¬i²KKi¨n5Z£Ó„•x ÐU#0rWØ8u'·®.Õ8ƒhÚÆáGN­GÐεm=‘kw¨/” ©ï rä^>ž¾M)š‰š ÂAf¯¹ëé¶ûåÛLƒ4ÉÞæÕûwW›GBkáIý ù¿Þ qã)ÿÖ6C #ÑÀ.1á úƒ2ö3©ìFRh‰p.ºëä1M“8q;ÍgǬË”<µxؘ0ó”ðxjÀªå³_±_ H(Ž‹\ž ®¾˜œA('­\ЪøLÉ?ùº„ûúõ°?aäcv<•Ä"µéoŸ(|BqhЏ>x^W4\ÐäCgìT¸OÝ3`wêòCL/}›(Ÿàû#-NbHʇ~üˆ:ÒqLEìì5àè%_ ^Ž”Ùl>¾ãº©ð‡áMm¢˜ÈØô3ðå–L¶Ê[H±x@—ÑÛú¤ øÙ^k†©H®ÐWC:é":{‹O,kÙñ¹î–0fkìcZeœî;ŒƒH” Â¯”ŒîýéÔ˜×e¬8Ÿ_ÎÆÅÈ›‹P½Âf`¹—ë%æÀ¡êÕ»°ª?~‚âºwp˜³Ádº€ŸŒhQ”Uà0½3ÈUfùjÂL’ƒØ >ñm9­v’ûn4™™"OÏLçŠe;R{šÄí¤³í–"–‘—HŒ–Œ×>ƒ^í«÷Žrºi;ÍŸfKÛÍa¤uí¨1ñv¦ß¥1if˜ß/]=´Si[F¦ßô‘©ªw} ©‹îÚ]ÝM3×ïýñDB¬=ɼxʵSÆœm4?ušŒ¯LíÔd×MÚ‚$2‚¡`§Æ1±º†„¸wÚiP «I ÕPZðTÒ1ú›Y‰UàÇÁ|^1S^4dïŠbTñù•À3"µ5±›ôC¸smB8";]àùW „ýLç30ð¬î¯ (Å®g‘€Ä¼Q”Г…+ÝÕX9þ‚Ô#˜ìa@¶J{ñÍ SDÕY `è-Òl  CÓU¡¦¢]öýÌiñ pç\¶Ó®UZ+hLňM:G42[gQu¦©bŒ‚£$8W¸R7N®Æò”¾-0#Ídž;/Õ¥Bå¢1‘#³œµsÂ2š MÿKV²¡a¤ÖH‡Ë!(²5fyôävý ÀÊ:+{jÛ—þHÙ)(T—!F=ßö˜æÒ\É’-&¨Ýˆ™tÈ·Ø^!àùfóÏ;‡z§ÅB•ÇzÖ,ôèÔÔ4~©Ó®CºÂΛNRYig2­¨ ^ãaÖ>gÓAsr³…)u?œ:c™ÑcS›Î‰}ê n‹Ñ×þ:çÛM b¤45;SOkžªÛÖLÓžiÚÐSÝ’„‰%ý#©gu—ë„s&䨫ñ°ýPq"v}[™ç‰‡Ð¬^lç|=CÔñëƒyâEºSÌ`˜5ë»y+hö¹0YÑXÙÕ`6I£ *jÕ‚šû³/d§Àÿógr– ùé5ˆl3@’»y6šdÐ’žN¦ñcÝvp¦•åN JÛYæñTf˜¬ëÆn(y. Ò¬(qSq–¤ÁЯ‹R.†—•®4I"P^’Ž ã‘îôÅ[t¸}gBˆZÆGzP—öšcµ˜¢p¤¶Vx¤ÏüR1‹µjxÌÑÑœ‹,©›AÞŠ-Þ^Mo FqñììðKkü¹‹Ï0ÛD_»úrJ{­H2Ñà·ïo®XH[Ñ6…l;åóˬ3Ê:ö=’e½Ñm©°[)_à»ù@NïèûMÄÒ^&íMªIX§æŠ''£Y¬ƒ4IìÀhYð)¶»+éTÛ‹³µ÷O5¶Ñ¦wN‡¡{/JEÓ“,_üºŒiD#ƒÌÚ¦7DJÒÚˆÌèT¥Z‘Ÿ¦‘c­ž9šƒ®L¿^Š%äÀ‡x]ýÅ6;ŒC0b%¶™ŠEò¤TÅùC/[êåÁj@J †äjBGÁmBL¯õ¥¦±W5ƒÑž*‘ˆæ’tpô ÷0£Cj8Ýqò0®‘ µý¡£»§G›]¹…ŸïÀÙÊCý&j@½±é~’.h>i'ýÖvH˜Æ¤Ä½Oå£ïGf$’lÀUz¬XÍfðÒÀŽá~h&!»G[÷MNM¸5ý=I>=–êëÑÅk|%›ž¨·Í¶oòí½úáÇkFP3íÁÔ×Lž ‡cK#A<Œhuwh²+‹Jp“Ðn²¢ÔU P§,—×÷£<Áùb+Œ}cñA²OÓ;ñc~½«”ýXÏìapKDü5Øšú‚¶óü±•<-?3ØÀa¿ðËÛÊœ¤7^˜–I¡m*ÁJêÚ(W½ûÁÀž™†ßè›be¹@pWþÊv·{ê;ö9ôOGyÌ!„ð($ÿE¾ÚЋ@Wáìšè§¾bªa¹^ìAb:¡*ÍW››ãçÿŽV¸ endstream endobj 28 0 obj 3209 endobj 31 0 obj <> stream xœÕXënÛ6þï§àú'21"u/0 ²`)²uK\ C2 ´EÛê$ÑÕ%nß¡}”¼ãÎ!)YrÒôï†h+’ç|ç;÷| eÄÃû÷ªœyd3û0cú+±­Jòãbvvã‡Åzf.3sY”3çòú|¾x?c1M“4ÓE6c~@cFûÙóÇåÕ¯?ÝÜ;ì~N. 1g¡³ÿ\e²&øô¯Å›™Ÿrj_N®£\×g +%®á¹g„nE³%yCÔš´[IVªjå.¦I8[²ßÊŠÈj¥2™Ñw‹K7¡ZÙÙMjq#¸<Õ¨øñ1­PUñI›áçkø|1?yç…ªNð"§!Y¬fÜ£~”¦ö°ÍðÈÃæQžxÌäÍ®Ÿ4æ­Ȩ2²Vª•5>Ѳ¼ }û‚¾;ˆBR1@(Tµ!û¼Ý’ÇÇ].[Ò*ÒHIÞwM«U¡a$oY¬)JQÀYHÓ Û¶,ð’óø3XîB€hPÏPp©ÆVÌãæàΩKa4«®Ýu-zàçÅ/×$¯šÌF·Á§&/wX!1$>¶OÜ[¡ctyYÊ,ð!ºùóιêoŸHf9ßäÞɦ~cB/îÝö~0(¡^䱨7™ÜÏÁJ‘#ò–tU›ÚFYe÷ó'àYêÑÔ'nà ØQçkÃÿ1b.ÎoµÊºÕ@\^ioñUQÏï3 Ø;¿½º%·­hó9¯Dñ©¨¸‘MW€ÁWõj+ª$—À³1@iÝ;·ç7W—–ëþƒÐf¸½*—qÎòѽ¹}û«»Ìì4¡ùà©>2F©¶ì%Š!QµBûöc@jL^š8ÁKy’Áæƒ4 Y7¹ª§Œz€Ç UhÇ¥€ðÖîqÌ¥èôf'Wù礪S¿*ºL’¥Ì!oÄ#P‘W+Uîj e£ÉuÙéãž'Œ2ÚyC„¤×iØ´•ص]-µ5®åð£8< "à €Óy¹3ÏÈD¨²Ä D:¤¸1>½O[¥Š†¾š»aþa‘qß*™„ü, ïjªPí5øÄOµOœJ”‰…¥ød4ècʧ‰½dêó+JÀhEÄi'}û"´Ïiö÷'ïH!' žIaÿh·µê6[T–b·"À?ÆT õˆ‚¥.Ñ.‹!Kýµ†×,Ÿsh)‡ÏM Æ9_[F}HÙü°$$¾iSùZ ð„mü 8 ØSßÁYÿç9¢"z>.±­Ã×I³ßÈJÖz ÁaŠ|1s”/´*‹eðÎw0þÄ  QìИˆ¥ª—|˜X9,[ÖBŽã¹%– ý™1v×dÛ¶»æõÙÙ~¯+a°jUWídEÁo,ÁV™8›3xòֵܚ7VñÓJÙœµ«¿·ª”t·Ýý°ßü-–à#ÝkqŽ}øÞÌÔ/ïu ÐWȆËÉfçÞ>»<`Šl-3» Ê (Dϲr˜¥aÛ´NAOHã'¬tîF<¢Q:ï¹î }šã4ŽÃA¿±áÔ™Ú‘£iÍ1“ž†÷5£ðÖæ¥üÚ>‘pcÃ[¸Gà"ªÌ+ã2ÐøÂ„ƒ1 é0[ŸÖ+Ù¦†ÈÆkeÓêþËx{7 %¸_a$ëÀÐ6˜ªl9Áú ×IßaÞ ‡%ÆiÆéíÆ0QczB¸è lÕ¨ÅB+Œ;õ¾8Á }­6:Vã3ô—¾¯ÊæÉÂÆ!*ãp±ަ§¿ øýåßøPâø·~ú¼÷RšÅÊNü]3öL»9•ô”ì·9DÖçÚ%NÆf{1s K“è Ò¤ýGQâ:k<-䔋Ü4H$Pn“Éíl”᜚ •fšhQ?'s‡†å¬~q²³ù›®ÂÝŒÍ]îÅ^HC'Ònøi1û~þø'endstream endobj 32 0 obj 1881 endobj 35 0 obj <> stream xœ•YÛ’ÛÆ}߯˜ÒË‚©%Œ`pQÊv¬-Ë¥¸y=¬Re,8\"Š¢¿ÁþýcNÏJk%¥*-‹ÎôåôéÓƒ_YrÑ?÷·Ú_Eìñê×+n¾eîOµgßÞ]}õ:£/î¶Wv1g™`Y’°»ýUpûê›ÕÝ®xy‘ãéÝæŠÇI˜qvwººÞܾüñ»¯ßüíŠÝ6åŠËàô{»Q=£Ÿþû¸¡ûåb9íûÕ뽎3ìZ°uœÒÊûàãGÕ÷+ž‡—<èúUœ…Q”ó`Ý(³ï𼻫®’ß{Û‚÷ŠöèAÆq‘'îAóõ«ÿzñÊžê=NÃTF1NåÂx&¹õ뵎}ËJÖvíoªïØÛ`»âNÊâ l´‚»°¯ëYÕm«·lØ©4+Ö¨R¬kÛÕø»eæh†Õ»úëŒý©9¬ºŠ×[¾$cD›qÆ<îÙ¶]C”¢PHow°©·&MQ˜§~=D±õf 3š&Á¼Cß­x‚D¼¯7jsCFj8:¨ «[‹Kòä±ízµ Wk)°Uw;ü¼; uײªlÙƒbG­¶Ç†êaWS´ª®êvmóã­ƒ›ÂÚsìŽG ÊXRdiðØ—f_]õõa¸aJTU—Ms¦Øž»#Û—ý;ö®íVB" IœÚu÷®<³¦n¢®Ù³?J ¸HPl"¨ªCåsç׳âµvKG Eì,üYÍátòiU \2–AÙRnGôIJE‡)Oè‹ÃŒö!Š|Dà}Ð qr€¸{°‹4P[³ad±&"õ /ë&dn˜>V;r2!Ic=Gð²ÉQ»l{fl £ ÉEPô*MÔR1Ögo ®Ydý‰#™ùXD&hoƒ¡?Ö;Ê.l¨”Ö”ñþ؆œs¶9JLÿÞîïe[>ª½jZ-øˆØµ³¯b` …øÅ*v@þڞ͹;<6Ù°Kn—%…IÅ<OþiÏÙwÝ…ñ ŸµŽ,³4 ÌxQx’&›½ÚV(ÊΉ0‹2Çiäͱ>5—u€R±EhUûz8#Q¥îZýv˲gÆ”V–âÀ@}kIfh L±ÕQÓ2:ôÕUðó°ëÚëÕ5UvT˜Båûh¶~6…‡i–cQÒr$ãPWïõŒšŽe˜HÿÛ²ªXêxÃî.pç›Ó<à‰ð{£ÀÆ}mÒ\·‡ã`WðPF’O6˜¦ü†ÇJô'=µe8é­›À‹( e"¦È§ÒqcOè9íð ) ˆu 1Ê{K1 8­×Äæ€˜Ý 5–CÙuulJÛÿW),¾8˜'÷,yS¯$ö!¦Újϵv!„uk³pm˜›ü*ß35‘ v4Úó;¹øG©˜­±…vE?Û°ZØf©§õã`±˜&¡#üaJµ9RpBâ…Bä(öd${ƒ2]ÀlLX|³(O„ÿÚö¯° }ˆÁIé˜=£€{E¨fê”Ðdƒ´6 ”È™3Lµé[´Òhú¶cÿÅ\,Éß™).‰>Äí±}ЏÒP>AË€ò$_~Úuÿ26ø‡™3Ýsê¦ì‚-äè*a mM—4<ÜX¯A–ÛÔdL¨þŒ©ým•„mÁé®Ûy3‚ÜMãÌÚ©tÆ%®À娱}˜lˆ}4V]”øjÑÇ}ù+ñË¡W+Aº'P`Bx6qÎZˆ,|¢Qš†Å‹0™‚³è”3µP¤éú!{cÜÀª"åcËs‹Ê'é 0ÂÞiâwó*Ô]-å(Dèœ$ùhDàYèÿft£(bøàwz¹uu ü$|êˆiêd=ÕÛ¢Õz=[lűã0'ŽR½§M_¥¶>yj#–&ÜK“Ó0'!îë6°%Nz×”»Ç¥o¹4?XÂEMÉ\LVóÄAè÷FiKÜ'š1¬¡CVÅ[ 9V7Hw›XȦ"ÊÛcG О{…E6>Ü''ˆ˦i,ƒx$·}lÏÆŒ.Fv‰‘Kœ@qÅS¢"ñèJÜ'p^ÜÒþ€6Ï YFïæ™ÉÆB©ñ˜h‹d,‹¨°­e‹x·HRÙôe_+›mº ;ArK×Îü¡?Ìt‹‹­5 €Çr,HäÙG2¿¯7~ò MF×þñš"ßè9@Ò)7ÖÏóþ0`Ì6¡ŸùG°]ˆ)óŠH&ž…ˆäé©V4ÁºW_”ÉòYýΑ²1)†ªûf%8ýùˬéUÉ[ëÊ}@B8¡q\€ÅóI*óßQ±Ýð°2ç×Ça»Î¯L­ì…Úµ·ŠXv ã°™Ï bª/e$îÃyP,ú°uñiVÚÖ˜¿Í{¡ =Ìh#š ô;o°D>‡¥ wµP6õÄPöƒ9êBáƒ@RSÞPç¢èSCŒÜÔ®vèE„½Ëï³ÙÏmMn|gœyA¹ZI§@m;"ålò¿+´©RpãÞbÚs»I]Äéô’òiq³í…ŠÍíã„['‘».üÜÄBW±S·n± > stream xœ½YínÛFý¯§h”B­ gøE$^qá¶ÙDE7ˆ-Ñש’”í3¤ÒwÜsç‹”í4Y,°H Ã9sçÜsÏ=wüó¹`>ý3?—Û‰ÏÖ“ß&B}ÊÌå–½\Lž½MèƒÅíD?,X"Y†l±x¯®^Ìÿšˆ„gi–âÛÅj"‚'‚-“Þ/¯.üÛÅÛkO\ÏØ«*Ÿ‰È;|ªWEËèÕ.¾Ÿ™äæÍ“ÇiÝy`­ŒÍƒ˜¾÷yÆ´°÷Ó®/›šýE°k¯ÛË2¯Ø2ïŠëÙsVÞ²c³oYwìúbËê¦ÝæUudû®èX^³¢^6«²^³¦ß Ž~ƒÏ~^¼š§g¬ìØ®mvE‹Ç»¢gûëu@ÉWÁ“8Rûc-z±»Ægôóêü×WWØgŶùñ¦ Îïß\\ÏÎÔ§Ø”•õnß³OÔÒ¯z±º©ç*’Ù7Ø+ôYí¯§5ÙÙûͱß4u@Q_{%žjÛbÙWG@]®ql G!±lêOë}›fk䡈Lº°‘>Ô¥ ƒ€FßÄwd7 ̞¡Ã5­'eÊiO‹%š1÷eÛÔÛ¢îÙýLFÜRzy[æ7UÁÞ¼_¼þéG ”~矱‚¯ùk÷µ¢ÑÜ.hâóõr¿)—wÏÙt¼ÛÍ„Ï}? äY&ûç|ÊÕ2$€„BœP>AÂKEBvW7À§W–F!4™HÎ6û¶=BÙbýñr"ºXÚlñ÷%ÑÀKIÏdkÕè Ñ 55vú¬ŽŒò£Ô$ðQk¾µØ^÷®A¾ñL(¸ C»§–£8‚‡‘Sœ‹LWé »T¸—ÎËðØ<¡yœ“‡ x¨× ZvQhÔOŸùÕ’%ŽpüÖ’e¶~$ZÛ¸˜gIàDKµ}Õ‘´Gúeø‚ÓaÕ±žzÿ“°ÙŽç‹ôDÎÂç켩‘ÿ9NYNcÛØî wŠŒKCC¯ý“¾†cÑ ë¼:þ˜vnheoä2¢&š†³š^—w§=Ô1 ËW£æ¢Âuu›q³}§Çåzƒ‚„¯j¶s rêóx¬}2Î6¨HÒ5U­µØD™ð+°i´|òÓ×Cø®ÄÒç•é m«šD8p«-ÆÝ#H3[s˜¹âl$dt×m¾eÓÒÄ+‚^;¶J%u»ŸÚN¡}ž{oyßË}Kõ¬Å6|¬µq¢+óF”Ï#Dø%dh)]ƒíào:…Q”’y³ \{Jv2”¸þäƒÕê¤ß6fU Ó]¹ƒ/ïçQœ€Ò[D”CYä5í~…&ßDr`|I"ÅÁppák•V¬Þä''†G„?4hóè=„\ø.qÃjõ@f-õJ,/ü) ŸX>/6Ø ‚4¥b_ËUÄílàÝŒr’ùB$ãÚ«’>]@’È:Ã7ÚZr?67-ù g7(%ªµtºr¥BÐN‰w9 œYï&a²Ç,š‡ˆ$ÁQO ¦Ó„¢m›V»éof8^ŠÀCzmT}—ÀBÚ­gȣت8h÷i&CZ1ò>öj1 0ÀºbÝ[Ó&Ð2éÌ£ŽÒJmôœ½ÕnüÁ\¢ ”)JgŒHRÍgáçûÆëOõ¨#ÂX÷Jé–Ó»mŸkµ…¯Õy^@žÕ(“z”IÑc­¼'^;3ܼ^y Ln¥A~¤’fšƒPzµwtù§S®«C×ZYV…¦>y7P^mßìɶö…gœ0iPšèl­Í$ ÷Ö«NSÔݾ5c´ÒÄa ²IyeËJ)£’I¬ÈÇgb›ÏÞ±33«Ÿ¥^^•+«æó €³›ÔÎgpzx/(R¬Áô;Ó{Ü [éGŒÌ7ðÛŽ­Ê.ß™“'˜qçl¼ðV ÉCâ˜Ç.V¿´Ô9X_?NDa«{‰BÒAH`µÒÎ ÿ‘ýP¶Tt”(¸ðk€R —ýÞÜIÌ#Äù™÷ºÙ·{º®ÑÛÔ·t}£’w(©6‹j§1,ìÞ4¢¦aô Ê•ÄSäóƒ›ñUøŽ^;£fü³·ÃsYD7]tß„†F5€ƒ\üãÅo®.ÞÑq†Û°±1—Ò€öº Ùÿ›Ë‹(£Ë "iáêW÷âŽ*uÓè‹ z:IiŽë^‡~&(Œ×”æÐèˆt£\¦6 õ½n".ð ® u€Þ]Á~?íÐNiÕ>?œdlðÎAGú¨Jã“a ç‹1QÓ` “AÆ#ñn;ôo3%n§gôdaé6ÖãH=[dpá±›ïÇÔ}a€V÷Vzd…VÌÝÝU»»!ŒÆQT%új£¤Ö8 ¸nç.éÂRM@è/¾ë[F,ÁÎUÑ•ëZ{›u,‰bò Ú&( öÚ&ˆ¶$uS…ÔÂôí«²GRÊFRF×$XXwU<èD@7rWŸµ’U³S7hú¦-Œx”YéP×ks3 aÂŽ^¿¨ÁòLÛïã ¢Ñq^~Q2á¿j­ÄP…©ld¢¤î/mÑïÛZý…Œ³1Kʘۦ·¯ê¢Íoʪì)¢ª8~|Ø‹êÎÈì‰p‘yÀ’Ôª<Ù¿ÎJÐô»„2«Q»™Ø›Í¸'áçàS©o30Ûò¶ìî†Ñ5Á¯3ªÎ^e#ÿ¡–.ŒS«6—no7’íŸLN®¼ÕôÀÝ*ïF¡3²z†$kc~é Š TDöÇ·èÿ•é Y6šw£ðÿDe-H¿x‘¢¨¬.RMï‡ÅINÿ.äi)ûa3Ì}nª3š–õ'tMè&ÙgéjÃ²è ªÒ×îêé³ô‰3ÿ5ü …êwIlÈñ”µ1æskc¨£þP#}˜"Û  µ¿ÇL*})fs飡Á£¦ŠŒ‹Éßñï?”¥;¤endstream endobj 40 0 obj 3126 endobj 43 0 obj <> stream xœ­YÛnÛH}÷W4òjÆê°›÷—v;ƒìI„y€iK´Å //V´ØOp>%ÿ¸§úBR² va rÄîêêS§ªNÑ™ÏóéÇ~nª3ŸÝœ}<ú[f?6ûÛêìÅ»„¾X]Ÿ™Å‚%’%aÈVÕ™÷úÍ_«?ÏD³4Kñtµ=AÈÁVû³µ÷Ûë_þùòÕ»KO\.ØëR-DäíïëmÞ2Úúûê׳ “Ü¹š¸rØ =²‰ ©Ñ‹û¦);ƒŠµ~TÙÃfÇTǶªW&p.U ³óa*>Ö·/¿^7}Ô¶ãĘHoQoêò £­6ý J|Ý eoÊeÕhzKÉ¥ ø~fÀ¿£ëÒÆ]®È²yÝ4TbškýÀØi-X¯¨&é.ã7Ü•Qian )ÜI‘]¥#V©»Êr~=”?{A¿/@<¼-nà¢FØfqÐYä¨jUŒWî´©„„¶÷u @¿k†›ÝŒ‰`±àJ]YÄ®òžn»Ù5Å&7é‰UÕå|±ŒÐKaÍÙ— À‰lÊ¡ª]ÂJ³ƒN~cH±úií}y¯×‘ʼD¸°´¹5Ý„ê¿*ÑŽ@‰Ÿ/"E„1F¸°hjbñ½õâíË÷ߢV=B-ZŽøÒ#´©ùgòý¼ ÎKeê ¢æ¡Î'©X7ŽeJM2›#R"eE:R&2IÿJ!¿PL(f†èùÖPšEfáT&„a3R¯ÁtS”L°X=TWy‹VÙæ£!s°Â8å3"›JÅ aR.PT|tŸ1U¶Œ/ÖÄq¸ÎsÝv¨ÐD&°Ç…æ"ºž·€C‘÷øÜõUI¡©ûüSo+Â_X» -˜Ò3°sZg?¦ÈDýŸ[.}ÛÈ&Uk¶p™¤.;þ¾úÇ›Š»3u8‰=ćJ§­:–5‡TG’hŸß7C»±­‘Q79uSÖº>¯´ò²õÙ,\)€¥3j¡ð^7îyjÛ}(FÍÕÞÌôNÊǾ˜«I€Â£>0H¼WÖª4RIr—IwjÖRÅ\sÔj‡’Q7;êGÄ@G½²˜ëP!c.GÙÕÏÌÍe(¨ü@¢‡ÁãÃñ«sŽ ƒ†àá£b`® ‘ªeÑ!G{ƒÂéÛ²r˵lø‰¯7»ßOtbÑ•f:1ôã´åÍ=¾;¢íùC¦#cñÀ½|×=þr.]¯Ã°©ŸÜ3³ ‚|¤@ßÎ.ä‹Q§““†§®Ekº^õCG4·ZUâÜ’3ˆ8“Ýh‚ÓpõdTÕN2ßAìM·³ÅØSŠŠ’‹Ó¥–Uâ wœpõ,t€ñôl‘aBß…&”§¬ üÍùqÖm‹ëëÇÙ#°+ þò€ì‚И‚|Xó~€<l2£òËÌñà|žÏINùŒîšã1±Â.ØŸ`ò0FÅÒ4ÃúÀvS„'ÁX»†0ÐòeŸÃïçîÌPO­´el×ý¬pAx„cPË-úŒ‡î¥T±³²ñ zϦï)~<4V,OFåx4XÓYF9ÚFŒR¸¥¶iÁ$+š!IÌ“(p‡î›yÇ㽜*ùCïÄExíý1XDIàퟛ—"Î8ì`œúžßÍË} W †²Î[uU”E_ú(V5ÛâÞ –ËO_0 Ü´ª:'Eqd×Å7\;ÞïDòÝnƒRk½n›Êèë’’ÌtÚ4 O:­õSiÐÊúߤŽN‰Ø-ž%·ªG§…öHQ#áåd 7ßò'Õ¸m‰ðõyõ±7>8-áѦr<žª:Tá"ð}·ëüjža(§œ33„7ØÉÊNY¤+g †™AÕ7@rVm·6Ô48G'‘¶åD™äZªÛÛ²À> ¥Q­*»¹œC/Þ á^û Îåvº(d^Œvã˜0">¶»àCÁåDåš ¦mOÄ—"ëå7ù'öìâ·W¸šÿó?c »Ÿ¤ÞæÅ“±C|TJg·DÇ‘» l¢ð Œ™·91‰ÛшÆ#¯cÂE~1¬z’™~}J“v;bE„X`A¡Wr8 ¦š’¥Þƒ\’¨6àîÔ ©ç-2b”ZÍÌ—Ìùò2õzJ7äù]Q%ÉʘiÂh浞dûÜ %Rz0¨ dÁ¾.Ç{!¸ùpÿé«râyÑU–ù‹Œ{{Mûäèžû¢ßѨ£K§Ôb‡³¡Á:N4µOkï¼[È)Å-z½ßäcÆ#ŽvþöTu… Þ2ˆ°j*ªÞ]qô2UÌ{Ñ~¦ŽhÁ$Ö¤ô¥ÒP €¶5¡[A™a è´*øs¨n©ó˜Á¤ÌÝ›2ÓÌüÁÓªÂfšWø8:&älx@Üȹ×EÛõçúÒunÚ^á8¢+YŠÑ ’øˆ&¦IÚÚû³ÏÇõ3á‰t²Jíçm-“„ ¤)ЦÀ Ó\À-ÕÐB(ÌÐ×ël »ß;å¡}pv|ÙÚÌÎBÅ‹îÚS‡ŽNØÎ4³,£S¾ŸhÊÞDIOƒ>¦· »Ìk 4ê(š‰<)RÝB[…ìFÖºi<n¿×8[÷ée¨yHÙmu-‡Ç€ë rÆßD>4çò3Ñ )»Fê¦ÛCEH“e/ ãñåÙx‹.Ǥ¿µ£îÍæ7»D62zPÔÐAæn§ÜR9½@Ä1ºŽÑÄ–À¼A-•ǹòëP3éK±y"ò2}Ô«ÕÙ[üüõQ½endstream endobj 44 0 obj 2636 endobj 47 0 obj <> stream xœ…ZÛnÜÆ–}×WÔÑ‹)5Ã*Þ`'AN‚8 {(6[ͨ›ìlÉ=ßà¼ÌÌ?ÎÚU»ŠÅ–Ã@¤¨Éª]û²ÖÚ»ú…RDôÖû‹HÜ]üq!õ_ÿ¨÷â7ß|Èé7› ó°¹y’ˆ›ýEðþÇ7W7¿_È<,‹²À§7ë 'a.ÅÍãÅÇà¿ÞÿÓ?ß}øÈOWâý®º’iðø¥[7ƒ Wÿû懋¸T!¿¹xœÖ]Å9Ö*Å*Îèóˆ †c‡ÅÚýµ¨ºµ˜¶M'ÚN?…JÜÔEæY¤xчž?“ôYi7ÓÏb¹ûFüiHé &áW«Gú$Ò•a*íšÆsŽOÁt:´uµÛÄfè÷°el× øé*\¬¼’J…I.V2ƒ´Á{m[F¹6\Faâ6 †Éí^†²PQl-Oscû¶_†qÚ̸U–Hkúi±ræ=×õàV.Â2’ej>ø;ñ'E)Œ`« ¹yœú¡í4Šþ8ŽŽ)Æ~ßè8–žÏ%ÅïÇwðÈXÄ%Ö¡øª´}Ëuf`å]sùéêú¹ðeQ˜¥_^Î+!~s”rr`Éï¶{ýn¢d˜À1p¿y5)Rýêql»;}¦Õ¢?Lmß]‹]{Oo)dt¦T†å“fŽ ‚¥¢´´ö$ô8Ť¿—ˆ>- àñL†J^Øú 7Û†Jqj—_vµÁØÔ=Üÿx3 UJ–yŽS•ÊžêÑË6ýˆý`[¡èÛiKËØSàõFØÝU]jS._ìŠ7]7ßç9ìuiþXY«”u©KÎÁ©½Ry6ˆúW\ïG$ÚÚ/”™œoðJc™lœÄ¡TqñÄÙ«$BÅ:F&Aí1<§þ8ˆ}u…Œ¢<”Ê¢¯°ÇàNhÒ$.C[Ü«³C³°Œm|PfÇuowp WÀñò8²¸Ú\ú‰è,­Wþ4ì¦QÍÈ q!S}›¢4t9Öœ¥5=ó×9\†LŽ`Îbf"ÜøêûN€È„ùQÍH>]Ó¬‘üöœ›~p’@P¨°:dƒKZÅ x*¥å7ž‘qn½³«P`·»f®¬Çm[oÅaWÕ°¡©ðû¶ÕY½RYF©<‹2¢«IæJÁªRåÁc‡xtÝÕ¯@2²{hö½3ç5œÁBqðÐxÑCô=â·¾KcWŸƒ¦ÂÙGaÜÒOôû¤«ÌåXÜ­q®ns‰¯€^[ñ͇’ÒJƨŸàÿ¬Ø«ÿ÷ë/ÿ&nÒÜ,¬ ÅÍÁoýÕ+òyÆJ—^Á±ö¡ q-ƒjhû#b´n5qp5p?´McUnñ,H•N Ð‡f<î¦1¼Z¥ ’üu³D¬îR¬Ûùq52t3ù|ž(W¾³Ä…z-g¤2 ƒ5~:[ã04æTI<èCm)^¼ãp)èsJ¯T-ñ¶ªïé “UTx+ £e©õw$ bþÐÀøÇuF¿¢®h-ŽB*¥©ô9žX‡ÀUàPFÅ-UŒÚR.*[$?€Äœ;!-{âEE|p ýÇahº ›ÁÓ0Hb´Ñ$.ÿ8¶õý—Ïl*(õ¹¢ÞõcÃgпëw–¯peºšâ¬0säÔEl”L(¾g ¿h–‘Õ&C6s† ÓAMN4)^»ÞjÚB“Ø‰Ñ S¤‚ ˜ýГ¹ç£å€d;jsíÇ!7ŽZŸ!üÑ,Ÿ¹«FQo«î®Y;Í0%¡_°AeXS€l®ÅïÇýꄳÆ<§=¹Ñ[“*P3ÿš2mw¡øMCü”³Ìç€èmµ HW_E¤æ¹Ê?C1ãDÏ’×y( ò19YäWšÑ´¥ST°¾0ÂéÈœíg·Y)Mˆœ[kß$•dΤnªÐ¡@n™õã(v¸¦½±RDQ1omd#¢Î+ P«[Ä*uÿÙh11œ8úY‰Îâ?­BP9©f•áƒaœÙ¿SH©m¹=n-ÑCæÅ9 ËÒÐÒƒÞ–àb×|‡_!; VB[”y}hãµs>)u໪®Ñ4ÂQ;±®&hð~5[øä¢"’ +Cxñ{«§Y4Gñšæ­œ@¹'“7Ô3_èU›}ULbŽh¹¼LjOƯ©Ç›øa¦ÖĨo‡J“Èx§†·AÕ»ã2àònhb߯=”Á‡ªÁüißP¶ãÞQ0 pDå¶]è‡{“ç8K–e³¹…J "‘¼× ÙHM nR>UšHEz¡&}ïøòz?§HL8æðáÞô‹Ð1ãÉò¢¿ Ôû,{ƒGO¿½Þ|èh¡}3ŽÕ]3^»Ü4cîÛ&±‚ÍÃÜæÊCµ˜ øI„vü8ÔD®ëÆà×—Ï&—c4‰r€Pu/꣓'ìœå±K]·7:þ3RðDs…YðÀÍœ1ï[ðèõ,;ŸôEJ8R.Rö™0S/7€>ûZÿÇö| œº­‡¦št£Ë¬©›k°L|#¬`“éºÀßxtSª¯¨5d‡msÉ'ØHFú•Э<Œæ]…Y’²ÒY–É|>tȬ<ƒ~ÞLP$þêxbO€ »)U&`íô+ EfË»0õUÁ®YrZ„hî]ÍJЛIöŒ_ø'ÉíÄ ðNÈ=|žÆs§1³R7õÇz‹Ä{dĨËvwB YOõ Ÿ¾Z’j…¹tä[ð’`UϬ,̳™ í¶FèɼÞÝé2((Kc×Jü«×ê3*ÑR1h?vú›]„“'"ÁbvÐhð(/Î9Ó×tøvcš#CCæò•fÕÐV¤uDZâ‹™ÑxÑŽæ x-ô›Cã÷ê¢  þ>Q;.ÈUÜtå…²³5`K¦f)÷N۹퇇K¥CóÅý¯¾4yñ* ¢-1{ª1Oa*Ûj¹.`l÷-¡7gèƒád¨«™EâÄB=ûÎËâ¹pIe&¹ΑoeJÎÔ¹E åÆ2Ή,pé÷Ñl#—®Ɔ+wý U¼”÷tßl4¥Ngủ‡^w•“~¢•é+’d3õÀ¶fe–A&¥þà%6ÞÈæì`ùáØ )y…%o¥ŒôAßÝ\ü‚ÿcË®endstream endobj 48 0 obj 4237 endobj 51 0 obj <> stream xœZÛ’ÛF’}﯀±!ô‰Æýb=ÙrkF³–<+Ñ«õF »±—¦¹¯û*ýóžÌ¬*€­ÖxbÊ ¢*³òròd~w|/p|úOÿ]í/|çîâ÷‹€Ÿ:ú¯jïü¸¹¸z—уÍîB^œ,t²8v6û ÷ÕÏ?\nþû"ȼ"/rüºÙ^Qìe³9^|t?¼zýö§ëw7npsé¼jÊË qŸÛ­êZú_›¿_DEèé•g¯Ó¾Wï -{‰—Î:JùÍ×-ý¾¦lª‹Âó½ÅCG?øò´‡¾(ó©nïœ]äž$Ûí×í¨îúrT[ç'Åê˜-?òòÐlª›FQ‘ÇòÃG·é{ÕŽÎu{A^fîC½ÑÒ¯ƒsã¾þézÀ¡Œˆ„öšM»‚À g„,ðŸ"ôQÅ‹ßèÒ߸ e‚ÔRýK7Þ«v&Q+§êÚajFçÔM==z¾Ü1Œ¼DÇ»$…¹èÔèt;çÐLw뺼Ù!^‘ˆÒyá!Öa²9^þòæÍ/o×?üûÛë÷ïë·¿¾¹~÷Ãe{EšÅîæ5~½q_~¸Ö¶˜MÇêÓ^dä2ws¯œ—Ý~ߵΟBPiÅéµ\<«ÊO­xaÚ+¸³Æ-Å©ç·Ë,†?¢Ìý­tv]¿/§©¯w¶uE¯—ý‰[‰°¡ÛÇËÀwË^9Gì¾ÇùZQX‹þEIºœñ¾ªl®ª`õÚìD)J¶‘a±«öFH°Å‹üq‡rvHàù±^FÒ8­Ü¾º¯GUS¯VÎV õ]KþÞ*:P½?4Š¢NÌ`UjT¹uÆÎáPãÄËSš®ËÛ†Cª…³+‚< GªÇ“ó05-Œ|[7õX«Áó¼ËuŠ€OüÀ­zÅÉ9ƒê$Á½4—¨KS/ËMæ¨ò2‚=“ Å+~“Á*~œy*òÅ3MÙÞMå"7ÒÑ«¾¾¥´;#ោÝfõ]ø/(°PƤ™¸m™å ²žxþ­\ûèÞãaøþêª:*o_½ò:J{÷í¦ñjÇxÖ¬a ð^ù»w?î››KÏyE»Ç)ŒPœC·ïpˆºåpeOâ"™=(å<-0\D¡{ç™ã.ã´©ä§Ḵ襑oÃ*#VLó0]?R4+’è”í–²¨ÛñZDNêçóÚP4þ\ÕeÓœhÁ){€Îˆ'„F‡ÜØý[=j‡è8Øþt¨+^S·U3!zK§WZ Ù#ë ɽ0Ê­ÓÊ¥Or ƾ—¥:ÇsÔ@æeQ>¿ý ¨±EÕŸ'ññÔ”âG`¬"ÓwçSÛ]†ÈÞÂÝcKqû­s¤(i”ý çðÓÜžãõg*oã‘Ån['hÅW•B-=È3›ï%aÄÊÙ—íÙò$ð’,7(u²{gR3ø5ùm7Ú­s/ÍÒ"™uèFìÜr¼ öüÌdÍ´k¡LîT/)’#FmÍYÃrŒ @¸Á!«%îa5eCrváÀo¬h˜ÂD6?»½ ñ‹Š¡ëؽÔ¹[u}Ø(Ñ€Í0p:Ά·I›:~ÄèäÖã=’Þ©îUÅ,c¨ÿGQ=©ÛÃ4|¡w ÒS/ ⧦Hýœ üT.+×˦†ºr~¤ã$x§tçAYTXTM{|Õ鬩Ïù•0óòÂD‡ÖçH*‰^·gJ’€4´õj§C04|$òMúvutªÙN¹åó;ÆN%¥#êA»SªND©™Íµ5ÕÀ?ûz_ž(½¨t«-A ŠïçLþ¶yó3ÒŽË)›¡3 28÷rø˜´0=¨~Ô…ÐËgGÿ1bóöÓ@ylBm«>·µ Ö}G‚’ƒ¦Xkõ5èþæõæÝµ±gŒrcw×Ð>Þ6ˆ\@õ,rË“¨'åÅV3ꬾœ¥>–$©Íîò¸d Éœö‚â"Ì@ªñ^Íé#­™F„%¬õûT÷Ìc$”®ðT_ÐmTؽ‘šCèGE– ´/Šy*Ó@µ¹º¬«öN /”÷Œ&‘ÔsâÕÊÇGMÀÓ?9çG}PÄѶ¥öàyá¾ÞÑIö( ¼¸ÈçÐŠŠ˜5”8Žò‡S°Û÷àÌ5Бk-ò˜þ¿lU7 ÍIR$§Å86cóxµó|Mc#Ij`ËI;%d(ÔƼÛеDœÄVçŽWìËÁs6"0ãØ˜ÑG8²´•f¡6 ûôõþÐwD(ÅÀ^Äç‹Â-›zË5ðž¤úë|zF‹ò+ÄÏ4ˆjéÖ®~iŘB}Ûôµ -U‘Té^.Q5 # Lz8À$R”ÑÙì9µ`äv˹¹r¾Po T,lƒ‰s 2Fˆ&Sh­„‡šÀÁl€Ž`ɵ¨ªÒ°ÿûŽýU2Íä7I´?t{ü¸ÅëÖøüêýoßÃÐÉ-GèƒÄßYÑ x¬c0•<˜I~·èÞ‰ŽÏ¹I5’( :û݇ÄÇ‘Ê"* KG.Î8î çu-̾qŸÅùE8¶æz ¢cSØMy 3•RïuU #o&5‚º›ší‚$Ãnšß§Dyæø qŒŠþp¿B¬Ô’6Šñ|@Cø -û»“¨Bì¿Ep•pÓí sRûO gó3ªˆsM‡Îæò¹yÆ•Í,•`÷5¯ gÒ©†®yÕ Ñ7sÕS㲆߭laDÖÊYk°ŒIÛŸC˜óGBTmÅ|mŽO%ƒ€g ïh>Ÿ¥s‡œ™î'à¾+~[›òÙjn¤“BÏÎÏ­¢ŠIY¬¸·ÚuM#|- ÷(µ tž}÷LZ¹(μ4‰Ìa³"Õó¬ÅŸ²YNèE˜ÉÛñlš° '00Ýò£9Éæœ!Qg5Œ0·36I /”¶¡ð¹{qûòQ1G=4Å<°­Mytê³Mл&IfG í2>ûQD=óèiû-±ÏD%™{è‰f¹; û1\63côZlíˆJ»nZÜ÷ ë˜HD´$‰8«cß]™ê¶U¶HêyFÕƒQ¢õZ&Oü¾Á?òªÎ66‘ ·ù Uw³ŽOnàDѪT¦$4e¢4¼’¿³ï¾Ò ðµ&xsµLrCM3Î-Woê9o;°çç|[ÏøYn.ËСI»@¡áÔŽåÄ 1w}·ç¼¤Ob“—ò Ë‘LâÀ‹‚”‘_–³ã»nñÚJç§(5Ïcš™”žšòõû³|e#y5浚³f1çUEžŸ^zl–Õ23S:×òº39ß} µ·…1èv¸h|ÐH`-7¸zJÑo¿AÀ!Y( š~7óŒœz¹¹uèšg…©[T `z1sÒR·}³JrÊätÑÇå:å9ÄÉSOã¯Àjaêº;01 ¡—Ýw➉z¸_N‚ÿPNÛÐîš­ ¾·õ– Ò.8Eó´l@/D&º©Béàâ4“Ü Š—-| Iƒ õ|ŸzÏaÆ•½¢ø®‡=·‡¦Þ4 â»0¡ gYË(OÐFº­Ÿ ÛäÚ„Rœª…Dy‘Ûd7â4[BYÛ:ŸÐ>‡ÑŠ8eLÌpn*:ïVÓX«žÈ ÎÌRÌlµÏœ5+ÄUºãÕ+ãïȤ<„ ;^=–tFð¬kÄM½‡îqá*D H*ÖZºq{ÜšNí–a&]\À=5c¶¼— pÏб?Èž(~es¸#èš„4A¥Û+ #1r©yâ·)¨ëQZ—µs:·¿Ò ’xä´H‡Á< Í­‰ –ŠÔKQS™_ñ4iQ=E£©mêOÂüÔ+|Û_zª„´ –Ý“ë¦õׂ”z¡-Ui®9,sÑ­ ˆ ÷ô‚$3ªœ@ÜÔÐÊT/¦Ù±T!€½ésqX3³Ó̯H íuȃ<‚ägÑeHÀÂ6sZWµÝtwÖãX½úÜ*!\ÈìµlËÙØÝS79È~§4Wö©\dÄsCqò¬ï×òüÏî¬2?;k¨i4¼£û?J„#…& ='ßúB2ôåJ#ɽØ^ò¯ÎC· YUž…®]yº­ie|s  kÈÖîQ;„>Ø ¾5Û¤óIÌËéªîl½Xh[æ³Î:±ìó«A:У¾ôRrŸĈ¬Ä¨³¹×£í˜nÁHiœ"—Àe½]sq‚"6õ£{a3á¼=™öw «ºóq J°<ùE¸¼Ë ùÅŒï#Géá©ìéPm@.dØÙMš¯€õÎ: ê‚Ë“½ÇúÖ­¹‹Qêì]MfÍsZ\oDó„Z¿­o7>Pqy:Ñ÷…™+ùa¦ß2“w!h³L­,¥™œA…ÓbÞ¢Ï3ñH<…Ƒ햩/×Bòoe¯^WÚ¡‡sc/é¦^h8œLIõxQàðÅO,‰’p^ <uì¡`½óJ¼bgÒó³ ü:B‡fÿQnGût-Ëå:ðýc‡/u¢3Hxk?ÙñõHœÈTÀ»åH>ZH}¤oBýˆæÿ£ï¹ºÒx¡•fwÙ/zž„±0_Ú¾l˜CŸOsRûÓ?åHðýô£É ÌOÍ÷ú|!}ˆñ5`Ôæ·@nvó¥Õ>ŸMÞè[{é°ÛíÀütÙafð=§Î˱üÜÐsi¾Ð^Ä‹yºñ|Gs²Ö¡©%XTy‹T#ÊL¹rbšªîv€4Åß>ýTÒÎV%uÂwóG"5µô1Å–Jÿú×÷È$Å%ò€¦Àg];òùW~Ô-»v$ Õ¨Ô™a" ø8èû–d^¨iÅ‘ò˜AòƸ.çÁ¡fžfކVÐc4¥Ìí-ý?© /äÒÛ…óÌo1Ÿ%ù©)döË÷ù~ ¹Í˜²§ S‚TÍÌš3âøv#rsù=·rêþïKXW„€ƒÛ¸ýèòýÕ÷OÝ_q'5ß_‰E’PV£I÷âof MЉF.|± ˆš‡ÆKâ!´Ûè´Ãàz„~â%n°¬ëÍÅà¿ÿJG³endstream endobj 52 0 obj 4434 endobj 55 0 obj <> stream xœ¥YÛnÜF}×Wô ehvóî}²e «ÀI¼–‚ °+ŠÓšášCŽy±¤ oûê|JþqOõIŽ2 yȾTÕ©S§jÞ³Àç, ó»Ül}ðþ€«O™ùUnÙóóƒ¯ß¤ôÁùõ~™³T°4ŠØùöÀ;yõìðü¿<õó,Ïðô|uÀÃÈO9;¿9xëýxrúÝ‹—o.<~qÈNêâÇÞÍÇf%;FKÿ}þÍA˜ ߬Ü{öMü˜—Ë0Å–9[†‰zíÇô0 G<ñ“$ÏõúÀúr)ÄSvºÝuí'½ª¶ÕP UÛ°öšìõ!ü<©W ›¦ØJ6´øøì‡®*¹b/ªN–CÛݱ ïò‡?mþ+Ë¥¶Vßn(´=tì‰È”'{¶?Ÿ·>ËlÈ Îó™64ƈïñ™²¨g7Õ°Áí‡dÏÛ±Yõ:ÄßÊ-EïùxMg…Qî')ŸŽQ§\cã ¯`»¢ƒ'°Ž^]†q⇷VHÓ•Dðäˆõ-«z†ý¦=À3œ×³c}é¿}m^½Í/ò€ Ö>U@WÿÓ=ÛÚNèí2 2 ŒAÞÝÍ´¥Þ´œÓŽ;ÞÈò]Õ¬ÙYõ³$6;|¬±í]×EßW¥>ÒPúý…÷ Ï<ÙýÚª Üo4h³è±HcE”~¹­ÉC[í±¸…ìE ÿ\v²Xíe¶ûÒ³Âè)û¡)ÛfèÚºêO\:·Ý¶Ø0Ö¬Ÿü¥Crï´¤¢²h=YD')GÎ"™çxÍFò­wCˆR{Ýê=uÈgü ºd ìOæ‰Ýý$úÒ‹â”§ìåíäérTÙEù/5²”}_ …^w•<èòCUKbðµìÿŠ“B‘"½Ô©ú¼kßæt@œ!¿‘îUÿnî$ƾ¥MïîxŽvî¶öº»ÝЮᜠ°ü¬^·lÙîû(Áe²/âÔ(H§† ÊÉqÛ”c§¨Âø§ÜùmìU~mÀ%+¢«vìJ©½éXìì®)7]ÛX:vµ%K¼Ë7ÞÇ«êKèõsËTÃ4%Œö¸z'QÅÒÀ@s»k; ù …ùÏÅ—öOÒÄ…÷u;Àa(8õ{Q4H†vìÙÉØ(.¿›?rHR…G6wT©ÙkÙm+¼ú ¿Ö 7v ,U‰Šgƒò' ü%}ª²ñd£W¢àÛ¢©vc­líT8 "þ¶¸­¶ãvÙƒ‡WñÅ‘)F妪W´ç¼Þ< νRdgVD Ênûg C†fÀòFÖUÑŸ0åÐçØ“HRE¤WÚ˜ªA†¼èÿZh3‘«ÐÖcoê½õ#” ޏîÚíìǚСl6²ÓÑ]rÛÇþ©¥À+™zƒãMW/½±œn%ü@pncdZ™@%õ²&Ĭ')õ±dýxÕËÁD­'-ÙIdÒÀ®î -:¹Tç‚ÈÒXX.¼üí·N:1º–®JÜ.,ýék†¹ÏÇÿ‹ o.)#˜½¥„Ìnwä+Ÿ^AIÈÏ'+„²âœP£_cEYÊÝÐ+™D÷ÐÚ3-%‰›WtÊ­VßÂki"¬üëÇ.÷£\h˜"!:f,MBïv×I•¬JNݵ#+'ÇnÇz¨vµTÞé>ÕNh Ÿq?žB{ûÕÚÐRZ«ì~Ñ¿“¯ô^–Ã@»6tºtá³S¥…ðóÔúÕƒÊ=Ú  ]ŠA¡Z÷˜eº6(Tp€-Él /YˆŠˆ®‹.€S\ŒÑ RÂGž7E¹§R»©ƒj¯«F*7ßTu͆»"¹‘ÈàõýšV(…°@?4È®»Èù¢Ñ)YfÑ=þµvÅ.$¤ûÏj7–‰p8 R¤f"¯¦ëÃséLÑMªdýÝöª­/ýÃežj M¸M ¯$¾¶d+‘‰d…óL]¹)®àñN¾ÑÓQUð ŸfHµ`Ö_¡ä#ÃÈk§×䬎­[”jžÑŃdß@7¢æÃÅŠŒ~¬å‘~B°¾‚ Áër/ƒÂ0ñóІ\·ˆÀ]àA›¸BÄ!ÓÑ™ÔöºøV‘˜Å`>öyVÏEIìX’ʹ:Ì£:)P;¶c½•bÒŽx.<Š‘d1@ò÷_›`˜0iœˆ=ÖT@ŒÞ1H©Ûö]O0‡¼0œvM ¨“8Êïhàü{D‘ž³8Î ’w¸egvc-{ãQægkíg´H3óÀ¼>eôK°,½CwD.¥Í%ÞzªÒ‰=ÛóØ]µŸPœÚO8ËÕÇ‚][OcBop}ÇjY¨‚c&õ7Œ“ÉøœëTCÐÔ+© Eó:óTËJ(Ö¡ëž{u" ý,pÿéQb}ĨÐÛƒ¸š¨}oTw -×ô.¼´Èä"46ªçÞ2Ž2£––ªuoeG%xÝDžB^¥÷Ø-"{°ÛvÞ°ÇÂ.j!TÙP3Õ” ÓyïÆn‡$éÝÀ­¨!eÓŽk\þZ+7:(Ðð! ½DÛMQz<¶ÅŽÞÒÐ M" Ì£+¼R|¼˜LM•ŽŸ‰AèÇf¤®—>;Ñ9åÇilÕp`ž·T?(Ÿ‹ÙS CùÖ ͶÕ¾ŸÅã:û žÊÄc=i9²Í§òuœášy69›ëÑ1$ª´õÝ |κ_žDŸªð…«ìVÑ$IôZ¡h’r2õºÕ‰FaÚ·$(Æt*ÄYÆ¿ƒÖ¹Þ-²«Óð ôElµÀ¥&6”+>ÍJ ¡ÍȇýÂÖ`hë/ü·D§¾¼ÖõK!Ôœ`ñ÷ÚË‹§®¼üd² ÈÒÏõ–. 0zj[K…ouâ%¬€Šˆ“lz9Ó¹!Í웦 …Â:¾Ó!D¦è´ˆ¹ðÀU iøH¹ÎôQÄo,¾ÀOËl¹¼ï*='D®é„¤$Õ^~P®Ôb"÷“(á6C¸yýŸ­©ö:I{æ> à¿‹|°ŠÓ&:õ€öÉÍTÐǵæ~h.€ª=èªðÉúyÄ*#m¦òáH6ÊuFïë¹è2'»gÍ’˜¯htñ81éŒ×È‚@à©âçæ{µÓ­Z\½iKãê^üØØ MmW©‚kšˆâžueæ·K»ý~Swá馸™æØà¥JAÈ‘ÎÔ+Úê 5Ë+„‡ŠVΟ¼5ÝâÂÅÑœg2›JÖlèQ”ÎPÔíåq-Þ÷ØÑ}‡õ‹™ÆµÒl.kÌ”¶lá½ ÏøQ5q*Æêʲ@*²i#*Ôì¼[iT\Iõ®¦I*EGwj$³L85‰žÀX? ‘#½SGÍu¬A3ÛÚuÕ¶è*À%¡jà:uh¢¼–f”+1ÅóPÍ$L†íæc7îÄ”'[šKÜlZÕÌÝb’VãÉÁ‚Ü~W&´s™›I>è8PÕÌÈ8NÑ;ªÀ5l-Ù59½Õ9Õ·YHVm9Z,ËG‘1G…›«Ó'¦'PžË1$4ºª=¶Î¶„Î4ë>ઓËrÄdÒnv¸uƒ„KÒ*Œt1œúúi¨Å¢)˜^S¦Z., —ÿ™q¨hèš#÷ ùb5—ÃóážRCAŠù¹WÚÁ|¯ùQ2«ü¡—:O«xæp¢©úFÜ¥º“½ÛÂL2 ¯Äj9Z ‡ÀHÀD8xüÞÍØi¯Žfðwì\`'´ö„ß©¢Ðv•šÒ¸G§®qe!¡ç!àš§³’DZÓLê‚õkxB4∣;Aâx9 8úIÓ1%HÂ1µ™ö%—x— åvm;Î(4ñ¶ÂÐ[ ÎâŒæ=Ü:{#M\ ùÐýM¤Œp^™ÍTC}ÝF1 42°Äý6íj °U®*ýU0ñ²‚Ä ç]ÞJîd³¢hx¼ZUz0?ç9["w×ã¶YîeÛ’žYÚø”¤&%]ßéLà:x†öɩ̣»=¼åb*ö&ÝhYAƒà b&Pš©kEI¯4ãöJv‹½ÓAýëD‹ùi¹€Ói:õùà9 žÇÚð™xÇMlŽú¡òNSªˆÔéË(0ý? = 6ÓnŽJßc†i<¯e¡– ‰Ÿ[è˜jþ ä1ê> stream xœ•ZÛ’ÛF’}ﯨ‡AB(ܱzòÈÖØ3²å•Z¡Po„A°Ø„›h\šâ~ƒü)ó{2ëjvBR«» ²òròœ,ü!_Š€þ˜ÿ«ÃM îoþ¸‘ü[aþ«â/·7Ïßfô‹Ûí¾XŠ,Y‹ÛÃ÷êõw‹Ûßodæy‘ãÓÛÍŒb?“âötóÑûðê§_¾ÿáí'ïâÕ¾\ÈÄ;}n6ªtëÿÜþí&*BßÜyq9­»Š2¬UˆU”ÒçŸ1-ì ­vå ^~øAÔÕ õgÕщ¾¤ºÉ ?ÃÐ,ì¿¢ú@F~D…þ€VLxŶ‡¶ÄQµÇ½Zbùºø{«>é=°ÁE+E~@÷a5˜[óÏÍü)A›§|ô”Ú¼˜¯/~ñýi!?ŠÜ+›A`O}U6ì”UXH? ¥XÉíÔ»Þ©º};v•U»QtÏc]=ìÏ^Ç®]ïÕ¡÷ÉŽço Î';·7äÁUÀÓdè»^¾ûÓí?ôe6¾t‰yœŸå!?òv§Äi×Ââc[ÃÈv«=3´í^ðÿb§öG~úã¸oTW®ë}=Ôª‡¡“»Â\’[Â4òÓ<¶þª&…~Ji£’åœ@ð‹X+ñù/’øybjÄjã‹[ú<,ü´0+x'~î ®Ã$ýX6퇜)Ö*¬MÒOÌÂÝRlÌeabBšÉÀ„tòÊdÀ£Pó°ÇyðÅ6öíQu½(½bDɉ4Þþèuj&È„,òkÅ ¬dK*ð£D¯t¢u”<Þ5œÂ®MršÙþîÒt,žMÞÍÍbíI k ŽÓ@ÚEÚ«ýóeῳk5ö/zU¨¢¾Ý'º>M}é ”.Õ WvœÕc¯¦D[" ª’~Õ"¡ºSÝ«¥µ;¤Ç>‹Í‚òÐfX¹L ü4r[Cöžêa'J~€Á¬—E—% ú¡ÞïqáÖ\˜è'Úª‰ ?‹l <ÿgm˜öXêG.†Þy=ÏöÄBCÛ> ÙnŽý>¾9í”ÚÌ’˜šÄž_µ‡çÚy+Ô÷}Wå™ëÎ×h‘å~LOu…#f2Ö|ëʵߵã~_.é„FøFô‡Û;–w)öe·¹È,õîUgæ€ áÙè uÅ&™—Å|QY” 5T¥úËôõ}£6nµ¯uSˆ0Ãø*DzP:;@ ÃL—¥ÚŒå†õáXVlõò0üÉ7eÆÍÞ÷߯ƒ§M6u+:¾&‘H9Û<¸VéIÒ/Ò¢pȃ;þT¡ÙŽ E—Lcù•E¸ãÔµ¥Ìlw*Q³J4β¯V(]õohæ_/Pàm‘Zsx®¹U Ââ²JÈAêMꌃÉÁóÆ8K}¥ƒ_è_\í䲞(ÂÌ;íÕæžÁ`ó®îú'B.jîÍâsG=v_VÊ”F D'C\ixß× Ô¡'ÁÐÔËVu”¥óõÏ+´·º¹ç2B1©†í¦ž·ÁbÖà'îäd\¥ 8Qž£Ç~)Îí(¨ŒÖª§äe3c?#rµ†ØAÆv¼hId£ÑÃÄ¢KžðÑÛtNÓUdR¸®b¢Ì ÷”S9=%öejÃöÑÃKñèV)»Z gæäì, ‚À€½Ll oêÚò[Q¡7b}M+ªlPcû½‰˜ô¹­@"*«)rÿp/7E,¥«»±Ÿv!ý,žµNãýʽv7y5{ÊHçZ£à5Îåþü¿J”š<¹Æ“„~ì Ø«Úãù’]…’ú„ ó(e¹œÁu¤e™yÂf ï À¦îT5´ÝYsÞJ“¢C»©W¼‰Góš°2ŠuåF}ÁÇ%!öýâ Q¶ú*úÑ:¦&ÁkðÀ?‰Ä# Çä~|¼m»×¶Å;èkΨP|%uÏ!žy-¤ejLQýQU5RáÊw1bYPºØ¿å:Ú´Í3“1“9Jš‰ö3ÜAû#»gEH{/2?É&çåAª;?aRGLë ÿQȳâþ³n3¡~:Æä¡¦ÉÜû Ý·AgÊêa"Ƀ8ópÿ®ìAö›¡C…µW7Í}tÊ CàÚÁu+놙•±œåvèVCè¹’ê0ûìÙ,%˜´{Õ]pòÂêøÔ9Sô¾L–:ô–ˆBÈ0¤-U\Ї«ÝÈ$ñ‘VήH×í#ìšÂ˜Í\OÏ5ý v—];w ä*(µ{îuÇ®,³T9vW4þË’ô›$u†(’¯ŸŽmO}’È’¶,×—³–®­=ÊíÃê2qG2³êÃ`:$bÝ6š{ÙëÀYpÒW”MÓ6ênÁ¬&¢Ú+\ì‚,×~ÿi«#–O‹ ʪKüÐvn@ߺè‚î7´áf1c¸D|´;«º{›±"4Tl†?nZÝ«ËFKHL‹%½³y*”LyÖúý—á:Ä…SÓY®çXK¬ ™Þ’¡üåv@ÆXDÑ»Ô-$ò@\C"Ä ¨±¨®Þ¨$“N¶y¦iÒ* ˆé;µûÿÔrZÊ4ÃHø$º±aýkž »º+jæŸh[Ÿ“f"òݾo—äCÂv­r”øç?±æœùÔ̓h%ˆMO3ˆªìUÿÂ7s´ñÂRAÉ”&áö%=ÓåfòŽâ¯ãÛŸë?z××?’¤¯7ÊàÖÕÀÄ¥D³EÀ¥çj¨ž˾?mL‚êfýš)¬Òw³ÛAKÊ{Å2 ?÷ƒ‚”¹óöõÃâIú0Õ0e(-n©¿ÎÉIž'3ЬƒV?Žë¥Ðá9O*ýÔ <­(rбþÅ= Å»ò‚=£É¤‘·÷XÎÀ@^€ASîîè Ÿ›zPH…­ËGRRu3˜©àî•ç`ñ$™ ¦Ã=Úú ÓÍLõ¢t:òÂ?‚R”¿ŽF‹|1~[jª žaˆ]ª,`43õŒœJQvyLÈM×ñ†Bj—Žœ:’QƒÅÞt¡‚&¤„™èÇGU¥õYÂs/³œäÙ\øf~à\ùÑÖ ÎÕ"BQÏÌ@˜¦>¤ý¡ûÜÞ—YãˆSJqø}­¶4Cý±o,Á熎´„s¶’96øçö )B“µÎ$¸b´¾Ñ¢è²ñÄC%teªÍý¥e$Ô¤Øeæìh` ·rœé~„ÀfG/g™SFÞyÈ„Ný1B(TÔU‰"Qqªõ.[g V}‹ÐyAˆÜO³ ôSÓÿÉT=`u³a•¥í¼ÖÎÕáÅà ‚ì©ÆY/bb^?Û²ŸB §ŽUÌ7É3×R6‰BhPKt],Îg³  :<Éô/Ò…F—Èç^ýè:„¼ Â|F•Óˆ7?6c`§ ‹á|´e0ãè”áP>SrÿغÙÝéz0.–Oˆò¯¦ŽÒØÑ-Åpѳȱq} Ô6ÍÉurÀÓvðz늘1âŠj .R]yêÊÀ²™#Ö³–Œ˜M4Ú’>åtFúâÌ>’"Vk\0X™D÷6`AWÊ`IÝÙß‚^ Z˜œ\sÛysé¼D?ó:¯ýÛyòÂ5íØH¿šÙÌ€j£–Z¢£«Þ‚V¡õdùn`¤g 'ò)Œp5¼o¤L,®´÷Ëóý =û¸/’DØéØà›a¤ñ„Mjš¼V»4#ÖÒÒÜ7µÅ÷MýI¨ð‚Æß¡=RQ~@·”|¾arÃC¹¶æ&™Z؉àrW^o˜Ò¬ÊM=óðG£gi®^X—N­6åÜY8ã5fͦ&+QA–Ã"ÿäÛ :ÊÂé“I<‚…ÓCXß3t ’h®,œŽê'†§sŠ…1‘*m4uAt"É'Φ¹ÈÐRšñ#ÙhXjÂuAL‡ÒM@Nõ"‚,‰¥×|¸€/éôó“Î'ÃõQÕ©7}à=Mÿgj¡(LÕ °·†RÙvíAüünõý›wĪVI;¡o¡‘Ö©ÿÂZ7·PoÑë-E0¯ ˜hʃ"ë”ï/ÅozÛ·[û õ)u€?MSîgH,a•ãО••쬅ÒbâŸ(aÍfŸŒ3RƸ¨`°ªÔ\Z›„$Ççõþ@­êÞhäXþ_v¤9Œã ¨ˆ@ÚžÁͬ¬ÖÀÒI¨ß†fü#χÙAã ÞSLÇqûúâáìôà[½“iºÚø‚ÏÝб¥;!$05ÛýÀç™Fñ Ÿ…pÊÊDèíl¼¶.7:<‰~ ö^ 'º:uÞs ÒbÒœqÏ xƒ§öú0E?ì ý­ª;¡ óÌŸWR#ïNTå¬[µëßÏ¢vñ&:b9eÊŒ.Ù‘ ìêöSS[Ò´ÅfE¨Y!¤G¦î$k3÷Lè:¢ÕÈ—·3(¹8[€I6Ÿ(wçÍtúE¬Åó×$ÀP£ÌÉõ†™£—„_Ýy±(pûpã%î£4OZ‘6‚ˆúj¤~tI½Ÿ“fâ³’ð:?`k¯ŽF(>¡£òàh—Ó}|œÌfºQ`Ï$Kžænôy‰®ÜÌi‚) ÛÝܯròk=ìëÞ’)(Db…jcÔœ9"†G·Ò­=À4Ï!~`#pÁCGý:áîy …µÇÞ–ñ¯ça‡<<Ò«9|T3îÍñiˆÐÅ”ô…Fu{„zy‹þ 1¬’€bkeOjKn°¼EîÓLpÁðÐJT×µ¢Y½Þd¨¥ ½©ÈêM9”nôRÓ™»Yì2î¬K-ê±I@/‰&@Ènè]OðŠŸ;Và•á~ô‰Yä…>°¥ã,šÏ3c££KjéáÚ1ŸÍ+€gCWWºoÙk/_âqioNÍ ç÷-Y“úµëw¢@luÖþåýœEaËï¯ï®òhŽL|ð•fIr>>D[V?éœuIB‡z5'ôyÂ@„þk¡¡Ú!…–tSíø`ͼ—Á²}®¤TƒÊ2ê…²†¶ âPïÏæüÔbì#I§ ‹>Ùø‚Æ&<'Å•î…÷Î×GÏ.~„KØ^²éµjjÆÃZŸiÍ­¡·7–©4-bè-é{š%m2ð@é ²/‘&JPñ'0 &¡ŸÍ¦ A’hëh(©)¢™¿äà=Só–ÐV¿kgNÞÖ‹ÐŒ„Æû^PöQ2ƒÊð6ÀQx£_xÒD84!ŠŒ®ƒdîç“EîÜÔH?(º ,ýòÀÔ°F3¢Ôº3OÑ<ÝIôp?ÅDîìS îüÞ-›ÆÉia&ýÍ–å4êð { ŘéMšûÉô„ËwïÜ{m^‹Ô¬+.Wpó®J¼§©dSYâ£ç„ú}¢žCMœ¦Úµæ™ÜÆÂLò+UÆø‹Ñ«”Ó¤=òþsþލ{2þãS5'S4-£¢ÌýƒfV„6~úA¡\ÐY¥€'#~Ò·7ÿ…?ÿ‰j¸~endstream endobj 60 0 obj 4602 endobj 63 0 obj <> stream xœZÛŽãÆ}Ÿ¯ ƦâM6ï^À€³ñ"AbOœ‡™n‰-‰YŠ”y­ò ›OÉ?æTWw“Ò®/°á]‹Íî꺜:UÅŸ½0ˆ¼þ1nw¡·¿ûù.Ò¿zæíÑûããÝ—ßçôÃãîŽG^.¼@C²•Íå?u»÷ð¦WÞ®ÛNÔqêë£ìkìßµÐò^kÅDÐuE¯#Á;'¥Þy˜6ƒ½nçY œ³4©ÑÓ›ŽUX–ZUx= …yÖ«Y‡!”b<ùïåñÔ¨ï¿pïŠÜ*¢ê *™­W§®IVåÖ¼?õjp×:z§õmO„ŠÍÁêÊxE†%æàºõ¾þÚÛd¿Y‰ÐŸvZk½2?ÑŽdµM;}ñDÄA–Ï*9kV“úMOö½¼ÐÚ”nïÒ,HãÜì³DqP©“ˆœûlÔVÂLZ#) -’¥FÚÏÍesÞ<E ë«ãÁ˜GU§©Ý-ÈT$«|ñæ@„v ݇׌—“òêv×õGÉ.Euÿõ×÷$â wÊ;×ãÁ;Ê–­žçÚ!¢<‡–­K\ºù^bÅT=«Ç'p³Ùå’œƒ^Û“Ãü²iX„ó W Ã<ö»©©¼FI"c×iŒ7ÐVp‡0 òКñ²[ú¤5¿Ë?uâçÊÁˆä½Ìj»‚s…Jà=ÂŒ´,Žƒ(J\”'v…¬«ãç&X’B YE™Yª+§u¾C»z5ÔûVÄ1öQä·{FÌ$Bà¦N¥¬Îa:é ‚A½ŽÔï5²ÝOrZ‹å)9\LÔãà‹x×9àDy:õÜS=¸énj€#øµ¹¬²ÔgècÄûŽïó/Š—€Gáì]×5Øs¡]{ÆI §ókB¿¶®Ôºûnj·£FÜ Hè*¯•÷Z%È„[l”¹τҠÕì;Æ@Èp¬‡É¢Ëx˜†‡¥ —~j”Žziäe¶b,ð‘Ñ'ÙL aZT8R÷çn%RNÐgÅdxfÝ ÝK_l˜&E#¢ÎœÖ?xãÒ•‘)£[%Ô2‰DzÇ ùéØAûÈ$u7 ½Èðàºh8j,;(íÂ"-‚Bˆy[¶à ‘dÍ™·ð'-ËV-ìmˆUk2Ð á %³³9s,rhÊꣲÀ•PA–&,ÖºË#Ï”ÂÕ,L½À!Óµç_ñBKâ_‰ºAÂ)ÁÌQÉî1 1dH’q!1(ïÿÛq~²‰Üá ¸Ó'¨ðØ N€<®ù›†;æ¶éˆ»Ûõ‰@Rw!ìgõxï÷™"%oÁ¡Æ~ÚŽL  Úÿ¿’Óg‘ÎÙ1f{ߨ+p:l²ƒ*âVaŽŒåÿ@°äö挳Aå2Œ—fIýÌ›‹R&¥pÛ9È%Øëâ*µyÿÉ¿rÅΞ_¤&—n‚†‘=(J‹$»©¸oÐ"y?4J§ Cò$!Å$šz-jЄÀÙ¾ÓÕ€š9oXó<ÌΞƒk†¡2ƒH?O´7X”bw\kþ×:(ø{š- ®—‰(Õ°wo“MÈ¢ÅE +Ã^."'^DN‡tÕ˜a^ÿrϹ§òãž]è>`lRSzFA™Ù¾Y´"pŸÈâ'ÉÏÙÆº†ÞŽ+ 3Ó¡¼ ’8vNøã7Kx <YßýãÛûe)q“mrÔ'±œ0 ,$ý8ï\è8½ÙøìL—)ª ¡5ìÀ-¸ÃTßÑ3‰ <‚:gF?ÔÇÁÞ\8{ ¡©k `šyÁÃý’<†Q”ÏR051«…‰öFö]’ïž» пXô³²±Nkå6ûæAÎ,¿4Koõ!²Äi:3´L+Ä”ŒŸTɸxºTJö{ö Ͼuèš[ foÍ_8LÀûgßp&l)Êâ†q2h¥YÌü*M®izXDZ`ß¹õrHFÙ Zy“öÒQé ù—|Öœ®[&õ`ì˜Ï5‡ï‰zk\ƒR£¹°,üiÿ`3¾A²4ÁÕn»TUµ”¾6 æ&‘¾ÔHø©³ßÓ°Èãr©(í>¦)I½€›¾rRRÊ®7Ë”ðDíXP0÷wãœÖt?aFÇ_ÞÁ¿ÈeÈòÂ5!(¹¨ñ¬¨  †©PÙ°xá=7ó>ƒnj¬5’ˆe俽óJ7²ãÔ·M!PŽ¡æÒ‚ue`ÉÂß ãoä;{ņ™³:hð8™&âFû8b]„.Œ ã`SUÝ«í¨)7ù•„Š ˆé´‹Ùû³o(ÎôªIgþJéývbK¸ÊÚ´÷Ù¢Õ˜–lÕ=^}^-š<¬ ´×4θl[€m;ÛJ¶LXËDKÛ6°me†Â^®l›Ìh±£ª”TáRÔAx&ZÄå źwV¶G7Œ ß«GêûôX.ð—îÕá4ÚìÔR»Ž(’EgÙŠÖã©—¨‚·œÆ£<€Û[žÀ® ÊŒ`$#œTN“ p¯G9 à6&Z•jiÖP#—Q[ϯŒi«"°$ÝAb¼€È£lƒO¦`,ˆ wG”enÀpÀû©¦£"¼˜jÒ²ìÀ Ão,õƒ =é ¥j”dÐÛ «®û®ŽïÆ3˘˜Š¹×+luxo¹MP¸âòæ$Ÿ”Xu­kõ “èÂÒVšþ8-+[$7¿°ûï­p•©ëb÷êÁ8;1¾ò }m!ʶid«4[#Œ ¬Ž2×€Ðuco”–(í­â¹Ô‡÷ðƒýaFÛ²$ãXA•g#åÌÕvFñ¸¬AÈŒ$à:sv4âÀ¢98Q>kæ}·Š¡,¦~?- Tì†vÓ0ÉfɶɱŽõ gœ #äßÒ‘PwæoŸ‡vfóöJ¸^[ ¶§%›G^sU³|•¨J4wŠQ×ÐU¢2E]sZÜ%§¦‚[æ*­r.Ø2^„âÚòù"HÄÌGÓM ³E7©Ì͈åýøìs*PTë齞WŸÅéŒG·é¨æë\"È!Äh„ÃeÞ\‹ký=8ËÆ°|Xij <ÌÐ-gæ*õh¦¾’iæ’Nv"<7 j·Ü¥×DÒþïÔ²ÃҽߟpUÑˈg†øö¤ßšâ S™ˆiºîÝ ›õv®?lg/}×jNcMç× ·+3Tbܯ'ZY”®më $nÏH„àÏŠ°ühK–„ ±ÓZ.ºP +¹zÕeMC70èrLl¹WX~:g­©£\ þGvE¨Ý*·Ã¹ç-)€Â)Õ Lž A¥;Z£¸îó¹§PÔÎw”ðÝ÷3ôPûàÁ{\ņõÝ¿©­Øõz^öjñ‚驨'×Qr¨Mcmº­+Õ‹oOnÒäeeB„AJÃ5äu'Wù=…‡i,?ýN¯&5ü‚•äØYá› îıƼ¢Ò3À8%nŠH§A­1Ü~]‘„9£17ï 44\ØL-}>]÷MxŽ’èѧy{¥\׌OæÄàú£ ¾_ c§{”ûÆeMéx¯˜w!óæ 'íœú$Ö/åÒ×ã2YllZá³~ּРzéXZE˜äàf­jø!F5»õ¡¨p6Ÿé+MEPd…lVÊŒ‘´Ž»ËÄ)!6).thëŸ'X†\@»<{uÝÝFeÐH3s°Ce¯Þ1Óuu8÷-H™g[šã¯=¢ëü™ÙÀ®ïŽðp”Ƈ)9èO»®HƒÍz¡n…%.,*\à°xÀÞ’S¡6;𤱛í»ó‡)°Æ‡FÑ@å+jE¶Óq£ ß y"JßJçÙ¶ÒüõGorm%¿kÊA<ƒ×¡Ë# 1ˆbé}µíšéØòQ7:q&¥ÏÃ’™µäæc¿‘J†‘p æ`NøkÈŸp3_”2W„Ò5œ-=LK ÙÛæpöjýõÝÔRÛÅXéûñ(^?4Üî=æ­‚FG©›-EÖ° XªªÇ®·µ½˜b¡/†»öÛ"Ò,×Ç|E`7®øÔÍ×K¿vÅ믗JÓéÑ—m¯¯GµBMYާÆÚë~´‘nû ϾmŒ¸O@)µ× óæKZ'¿LÖ¢, b"&±Æú>!RŒýœÑàß_¦Ö¡ˆVkü7L¡Â(Ñêûöñîïøçÿ.»ñ&endstream endobj 64 0 obj 4654 endobj 67 0 obj <> stream xœXÛrÜ6}Ÿ¯@åÅÔ–"^í—uÖvÅ)ÇÚ•ÆåÚ²÷"1l8ä„¥L¾ÁùçíÆ…Ù®lÉeH Ý}úôÁüFbÊHŒ?þw}ÜÄä~óÛ†Ù§ÄÿªäÇÝæê&Ç»ýÆ-f$ç$O²;n¢7ï^^ìþ»a9-‹²€·»fÃDBsFv›OÑÇ7oß¿z}ó9bŸ/È›¶º`iôø¥kä@pëv?oDɩ߹ZŽv·"[%ÙŠÌZ¦1Kœá·{rîÇgiLã¸,¢A’¶ïUÝ=© é¤3MS\_oJAy‘–ÞËc¶c|ÁRÊráÝŠúF^yÁ'M¢ß«£ê$1I¾´R“}?=ÖRª¡ª4µŽX^Ò,Ͻý·æ:@ï´€ä$þ­V³w(@ÁCÚ 8ÁE]=ÈFݵg2vJÃzr¨l>`CêÊB<Œ ¿ñA=ÏhV ïm÷'P©4cdË8>i‘ØJE_W!ƪÅÖ2‹CÂζȜ2V†gÕù9ºÅ‚Š„£KÁi&æ]f> £Œ3ÿrë´ï[Mêª{¶¶’Ó8áÜ[1‡o[‰ª®i¥+Ç|xCª¶¥ö´)OýÚ÷Ò=¢ ‹ƒáÇk V~ØKÙ PÔïìȨñO›Ì-/0ÙÅ"gð_u€€®jIS™Š4²UGé0ÎbAËDL!§¹Ý³,Õ}ÛwDéµ/¢O²V`mQÞYyÔÏÉ/U}}‹ëáÁ-Á•? dI¤ÖY£Y›~8-O`>ºLg¢(Oç!!—×m’§º¦÷MžŠ˜…ôé«_n·¯ç”ªFvFíϤÔ ¯,áT‹P@l»tšÇ) kBÒ`*.‰=Èh!¦ÿÕÉTW÷V½Î´gG(-gs1SÅoE*Òxøº÷¹ÆyP5llÕ¯.³1> 'B ç”ÿ˜ƒL #Ó‹ë÷Ï/-«Ó©Uueœ—8¦Îòö÷4çBΧٞ[âž·•Š:j,‰e-‡´EHÐ%d1ÎC8-yfcùpóV_}¸y§)y£|OᎲ¤ù å„çþu;6ȸúTÕ–:š+`HSÝiÒô®«ÑxîšRFDdê &ÙÔÕxôÓÐßµ€xK¸Z)0øD-n„¬ì 5ä™y Êã<4xèÇûézƒé©ŒCDVØD8f‚ìA$– Žêþ`žps§‹éÄ¿‹Êd4Ÿf¢³ÂzTæ€õ9Z¦Øb92 Ö-l)Ü ²£¦æ%ðœxÒA¤T­úC6—D÷Üz‹sȽtkõx:õƒÉXãZ»É,ë霜 {öÝß`¦vä^vr¨ÚK̺‚¼ þ+èÃãÉh„“D)BL´€È€ÆG4ÿÂöì»nÖÿAm‰IÇ]ö 8,<áôI&p/ ÁiœÏcƒ תUGî$±=É à’°ÆõÖO9 ˜tîqQÄÓîÇ‹ëÀS”媹Ĺ–ЄʜÉÃØbÝ©J"!|‹ 5-£1C¥]ñ9Ð"‹‹û€e ÓЋ`ïEhÇØy¥Õæ†6ª& ®ñ“åa÷æìÄ•k6—ɬ¤“(4÷Ë’ó‰Î`ä¹Ê%L™rVN.—ñ×yÎôÂRæŽÝ¨“„ÍäÉÍÜè¼ýNº<ãz ¹ÑõÅk$”{wg?x¦“o Ô¸O‡Â7i ú0@/ί@Ú@/¬ç ¢ÿ¸µtò[JcÅ‚ü£K½`”2eQ¢þ(-9¢ò óÒ[Hs8‚±™aa!ËYLKлgOz°7-g˜Æ®£¾‡J/SBDWg^¦áŸFi§0¸!ÚTˆ´ÉžtuV›!â`µô‚ €7mt34è#žB …´9Œœ€sO¹Ò– ˜§ú$µ…‡¾"¨*s‘/–¿ƒ‚já,U{ÖʵÁ §ÐÒôp)ïN= Cx_eÆ]L˜Ëb>EâPkT R96Lb¼ì.µ7s`‚Ü@¦†/¸²p‚“¬Â;/ñhRN×]SÅ9¨Í yÑ¿[k¹!\ÕØ<FÐŒPŠƒlOv-ÝÒSkeÎoÇ&1WÜ0Ý­ÙŸ;——ìëþax IÄBš±"ÏVÑÙ‰i«6Oˆ&Àú €°_+°SJG-re¨3‚ÉÂöê¦$` i·G Gà–æè%º}ýš¼|w{í–…ï.fÉKü—·ÒÉäÀ®) {”w0M%^(Æœôó««æñ eësÄŠœ†®ùѺ?^ý¹ørîɜ£z“ÁÝ't<ý÷ò*Pf“vïG¢Až¶@s-(%íŽæ‚€”º(ÊœÂ&l±üé²^$Ž®C]ÿôD–ø Ô#På.^’û§D/f•>T ÖÉÅLxAgñ•ÎrI="ú~º¶ß̰´Œ>î.ì×CI]Û¼ÌEÉPÓMÞœ¾XF µ·_:\d.ý–•.à~;x$·§aRW®»0²ëuÐ0ÿ2`½†xó¼¤Þ\šXeµ'OaX°@_~XÊ9ž‰ lv?]߬Ý@çç"›ØåSô @Vb2\<ò’’.äsòò÷)A©ÿ „Ä&;A@`è¯î›lº?³,³Wućïa'SŒ"9²«õÏcGxÌÙÅþSšF,µ^^ï6ÿ‚Ÿÿ}sjiendstream endobj 68 0 obj 2272 endobj 4 0 obj <> /Contents 5 0 R >> endobj 14 0 obj <> /Contents 15 0 R >> endobj 18 0 obj <> /Contents 19 0 R >> endobj 22 0 obj <> /Contents 23 0 R >> endobj 26 0 obj <> /Contents 27 0 R >> endobj 30 0 obj <> /Contents 31 0 R >> endobj 34 0 obj <> /Contents 35 0 R >> endobj 38 0 obj <> /Contents 39 0 R >> endobj 42 0 obj <> /Contents 43 0 R >> endobj 46 0 obj <> /Contents 47 0 R >> endobj 50 0 obj <> /Contents 51 0 R >> endobj 54 0 obj <> /Contents 55 0 R >> endobj 58 0 obj <> /Contents 59 0 R >> endobj 62 0 obj <> /Contents 63 0 R >> endobj 66 0 obj <> /Contents 67 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 14 0 R 18 0 R 22 0 R 26 0 R 30 0 R 34 0 R 38 0 R 42 0 R 46 0 R 50 0 R 54 0 R 58 0 R 62 0 R 66 0 R ] /Count 15 >> endobj 1 0 obj <> endobj 13 0 obj <> endobj 17 0 obj <> endobj 21 0 obj <> endobj 25 0 obj <> endobj 29 0 obj <> endobj 33 0 obj <> endobj 37 0 obj <> endobj 41 0 obj <> endobj 45 0 obj <> endobj 49 0 obj <> endobj 53 0 obj <> endobj 57 0 obj <> endobj 61 0 obj <> endobj 65 0 obj <> endobj 69 0 obj <> endobj 11 0 obj <> endobj 73 0 obj <> endobj 9 0 obj <> endobj 74 0 obj <> endobj 7 0 obj <> endobj 75 0 obj <> endobj 12 0 obj <> endobj 70 0 obj <>stream xœxgtS×¶îFÛ;„jGX‚\mrJè=@½8€© ãÞä"[’%Ùê}©Kn’l¹wŒ±‡ŽBï5'!! ÉÉɹ)—dmgùÜ{—HÞ;çÏû󆇯䭵5çüæWÄ"†#X,Ö¨é‚äüY f¥'†Þ˜ÁLd1¯cþ# ME‰¿óßg3ü‘F¼:AÁÐã`ç(K g±ÞŠŽ-¶sÛ®7g̘¹*'W*LOM+˜4î¼…“¤“þüϤÕÉùé©Ù“¦à'â䬜\ArvÁætA‚(Ò¶ÁÁìIÜÿßßú×aÿÇñÖŠìÝ9«r×׿¯+X/K&l”&nJÚœ“²%5m[úö;³»ði‹&-Y6uï ëÌý³fÏ!ˆ¿1ÄRb ñ±•˜Bl'¦;ˆiÄNâM"–ØEì&V{ˆUÄ,"ŽXMÌ&ÖsˆµÄ\b1XOl ÑÄBb±˜ØDl&–㈂CŒ'X˜HPÄ;ÄHB@Œ"Þ#Fcˆ±Ä< b8‘B@Vëù°¸aÿf{6ă>œË¡röhƤéK2äéØ}ßòרÈN&¾ÄÙ¹N©’J£s{=Žª’Ãt?L`G6;«5:së’>ظ-xƒf›l±*‘q¡œ'?m)× Ð[ô™6ý¾OöÁùÞšc7.~{úT' |^•T©ÏÐfÑÐRv¤S±Ë¤POH®·¯~w‹ÿ¢df0È|}ð5J’“'õe:Pze±MFos·À©êC”ó@½ß{ÞMùQ@>`ð©«öÿŠü\Y¡L"/çKò%•Z¥QïÝ.È” %2Mž÷ þWæ­÷¹ý~΀˯£¥n©CŠx [mغ¦Á¾Æ£q /N†¥\ø.Œ=3ÐRÛ[Áà SU3³«YO`Ó0øˆÙĉIªÑ¡pðµðBì³kWšø×®v?¨Ï·ö/æ+Ŝަ”m+2§}M§Ä& ãµ/ëðù{Í_¼MéïiîÔèÁ9Òã̇Y×àð°ÁIL2§îe‹I­\­— PÙÄÎ¥‰® @¡ ´íCùh$gýòiï¯ßвŠy ¶ – ûà>_þŽzôWú£“—›®oÁé%ˆ B%T1zY̘oÂ.0S9µÖkPä< LCt*â,–,/Ú¨Þ_¬Œ·à^ô…ï“yj*‚èzE¥±Pp œ ߆ è[½7séVºù'«Ój€g7ÛL| ‰f‹ØÐË6Wåm`]öâøMcö v*Gâ«9ÔǷܧo œ€ ›Û¡ˆQXŠ,2ºÚŒ÷ƒ‡á89È‚£ÆŸïŽžxxèBck¸ÃèT{dCP-þʶ–Â꜂ܢÜ<:!>q«<±8•{ L¶• y¥’' ¯q8¬@Õ”«¥ÅÈ×ÑËÐqöpÿ×Í Õm“Wõez ŠŒB]þ‹º¥1:ý6-ƒÓ¾Õ.--Àk+s×]‚ùÜNs¥n‹×èÓº¸H¹Y©Ï ¸ BêüpžÉ‚Þ1óp}®`…ë(àÁw;è€Á¢¦-`¶h«Í\\¤"(­ffÖ# ëî‰Q‘ÖÃp G‚°ý¤7àp”‚RPi â­ÎÒÕúL‰O.ž{pDÜ»o€Nî“·‚&ª½:Øq¦%åݾŸŒ|5iv1©)Ö‹€hl…NüI°Ø&›¸b_üúÌêøžô‘Ý4MídØ.8ú½œ?z0EÚÉ bÃÂwNç9dù2u.à©1øEž}þýž þÔàÏ]×¼¦o/}z÷Ýܧà+p§êaïIà \ð•]u`V¨’‡ŸÕP®s˜H'¯¯6j”J‘(Yù!>ˆ³òŒ‚cNÂWNï»Ôx \çs[öû…n‘ó@¥‰;¶ªNÂßÛXð$³œó6Ùô‹ÕðÏe¶ëõ&‹VÏOÚ³iw¦F¨Õé X€Ùj¢î‘«P“Yc1š´;°[íô3ø?&ÛÖâý¯8¼Û@‰ÁiÆCÑ!_“ž‚þÂ-\¡ÏR*¥RÚqûì9¸†óˆ(ZDT䯬JYK_MÕ?nbØ" 2oaA|ùtX5f¯R¼U¥xJdsJ×”¢©`3•mÕ{êŸý §ü¿ãTÃÐEµå5 Šb¹KY)ç—+Z û¢Ñ°U+²2¹:øšþŒâžäg`ÓÐY´&¹q“2Ãð‚’ƒÌâ Þ æ‡¢"oúñ-ƒÖ‹ËìóÊ2èUÇ,Ç®-ɦõâï¨?|ÓYìh9û5œËmFwl¹6“ð< ÄÛx§Ëá„ÿ—܇cÁªUT#âo¥pjüÅ|‘K” >=E¡·2ásn)ƘÁdÖøðý¦[ªçª›¼È¹WTf·r"F›Ia–T]¦ÁTf•ùÅÈNî 2³j"Oàî»Q‘Ç™$8Œ“““™©ÒhO«w¹ƒ=py|Ÿ¶—Xm6¯ÎÎݬ3™T{µÙÕñX9xhŠF Öt%\¹ÕÛÇ~E‹—šµ@HEf—)›ºëªžÝ磷áÎ!sM>HoíF#Ö­ "çæ§Ë²'¦ŠšN\èüéØeº{àDÛÑ·oQ ÀgXÌÆÑj z²@ T+A1ДëšL¥Àf± V¾ã:z+ xM^C™Îmö*Xá«®‘ùò¤¤NZC«ÎßP1!€Lí&±Þ €Áì(â)q[K°ýqi*bšÑîRô’XP(Už¨íj—­¶k%).’äUÉ[[˼OÑí5-GÏ· ‘Üò]åEm  4Ô |ó¢‹µÌØ“,†ûE6Źhvš€hÌ*]YoÖYðƒ‹^2³áýØD,ƒ+áü[q§Ö¯Ù•€†­æŸ†1ž¦ãp…ÁÉÝ­É6¬ÔP0 UsŽ5dÄnØ3)f’/Æ& «¨´öbËß{îÓÇïú›æ,8Ìü |jˆääÿs¿Wø\'q¥­ÊÍ< â¥Éô µ\èið8ª]Õ4ÃÄüIx(!Èü>v|w˜yƒSf÷XKÁQP%îl\qe€d ×É‹ sR r” ±H¥UàýÔÛUž¢2µS (‘L&Ê«–¶\ÁÎâM¸²èpLÓp’jÖ äE"¹GTð«Tn žmbê{‹Ð_$â}½.)”‘4[LÀ´–}¬Ú`Q˜ŠÍ/àq˜¡«Y-_Bõ0øË¯œ[’Dq€Ú–Þs狎o. ÐÍ-ݕ݀ª­Ð* fƒQCëf~zy_ïŒþÒEFþŽ¢g+–,(–“ßð[úá\|Üέ‰ï½½¯ëJ+à¯âWTmÃN<òW8™Èé¬Êß—ªŒ/L§E Y¢t@%‹šú¾íÿô*ýïáøècû£š&‡Âñz¥òE8ö””ú/ÎÐÍßUÝõTwncRôêh4e6Ždvœ1ÅIú­˜ ¬µÖJU(_c»“m1‹ âÐVNòâˆÜ g—êþäÌã—:pD.W*ŒXÙåô”¨ˆÃæQÉ‹,Ï È›Nu4>½øgDþ[‚±}ÅÏ9`— Ï̆fîÃ@{Åá¶öæÊ#à8õÝŠÓh¡œìÑ;-%:Á¥ÄUiÈ×ý)#[°Œh0$LþðM½C¢ÄVRÒy&s¯àô §‘¨Œù# ÜݨϦ¼ÿæ»Ñ8©ÖêÒ!oÜÇ|d¼…ä3ôZµZ&+Rc­ÕjÝž»ß]I;+­6¶-ü+xßd›\XhJ2ážœ³xM8¯hM2}á^´†+Ñg •â—´ônyÒÏ3qr%¢¬Ì*qsCmmSsACnh&Òf¨=”T¢¾‚ãžFE.aÒ˜4N7NÊd±XcPÚÅ*ò¡WœáÌšøúеoîôe_ü€v…B¿Ì'÷húâÊó@<µ|ÇÖomºýèl^¾Ä–Žò1_¹kKK‚ØÎùŒ š²F}+†áO¿„äUQ×ÜoéyÏ4Xö.÷¹~¤E‘_ͯz2lë_hwù¾ƒ58*çšÉƒhv¥ñ,$Úp¦™‡Þª—ÇæË7°hôúù6Ð ÊpÓCš1pÏ“wÚ„Ûqú4ËèNŸ˜ÇŽ2¿Y?6èú“›Ï0’@ž7u/z_ÇźðÁ:4 PK¶õÝîh‚Ä}裃7ý7=Ô‹xp]_J”Jlie±hW€XŠMà 5óÙZÌ€QŸß†Óñ?‡]]!~¾„ùO5È:ú0 Â1œè%Z­Ó¢ÁUæ±—;+i«§|+e ‡3˜!Œ'ÿñ‚z™#-øCõ&5Ž—:^J °íÌ¡¦®†²Ý‹ebŸ‰€¿=„‹1/\ƒ·Éh0Œz™D£²XDùj]1FŽÑYêp\uØ`8¬N›¸y‡…‰®(Ÿ—™°w-Öð¨â<¨¢Ô¥o^³MžÃ€É&ÛN•ظ8ôcÔ œ2¼8e8tØÅ(ó礡qxãDïåŠÝÔ}ò#8ß×uèLÿ—Ÿ?¨r·F® ‰è5Z›m,VÄQ¡µœ<}úÖɧŽ5ªÔ«ÁæCmÐ[‘Ld’5^KA…¼¡ïXû½³|§Ïëž48ørõ;?4¬Mròœ¡T‡Ã›LWPœ‹b††s™)'p;tW”Ÿsâiäáæ;λ–‹–£Ÿ0Ó_\bã#eÞOB¿o©äáíFì‰5e*GaÙœKCÜ* ™8¶“<5Ç’ðóiãéoWYè'*]Ó`x«í1¼ø8 þmp ËçLTˆ”ˆ{eÁ½=¾Öú§{à2ß àü-ßOçës8g[ö¿&$¢¥Û&ÓÉÒ÷*6óÔ¿†{Î|Gw^éj=²§&àäàÛ|22Nâ­õÚ}Þ&Úæ¶:í%ðuÆÏÅ ïNÊa¶›@ŽAµ“?Oj¶è,J3¯(¼ßVkõ)„tfA‚Á¢â*SÄêwt/ÎÂù—Y̨çÌ$á(f;Z4´J²ž }dZË~Lž€«Ù?’hñUJs°Þf;ÈPÕ=LÿmüåfÔ`΂2²ö6yÉ×Q6»(üq»òpv[^õK!Ö²7牥žêl¾°ªÈÙ¼@&+H="¾—B|.¸Tp6þ(Ü‘æ_ÄZo_3QÑr£ûœu¿ðFTäsøÁ/9Þ nSŸ¯˜>8!È‚ ™õœ/úŽŸýT·°5#[$É“ºTU2¾¯cÈ+ÈÙ•ŽÇ³`ã ½‘ż28–ãnd£$ÚóÏ~6ÜBâWÛÉL™·Ê €ÃOÃ…ƒËÜ%î+oôà[xŠû®±àvwðål€9(÷Ì…9×PÌÝJ¬ƒ«ŽCÔåØ@½vaß?z+ r±‡ÒËÅo&¢Ý4Mù¡,Sš%SUd°—Ø­ö™rc3åüÓLá±µçÿææpóŸfjYê4éŒ³ê ½¥mùTv•¤¹»£éa?_UJ£')4j@é —çätA>ím÷4;V×á·ºÓ`çq\Q›…Æ\s6ö,ÓÉ–ç¾î`k}WKà(6žåzµÉbÆ.M§3€Šúeõõ@}ÏÁ¦ÍÛwä'¥ñî“$dM¦’ºL6F‘qB¿.ü߯ºÔÿ§ñj+ÊMû·ÆW¡Ž.— WpÏ`?m%ñ«~²Ý¯‘À-úç2}®F›eÁ¼ý%Üq™; wœ,ÞȆ¹$¾'F «†…}ö#G fbœ4µ5`œäaœ`®ÇŒÅŸ†=òÐè.gß%™ÑƒËÙ£¥•Ìj/L+'kG> endobj 71 0 obj <>stream xœxyXS׺þŽ‘½w•R%n jµXµÚêQÛ:Õ¡VTÀf3†BÂ@1L‚àŒmÕÖ¡jkµžÞ¶§Ö«§½­µ=gítqîs׆znœßsŸûð½²öú¾ïýÞ÷ý?Žàñx÷&¦JäK6JSb¹?_fgðØ™ãØùrdþ-Ñ£õbEÞðæïñ­3g>õe7O†§^€²IÄxoÕ;{«ý÷íY¸hÑâMÒt¥,1>!sÖkË^]1+Z9ë÷'³6Kä‰ñi³æãÙ’izª$-3015:K>k·45*m÷ò?þã¶ú¿mNÄ–·Òl”Ü”¾9c‹ìmùÖÌw²¶eçDmWìPÆìŒ ”ÅÇïJظgoò¾”ý©!Ë^U½¶|ÅÊYsÖ®óïZøòaSYØ’W–Ä"ˆxx‰&Þ æ»ˆyÄnb>±‡X@ì%ü‰}ÄBb?ñ2B 6‹‰ƒÄâ±™x…ØB,%Þ&–[‰W‰wˆ×ˆmÄr"€XAü‰ØA¬$v«ˆ@b51™ð%Â1…`ˆià"BLÄ Ä$âm\.b<O|ÉSò<ã6ŒäÏã·'Ç'¿çõšWéKV“·©ª›úžÞJ_.깿M0NøtbôÄ>ïÙÞÞèùç»}||r_XüBÿ¤y“:'ý×äÚÉßøFû~$ ¦L˜R9å'f9³‘é˜:kjÒÔ¯¦ÞŸöò´­Ó$Óº¦’Â/ü&ø™¾bzôôÜéöéÇ¡ÙÇpËqömϳÅÅDmý>8ÉÙV¡”D²‘“’%šüÃ…~2ᢂʳ¬  ÔU9[Þµõ aÙµ¦6d,uaBi‰QmÌ7Ò2x1@-óêŸ ½—{8Ø©7’¾w Š xšàÛãdâÊÔ6S? Ë©ûûß{=(L'œ¼‹öÈ©¡"K¡)’F§)c¤®0BGËa±“Š/WÛA/ 0WYkjhÁ½–gmëŒî†ô=bTB%ê¼$^¬¡FóLÂQmö¬fYF^+±”€t­Í ÐäåHåI/×…jGi¨͵–ž2üÁTo¢]èGÕc¨+è ‡‡ÐmB©qrõÁbœ³‹ ¬Ì©ÁYhnê¼û¤ï¼ð ZY«¨Î?›‹Ó Zœœ†G.*Ѥª;|Àá@þèÝÖt§ÊÏdzc;êû \—Áבn˜&øÐ>Þ%áZ8þ.ô:¥èOè'M´m±Ñ‚'îølúӥѺ"#ošTeûéU¢Ro.¦¡ ~Â%žžÛ‡Æ½}ðˆÜ†!1kßS_×/<ùøXä’9IRô‚AìÃò;Ùµ<\_… ø°œMeД…sÐLôÒã¹P§þí)œg/zб)…¹Ô´­F¯ä„ì Î9¿´©qøŠø_)†p%ßÄå9]FÞ,±ë@ÈQ'gD">Ú)DÞPe¨0–•Vøå·êkA-Ýb³ ˆ\&/z £ºJÛŽD¸}-D ¨Ò Ú‚7‹pö~rQoVÔ”Þ¥á î×l­MÖ® œ¼8ÅÏsnÞY¸…ï™3Á;“å‡iš¤b)Øvt§ §]Èÿ<¡aÌ58zŸ>¡” ‰%΄® ´ ªÓIU|aA6(ùåY5»‡¬‡BÑB´E¡8̓±ºÙ ùOp®. (¥~p#ø.FðJè?MO¢LPY^Sé-Φ΄ºÔ' ½>ÿúÃY#~p|æ®± áÖ(¢‹k´ Š)¥ŒQ:](‡è6J²–=Àªj{m£¥µ¶ÐÃÎ 4 MJÞ•”ÖÚ§Mr7ûKïüÞ¸‘_?Þ"a œ‹;)F#1îV•]’‘WKšT¦Pz¤€ŠHÏÚ#‚¥ìçL«£öøísIow‹ÚCê7‚•`IΊäðİÙ€W×äÌ—wŒ×çãWˆù¬mcÂ-…ÕÆšýNE­Ýs`(¥î ðCS—ÎÁIzñ³Ew¦ËÞ? FbʸCW¸]‹ëå Ð~ø>S'ËNôΔëpœyìÖÕþöäÃbñ,ìâý‚‘b÷ˆŒß¼²QüîÏ×l*¦eì—T?Œõ’’)ïäHãÓÂâöå­t€²nP K(ȱµˆ¦Ûàà R…ÈØxD˜h¨¢úꪇ᪳‰ÈÏ%rÁ°‘;¤Œ çu‡ÎáûG6Ëà'hÖÖ¯Òp5Ü1è¶TåYEMé¶Â6@÷¶uôJt‡”dl  n}‰vÉ©%V)j”¢ ´‘E¸^M” 1âÇý1 ‡Ê´ÿaÀõšYQ[ú> ó©ŸK{ãêñ©]ð¡ŒT"2!aøýÐç¿û 7ᨨEfM¯ßA;ñɯá“ûåw±«Ý¼öŸ è{>|?gà¼,ªXU\¢Å °,¯"ÙšYž èeÛv®Ú6ö$R|+µ]’éØÔŒð-a'¿ÉIÑë.ÒÚRYY *€¥´FDsN{Я^ùë'’Á'Ä[H] ‹vw¸úÚÛ´Ù-¢æ«ÒAûxšnÐÍë…[à0\Æ÷èa?ƒ¾—‘ÑÛ ÊöÐs¨iYïìˆjLE¼Ÿ}@oÆ]Å]öüéA¥dðÙe1(wÙ\÷ξëb( Ê>µÖ~ZEûÀûšOàoC¼Û‰ðÅ,kedàŸbÂöÒéÃè0sëFÿÑ/D2kŽ$/?øIµ ýbøîcÌúMXÎ.Ÿ†=Þß1š‹9b.f‹%·ÎxŽf”é|sÃGfÌñdÔMƒƒ!>N1Œ}r“{òWu½¤QUv€««ñ`žz«×õ¯.js•²Îxž†¹°åR¥rÕ›9¦zDq=tý‡9ßëÏ$î$Û5ÈD–iꌃ4AarꬡVcŠ Q•””£Mt´Êq^ ¿CÁrj@WUÈÁ­‚Z~.ä«ánû¹K¢jÐæ,¿^E \©Â2ê÷;Ûzá XÒżUžSo¼0Ô…ûí2|ô§2êcCó³Î: Tm,Á|JqŒï`·:x¬§-’“ƒ¥µE@4†|b ®:‡±Tù[M•«Ì ªLíDf9Õj¨4TšÁ©öèÎ ÛH¸‚Õ4d±tš9BÛÛÂí=CNöê­: ÔjIʺüx]–:^;XÒ¤¼®¸¦;j€½¦¢ÏŒwVË©ãz“±i›ÉP¦3ë¶¢õBùµøGŠs%6`õ 5Uåx™LNµ•”·oƒþ#„NN†WFW½ZI¸”gëµXÚ±*ŒxÌ×…Y̊ЋðÅi‚[lê5¦ À`0K€_~‘¥A 멯×#äµþÀ†(§| ¿ÃÙU_R§¶‹ k • ’nn·÷ˆ.»ÒÅ)41þ".#"5'Dҧ¯_<å8÷žÈz Eq ‚N{ßhr‘IOÉÑÈšÝÞéĉÿh¢q´dÏq8¬q12“¶BmC—X! †û{\?XpÕNȨϋ+ ¸y%º””ŠÒ„0 ·„Ív»?(£8½#cHžzKñ ‡5<@µ»`Êi’W­Pç—$•–5µcßråeD«p2yEåEVäÂ'з©Õaí¬ðs¢5rêL‰Ù”@U+M..V)TÙÙêF}eö1M °€ººÊ®ßÑVR©w¤Â)è 0-.=©0_+MQh ‹µe)¦ÊµN »»*`ö¶¾Sfs¥¥ªºQZŸ]“oËÖ¨,  uq2·¸˜•—ƒ÷+—'_˜Ã¤‘IksR’£ãö(×:“6…*»W_÷5ôŸeÔGXBL!c)É×nÆ=ÊÞå"EQÙûžNä³™ÿ/Úµ¥……²­h¯pÜ™s`Áh¯­r™í&á‘n<µÐ‘~F¨ÜŸ{P–,~…:Kµ ”™ÌbS…©”ÓG2 ’Œ IhòÅ®#Ö–fQs«£¿û1\ÈÎ6œ¨©é4ÓX‰òo°~œÑšÍg—A•‘ è{¿3Ÿ»:l·é´•b\5¢L²ú}¢ÍyüÊ;g–£™ f£¹HüíB8ùÞûw.‰}~Û<†§_O°p)ÿ·%.f}5öHŸÒl Uv§¾~. IA¡lŠª”‘·KòΓ”2ª5ë8ÆR»¨7*ãšM¢`ÅÈC¯vV°÷©¤Jw«5oqøúz”ÖÞr°³ß‡Û¸³üá*ŽÙβƒL¸9¿œ ÙÛ(YN]××aç¶S‘§Ría˜çǽ> ÍÃVaá¯Üös§ÅÔ©:WÅÌe;®X¼ntè;äjÔ9™ÙÚ,@ï—]†S Ó~ù’»S.©ç|ÒQÊEëûË»iÏ Øç¸Èõe“ñ6ÍΧ0Åîðê`ï“àb]ýõj{²Œú´È‘ 6Óè…~fßòBñ2ÒTgvÓ#i”18O¡Âæ6 ê…+:yì|8™‰>”ªŒ± ­1»[yLçÖcSWAÿEu:¹/ùx¨cŽiÒ*4ÍÿrœôÅÙÎÇ×ÅÈ×3fèÝØœ¶Ä2ħUÔ¿D´‹è?°Ie_ôlePòG ûËhvnø7þ‰…‘¸¡p±1‰ã®¡çQ,ŠDiŒÐjÂõô˜·áuó~ºùÜÀÇéþÆE®­ÖU—Þ¡a g˜ºÊ‡¾èúü™†ôâЛ"t—3üõª²MôH eÜ™Ÿ®7€‚Rm) 쟙ֆZ÷WîDìÐH22Eòœ¤¢Í€æº4ú{ëBa§oǃ5ðEÛédLù`££ôþ¸œ]!"Ø…öÊ©S…•Åx’©úw“tyUMMÍè è;GcË IŒ‹íp=ßáb”@]QPÂ`Ÿðr“«¶£íH»½œÄ¨ð¿‚¶¢â¶¾>¿ì-¥o¬ã,ÔC…éÊZz+V;cÐG^0ŠÙÎþÀ€Êr›¹²²Æ^áôw½‘s¶«b“³Å¹‰EëØvŽê×]¸Ô÷¸Íçhè´8™Ärµ ôÑì$.Ö!¥ð™g/Ò…àtÖæçpÿE&$D…»“††ºÜCC‰]‘\*q›NïT8|‡pŠ‹áÄi‚Õ¬‚•205•Ò¥)±wÕ˜³1gÝkK®Œf®^‡+†wÀ‰»Å7’D93À~¿·E¬ >ä:+¥÷æ»s?¦Ó8BV¶Y,v,šVCKÑÙÜÞ¢!ìûýúúÞ ¿pLŒ|úF– œñ»r¢ïæÉЏQW‚=Í@sb8æ*9£‡]ÃÊr­µôÍ:)ø‚~8¬M¤¥0ÌkäÒ€Â¼Ž pâð)8©œqR¥ëµ«8÷PcpyÝC¼9¨Ôpz˜”I-iÐWÊ æbP ”Z-š‚¦ÙM(HN3Ú”¦ØQÈÄä)RŒ\Th•¾Òxš†$ÕêüšÞ(«ÔÐäK¹j'¥%æÂZ<6 úµ­ñª…æfõ³ÒÁûO¸Þâ{vý~Gp¯¤9låhÿ=o£‰s#.Ù"øÍ¨ÀQ6æyn[ÕexÑ7XØ|èÈ3 ×”Ÿ‚;àã–ÁÞ“}mŸG4¼M™>¨·_­ƒ—µÜà€‘‘ òÆ~šýí–SncƒÂ$ I¢ÌN ‰•Ïl\G•(#?ÖÛuÑ ÉDô¥á3)Né­ÀæZmÖ¾² Pg²qWDßʨsEÕ:×^X=ò½˧‚ý‹óJ}Ý0w½sçÙ…×'c=:6„zÞs2“Úfxvéµ;6sûQêÕç°„§K‚hÁÙѰ%µ˜?#¸ù³ÈI%–kêÁñѾ­´7ÖYiÁöf{UãŒã¶Ì ®sM±jU¼a¬‰fÜä}£‹+ìMu5- x% ûlòàÑ¥1jUç¿ )ŸßT*‡Gìàý–Èe"@F¾k°€ 6¨ôùh<ú^ˆø­¶ËP jü€ÓV=d.ÃÃe%—‰ë2j ÔQh•w/¢ èCäÍ% ¥U Ú©­æ,Éiu¢¸¦°áLùQØAÂ@6®Éà|G(ûc]Ks—™3ñê_Ï _ƒ3ák|hölfÀ¶ˆèMÉ{³–€ÕxV{Œ»ßNýv#á0ôe¬ŒèæH‚uk Óµiyùx:>¨¸Š¡’‚‹/ž=ëØ‰ˆFM°g&î«@èÏgÌ«&¥ྺ‘K¡ ÄóÊ ªÍUæò²öWU ]Ö¬PñC™ÞÈVúcȰ)˜þÑþGÈÌ<ø-w9Ém ýØäÁ p&Ÿ•ÁxFN¦mÖÏ5ÒhG™¯|~·ûøÌïë?C¼ƒ‡sâD±±9‰Ò tÙyµ·ý]0ºÍñµÙ)š"{“X—‰­Æ2:“]1:»co~á {àü œ&øúë`ú>t·úêñØíÛ§Šs©¯Òܹ=‰´àVgZcøáé›$aAr…õX’(öxš=Ð’tyâ¾⿃k°Þ’pþiÕ‰´nq¶+×ÓH ¾¾v¼éÈåé÷ÏÏóßppîÞ±„ÁIϾêð…8½_š&x‚¬…a·¼I¯C¾hõÖÅA‹ý4¡¹&åypîUÈ'PôT$!¡žóâ Ûÿë$v¼¸ 7Äb>›„k‹ü;²6„ ñë‚Ñx€ühôÖC¼Õl8éáÏoü3"“³ôêTQ/\ðÕpþQ ãÌÖ}h9òÖ¤’çÖ4ˆsÝŸ‚GàJåŪ Ke]¹ { höa‡=Ëq½×°þŒγƒVú¸´#.V&̪ÝÙ¼Jd*ªÈ©È¦á»S»àüšóÿî¹{ã ý€Çv±/1#¦å¬‰Dôø±øá6†]]^jd ìñÂöö£=¨yaÛæYéà‚^|xÙÀìL’fÇF¯\†&4,u­8³îÔ¦Á˜ÿ ¦;¨Ý½2WöÉÔ+ùßø"€âúŸ:>p ¹Ú>èçŽ%Ü „y€_Lý¾1܈wnGk˜+îŽæã'¾~x Neß »Ù¿ð2-¥.Æ»2šÃî¬_ Ћ‰òçKƒr"dA1œMR'›Î¸[j̓eNP]V[ᨶ·€FºMæ”fk SsD²¸Â‚¸4YhÓ×súŒ¤/;Ø—y^ð|{·WI¤ýç!¯¿’>Š&6ªFØH÷(šè®ðö†¢ïç â¿d•=Ž endstream endobj 8 0 obj <> endobj 72 0 obj <>stream xœyyXS׺þŽ1{ï:UÁh"6q¨CµŽÕªuž'T”yežç! $+ †@€0Ïó ˆ¢8³Ö:[+µ£m=m=ötm΢÷¹+Ø{z÷žçþñ{àììÍÚë{¿÷{¿÷[°ˆ±c‹5Á)8Ü?vÉ‘Èpßëõ"ÆŽÅÌüÇÞ‰ôÿ\;¬à0‚ ˜ÀÆ–Íœ/´aôSàýwaÂdb,‹µf¿«i¡ó×/þp{dTRLp`Pܬ•ËW¬šå—4ëÏ;³vøÇFÌš?$ø‡EF…ûGÄ ÷‹5úÞYGüãÃ|cþûw­öÿ·>A^[#ܶEºoÚ½3fWìî¸=ñ{ö%úîùÙ'?|â ÿ¡‡À #ÁŽ!N¡Îa.á®ËWˆW¦}´jõdzÖÌ^;gÝÜOÞ7®Ÿ·qÁ¦…››?زÈs±ÎëCýÑ%K}–#ˆ9Ä!b1—p >!Þ'óˆ#Ä|‘X@8 gâÂ…XD¸‹ 7bñ!áNl'–Äb)áIì$–»ˆåÄnb±‡ØK|Dì#Vû‰Õ„=ñ1q€XC$ÖSâ(aKÄS .1˜N°1†àlb1–°#8„˜˜I„€  !ñ1‹¨!Ƴ‰ñÄbNl$&Ä&bñ.±…˜Ll%Žâ¼ã?õ'²"ÇØŽñs½“=8võØjÎ Žˆó‚ !ßP[¨NšO;Ò§ßûŽy܆qãÇ÷N;A5ዉ'j'Ñ“B&]{w结m'3ÅsÊ#›e6ŸÙÚÛL?µ`ê=îbîÓiþÓ§™>ezàt o ïï ÿcþ:¾?¿eÆ¢‘3žÙí³K›9sæÖ™–÷Òß«~ïù{H°EÐ'¸%´~3ëܬŸfOž];ûübNÅœ;s¾žËž;uîâ¹AÐ0i8”B·.fv)kØÅÂõ6(ò‚ =s“—H¢#²ýh¾,ÅSÃA å™hª3 ³ „½ð4“]‹MQÆh იä4--‚9Ôˆæq!k!j9“˜ PÊp/²>‚;†Ø%Ó`™t7¤€V6SgN•›šÝW¶Wˆü)Í>YŠG-†'Ì”G–ܤí£aõƒÏ¥­GÃ’÷ï<¥”zWQ°ÜUÌO¦Œ†\]> ksÅB¤£´r©{=ÑðŽýð".J‘4EJÄŠ¤ð@ÄAžïàÁ±'A9”šsštµ:ž]Q73JÄCBÈB«xhr^9[î–Ž#—X(‡ÌäPÌæª¶^8.äýˆf5»‡1$¥(‚µé@®•Y8k¡\²ÅyǬáÁùpßÍ'¥¦™üIÃË@óºÔr^CõëO 5Ýöeñðtî:_¡ÛB8PÚ-RÙº ¼ÈWÔcp¯¬­¹µ±ô8z’;CëÂk¢LûŠú Êò*ËhÛ_«ÊÍ­'gÀ±+Ðj"¡ú†û ôªZÅ´íËËq5~fç„ÇãB“üÒöÚC’Û(„ca2¥+ÏÌ.Öõèx¶¿B¶á¦ÛÊ`ƒ›ïb-³¥¨eVֲ꾅…ß²¡9ÆEÓW,F4óåhm~ú !oÙhªPÉ\ŒÞC¤÷ž-'*;„‘ý)wÁgô½×î þ•xç5{ØÑšŒHÙ¯-N±@‘.SˆÑ\”ÀC aŒ¼HU òùÀR˜Ó¨Ïy _G[P“ˆ:£)”ü‚fÃéȉ‡¶QÚRS—§c|-ÔJ½4_û˜†.\®~]]~ncIó÷N&{˜`\¹©0ž“@ªRd‰ ˆ â,b÷/°¬ ;à´ó€ÿ2€ÆÐè䣙Ðr~é}vET²mÇžðµ€oKµ;õ…} àXî} i8ïr‰NAc¨9Ҳϊ ‡áŠFfÒ›‡C0þÅtÛ‚,Î…êr‹N–§½AÔ­(¤µBqÒŽÿŽ…óàäß,rô‰uò>¦Tzç„ ©S2?…ÊÕeãèéf£ÂK8D¹ÂAEÛž‚K™ný¥ÖÞ}›Ñ;[74ÆcËv¯#­õ£0·1_¶±Þ¼fHÈbMƒm$¤ÁoM×.Ýlû¼ßF¡‘n»‚Ú_Ç RÐòÒ˜—©Çٺ哦ÂJMUMuz©Ý“ëwÏÆ6j"âFd±¸Ôð»jz/ׇ¬¨°rTÒÉüÞÉj„$3ë{ØþÎE9IäuNš~3>¦BEmCk@ü¡ö»ž>Awßõš;à8+j¬(Š®:HWi0Oª“¤ @R IFo³WŽ7æž'“èØ5[.9oízåÇ€¯œÜÒÙBCJ5ßt9“žýÌ„FÖ]LÝÆ…;ÒdžÆ ^‘,Wª¬dè4 }] ×Ôìk¯ìoHóã£SRã?@\s];~¥ÞöÎ3=°µ”õûkxé5Û2 6XÈ-Ù2“ö ýà%äŠs”*ßhÍQƒ…úóã@éîçå=6b‘kQUy ÝV¹ KXÍþÍÑL®b­¾Ʀ”õÙÜ5„©s–«&=ôÊíiþ„V&S×2L àN#"Õ‰<*>Lè¡Í'…ð)š/¡NcMÕyÒ(‹ÚpÆí~[GQM »›³–ÊÔœ-mÍ?WÈ¥ÿ¨rS¯­û¬…\§—jXw®X`znÀû;+¢¾ü«sm–É×dX÷')e6”²˜h .ŠÉÆ ³ˆ€B£HW,D&Þ<˜«*Ì(¹|P’ol1Ðfä&¦Ú5FEïûpêäéU¥! ÿ( j}z¦Æ²±Àܧ¼º;ÙÆzƒ•Ø’væ?ðwàú!­­¥SD>Så¢uœò–%DKT9UJ¢%¥(ÐQñqQ¾]á¸zN2$#7÷Y¶Õ-ü¹á;xÃbªY™§É@¬Š•G­@1¼50.¹PÀåùÆÓF¼]1Õ–n’•ºdIrc²“—#OÞBX˜ž§Éy|P–ŸÓ’‰ŸÚ#¦*49Šr7h‡~ä™Âr¤Ù ä˜L5Xÿ•¼ïÜì¯Wß²r‹:¡þÌ+9iÈ*ů &1ŠËG^¥Í¥çpá3\¸ÌÁ[Üd‰L-tœ²°G])Я®WÆ·³8zÉVû8KbeeYiy¦6Kkjrµ9ÀH×4–wöÕD8 RhÉÁ¤Ôcþñ‰’`‚kؾÇçjOWYÿUmKVIb—]3(3µ´ã[hVçpµ.ÜÉ íD«yЗÒ=̳‚lAm˜Ëê|™~Û[.ËßVD‹…Ú”%Ë×> á!ªºìso:¿ ÄòXªŠÐªŒ:ª 媓ä-…$ÐÀƒG Ã›E9w²ød…Êê/?2³`Ã4xÔL†Ä¢°4ºñžÃ –š:s“žoF+ÅT½&O$@&‹ S«dIÒÄ4O\‘Z É5(‹pß5d×ëps©zP$mðú½ÏC$Zî§P†dðÅpž™Šg³ Ë„Oá»ß¡Y™*½(± T¦‡hF+´‘õéLüš — oäªõ~’¨TO)?"“Beë й©¾Â‘"*l(ä但cà\8yó˹' \Ævœní¯­RˆÊaå»Áv±=÷¯sõ.¯í‰Ì/¥ÖîO[ÙßòoY unãÄ^sŽE#n:½‡Ü¤O3h[i&œÒß/(x’9j_"†˜«¸"­k‡+¶(5%]«ÊP ¡:DÁlUaz¡•Ú%fc·Ãã'¡ªÓ‹å9ÉDZž)J§ÍRÔº1H‰;˜&ŽII°Š¦âÆ’dLÊLt¬HÒÓ}§÷"œwQˆí̇ùy•¾•ê÷N«ê1›™—s=wÆô2ûÏ!õæâÝg­ ÿÕYÔÐ*¨©°ÔÖÒ“þ9ñO‚²z˜l@ßXqò$Qôˆ¥0zò‘_¤çËõX¿QšÙÒäuVNÊ0'3Åeš¿ÓÌ fŽœæ’0—¹Ëq%î†?ÛíöLi¡fTÊõ÷L÷³0’ ž™QÏb>†vܤ̤%Ùâ >°œù€cF¿Ph§„Ìù¬Ð|MOC‰,#pÄÌD+‰q[šQ˪y±¬Ë¸R­ ¤ã²KÍï27°©ðJ –ïµzÄ]Èt[®ÂOˆ–SþQùVóE-ųÍ4õÁ*ȾÔ^zºY¸ŸÊÌ€ ú9hñ.P*e yrb´"Ðkœ?‡“áØ¾.œñrâZ–—¦ZÁ²±‚õQÏt[Ѱ«.™ˆü\]l˜M£o©.#â Í"²¦uzÑ#þ-j3)«XaÜŠ™ Òð¦ ø©ÑŠâSÑ©Vó!\ËõÜ|,b?8ŽÕE\NjW6j®Ñð*™vSQÓÞz´Ì¸¯$ÿ`/¿¨`÷VCêLJƒ8)@Oà‡Üü'ÍmWÁUPY°jTÄ[™ÿhe5c{± ’løÇðZ.rD3±)ð^Ò¸ìÂá€ý7'¾ÆÐÎÄŒ÷Ï/œ…öŸ®i] èÀ±½ 7©5ô‚GÀÆÙ®×Ԙ䘸¸  ï$px—6¸õ†ü ¼®}uò4ÝÑÝW~Ðo­âœFè[Ëú;6׬Uô.vƒ–úöòED‰ (Ú¤(Æ>±¤¤¢Õ§ú½k”w´0Ú;-P»ž^úºMj¶(ä;¬co™Zg烇4¼ 'QobY'<ÛÆúå5L±Ú{,µÒrSuJ©2u³ò-#7àm•Ò}Tµ¦X[ ž‚óyÝ•W[¯‚[त=ªîxϪÚ%˜*ÅØdíàÖ5Ðîš×û‹Ü•(Ñéã£rp^¯‚!Yµ¬Ú»0åqM-› axÜŽMTñ9¼è¼È,ÜV—nݱ̾Úÿvˆ0:6!Q&ÏHç'ī䏯çËO&nw´ËcŸŸ>©>Ù/ho(níàšW×ÖLÄÍæ9ëcsA(mj©ÉiͰhô  tšjšjÍ-à,¨SWHi¤™ÁmV>Qô·MÒÀÛO ÎÊ#u=¹æÎ3Â,ø’;XÛÒÛP^$°å{ƒã´cdÐÑ~7¼mÓ.°îÁƒ¸²RÌ\ç\µQû =©ßü.¬sð=tT/SjC,&Í)…eéLûº;'í˜p$Kª:íˆ'(ÌLÎJË×à¿WQ'{ë‹;ÝW¸Sˆ<(ÍŽTù5~(ˆ²Îú¥Ìë6Öë×Pг6¼ÀÂõ7$æE4#?˜Íƒ¶U΂ïA·´-ºÎ¿kMõRœ•:ù -ï_‰MUlQáÄÖöH“ÕÙ»S—ô0]åÀÕäˆ'ó‚[›ŸÓ § [âžà(R-ÖX=.~÷Àk›'¯?šnû)fro–2׺¤Ò h™GŒuĤ7éò¿rt<Sš­©ŠÝ´í—pìðrnT\\dDy|m}yy]]\yžüÎKZãKÔ\jóÙ (ùuºí‡Œ#®´Òvf|º\–l§É™É9´mSa@@Nˆ/ðI‰ Kò®`}#ëpïDÿñ*ÿ\iVˆ¡÷ºݶâÀE8É]GÖ£ N9ikoÑ™ Ívù 8Ý¢Ä+‰Û»Ò:ì ýõÓ7_8Ý@¼{Â9—}{ÀEúâɶk§NŠ[ ¡…ÑExB¡£ˆfh?þ÷£á¿„ÎÌQ®Úp Ö_êh•Ï,Yo¶†]‘›Œsû.6gÄÈU Išw0…1¹,©B’‹›V\Rr|hGÜŞΪakcùð”¶ýÕmxó¿©Ì«“,hÄ~ÈÍÂ]—)5ájdr.Px‚+K.G,º’TÁMœ‘«¤ mâT’UV )=}a$ƒÔ®NU¬±Jé©?-ÍÒRÖClã4(5“‰:_öIm|hOÁYèP¦Ú 6dðsPÓ©©*™@$†fÒÇfñ=‡–@^] œÇÖÝÐ`ûsLBuhóÓ¤¦J%RôšÄcÖRéú²ˆÔ#b~¸•óº\õð!Wê)I ´.;ä£âÚÃ0¥¬7¯á=ìagkc‹ÈÇjs¢þ}UP`·Ê?9<ÊsذxTFNjT¶ë4¼?:Í|nfZEÔÓ?眛ÚúlÜY[ît*Oæö‚Ç4,¤ô¿å>Ë}K`Ö߆ØeÓ ÜLÚäyÚKÖSƒt½[J€|Îb6•¯3é°‹jÌ“x G¢)­³Dr meÃKYìÛô‘ÓK ¤(£dáhÁ›‡ÃïB¤•3”æ6ê³@¾®ÀzÞdQ}x6ê^ µ#½<3 c˜¦§ùùg°K¶à”ðúY/† ½õ×zÌc&Ýt)ùÚN¶P@Ÿ“g4VUt·º§<+B8¥9¢;Zu=ÎL9I‘æ ³¨úîÆ’Ó€¾\µVˆ)ƒJyX…Š4SÑúÐ,¹tð¡Ǹ²é°[ôagAÒåàgà ¢¤k÷Ó)¥ÞE,w±žšÞžVç¦x Q6¥q”JœpSú玷0üs­ìtΩKä $ª¢‘h úž‡xðeIFŽ&“ŸZ¦²€|PY‘wÁ C©ˆº¬ÍKm^ß´Ž7 µ ÷™ Ê’ôÑó¹òÂìs™øˆ:§6'µ-Î#ÍV¤–2ë᪑õ3ùše Ï[úósÏçN„ÕÃ6լʟ`ÁOlhÄzá|S;ú#  wÓ„èÓŽm>çbÀ9Ð]ÜÚ2p±ÒN¤¡ïr8MdDs‡Naƒãü}f­^íó;<ƒOÁ1/„£Õ2<½àl8n¬3“›@r¾ö ͼ¢ÒôhÏrf¿¹ÒˆMSY®8TˆœÆ>Y²Y‹™æuûû6Òsoý3y/i]êSñ€¿{Áf"á{\iVÀa¹ÒKËGi$Üw|ó²ãxÂÿå“Çs\ãBƒÅ¡É;ÊԼοµ4Þô——ެÙptÙš•B´ æÈ˜Ô$øwè ËX]°Œ ·1ǹ[¶ntxxÿê•{7[CÀþå»+6ð³§þ÷°dÃ%ð9wTh*R¯Çµ;‚]ôÇŽû·F&+Ø“±8‰% AÝñw=­î:#<ÝU5nƒþ”ÞȆ„r‘é˜ËøÓUmf|aq©»Orh  <;óCæt^çƒS×}«çØþ@qPL´0ßÚKB Ü`6b'xêɦÇX>™0˜ÂÇö!Ñí‘Üý°­§l} ׿&Ñž\¤$¡þd=ç—´1—Ÿ² s— ÷2Ÿs¡Y :CNû7¼T£81UøÈŸD,¤Ðj€høªLMNc‡RzR©€þƒ`½øÐ– ‰)ÆòpAhe|n #%²ÿÞØGÏïÕœ;'b}²gù>KÄo覧 ÖÚ„ˆ]3>x²’pÂã[|MüNô>÷¾ke p¤÷y{ïÛì6ðâfY×àíã¾ÇÜ•½à=pªëúnŸ]£ïöÆ.êÃá÷qýÌv®¡D_ Ï-z”{ÔÑ墒¸XQR\rኒE´pÚÿqÝÌØZVý÷ìÁx.[pÑr§ïÍ£«p2€v4\·¾ƒ¦¡ñ+ç#;4éÞ'¸x²¨ë¼À­AìYèÃhÂa.HLO•§FÅùK½Ùó!¹èJYµ°¸´*¿Ð_Z6¼Uèvθ÷áá6Vr¥pç·‹‹ÈzèÍ9L†#oâ“ £aÖ‹qNp ™€fpíô;‚Â8d ãÀø¾õ¢ÁzÁ"‘æ&ZŸ›A–á5qÇ’cÍÓA6ëd³áLƇQS×P]Yß].Dhìÿúnt›¬þoðäò”Íld2¸M×3¯É£¯ÛSöÊÈÔèà¨Äãàð* ê ¨‹,vœF-ÔËéØßh1šF^ 8)Ê W5E=05˜Zëšj-]à hU6IË¢»¢ÊЄOi¨¥†§|‹?¦ÑÞ¥Ü5—D•à4¸ØÜüi!Ý‚^q_.‹ÀÞÀ€bëX3<g\ÍdrѸ0©$5K ø R™(%Ol‘á~‘5lUiʨ…l·¬cºížßÑlî§ÍÝWÀú\P»w`\|°À6#¤\Ôf4êtÙÛ }–èìr²Ui¡‘ÎÂvæ ×6ê/hªêÞB3ü@Zª¬‡¦æ¢FTUY¯*µ¹úÆTÝ|£«§Ûz~9¼“qf¡wД§ÝîŸj+již¿Ðô <¡ïøwìC¹ >Gbvû{ COD$cÆÄV·_¨}ÖÖ/¬é¬-i´/ü–{‚tr;‘lŽƒxcl)mÛüey´4+ÌQ³Ñxd»óü‘›Ý§J[š„ýç?÷@¡Æ¤.)QZ2ê@7¨2vU¢7P¼3¤íÜ/e†¹Ù‰1?±KœoÈá£ÁGñ [Õ*´å|ùçpε,½V-(”šÔuiX¿®Â ·àŒ[,¦™ÆÑíet$š1öíœæÓ7,¸»ƒýf'÷vÓ©«Ú³AÞA±qÁ¡å¢vc¶×,=z@[a ‰ İâeå2Ëa1ÇH,‡µœ÷)8ˆ|Ñ ò´ª’µ ÏàŽy7ä­á1Gw¬ Z0Ú§¶-úz^—gu|¨©ˆ·þzdkÔƒØÛò‡àWð[Á󚫵×ê[ï X§ú´ßào¥pg=ëι›Àu 3ðtŸ§¸³­·÷…e}­  ´K[ã*‚[*°;Y¶óÀZ¿¢„ƪ¢¢ªB•I\,”¦ç€\º±·þÌÕ3.{ŽJb‘ûE ­?oU Ã"ÊÿRë0ÊŠŒâÞÂHQF=_°ÛÑNúª¶ÞϾjùÀwœðê£×~g¢Ë]e)¼Ïík‚j·TîÉßæƒ9ÒuQ£„l?Œ}ÓI×Ú ë{à{ 6‚?c&vN·ÞqŸ»1ÈMºÏj›ÑDø.Üþ²õÇ˾¾[5p[Y§¡wÑóíï–šŒºl]–ð&4rv‘ ÿø.q~àA)AÁ®.Ø*o¥mØwxôõœ®9Õ,°òÉn‹8c÷ó—XH¸pš §¢È}Œ–!WäW¡…ðÄݾ‚žWB´‘YÇ­Õ˜ã4'4îɇc¼hÛ5‰ñQvqç/”œmnÖ6¶”VŽGŽÂ¢bœ¹ºT h@´*Zª¥'9-*J¶”•Xʲ3LêB´EÙ:h#eÌ(K«H¬åW…ËJ°m*4—W‹ó}ŒÂÙ!¦˜¢´,^_­ÅØcìÈ6åjºBR/N–FÆ bÂcããdÊt^5U§qJSŠÅâDy¦(;A”†§>)å_–XÚšX)ËÁcV¢Dœc‘ö¥ Û”õ ‹4_Éó‹IQMõNK–h:¡@ZQ”›e)Ô5eeåór23Û*­ …–W çV±¾~ĆýÃS¸U(ðAXµš ÖIÌÚVzx¥kÌÏoÒYk ·¯[,¨¿Å†zØÁE‘{a$Šº£`ä- £¬öï<6ù³›à‰*ÖÏCðлYͽƒ‘š½ ™“[ô(ìã3¥…xú„_¼ ^ƒFçL£bJ»K•v@ý_( ´7ih¦€ ˜u]?/Ýp\šá‡íÏŠnRÛ–Ù‘UTÐÝY Ô‚YU%ªÀz@Tf.ªèv¯Ù´ùp´G 0ÜO ZOï²µ’ÒaA)+W*ý±‹s‡DIûp¬òk—cá=ö ïÿPmYè_Â{ì ïÛxç4Â456¿Aæ~Šn‘šMJÅ¡ÿš]²$&똾‡è+Jë.Nq³Þ 5SΙŠ\pÞê´ÕúT"C¦âÛ~˜*«ÓìÔ@agѶ^ù‘Ù1vGÁÑØÈáÇ'Ò?¢wð‡iÈÔök­8ßøåÀ”VEÛ†EZ R+ìr°qÌÊþo9†±›Ñtn D1/¨fm¡XHÿ±ŠÒ†Êå!V3ÿº\gu@-»æqí¡ö:Vn̬»Ö¦<å—ÿÝ“­ç]¼³,&ñ¸gGTîÔ¿À†í=èQ¼­*¼ó oý—X&Zï…x‡h·fÿÞ–ÊŠæÆxK€R©Õªj›[:M•ÓTÓr±]8IRȸäAïB²}Üóñí† žfN˜Hÿ Ź›‚ endstream endobj 76 0 obj <>stream 2021-06-03T11:10:48-04:00 2021-06-03T11:10:48-04:00 groff version 1.19.2 Untitled endstream endobj 2 0 obj <>endobj xref 0 77 0000000000 65535 f 0000059381 00000 n 0000086299 00000 n 0000059223 00000 n 0000057065 00000 n 0000000182 00000 n 0000004932 00000 n 0000061346 00000 n 0000075710 00000 n 0000060679 00000 n 0000068726 00000 n 0000060103 00000 n 0000062106 00000 n 0000059446 00000 n 0000057207 00000 n 0000004952 00000 n 0000010240 00000 n 0000059496 00000 n 0000057351 00000 n 0000010261 00000 n 0000014313 00000 n 0000059537 00000 n 0000057495 00000 n 0000014334 00000 n 0000018029 00000 n 0000059587 00000 n 0000057639 00000 n 0000018050 00000 n 0000021331 00000 n 0000059637 00000 n 0000057783 00000 n 0000021352 00000 n 0000023305 00000 n 0000059687 00000 n 0000057927 00000 n 0000023326 00000 n 0000026702 00000 n 0000059726 00000 n 0000058071 00000 n 0000026723 00000 n 0000029921 00000 n 0000059776 00000 n 0000058215 00000 n 0000029942 00000 n 0000032650 00000 n 0000059815 00000 n 0000058359 00000 n 0000032671 00000 n 0000036980 00000 n 0000059865 00000 n 0000058503 00000 n 0000037001 00000 n 0000041507 00000 n 0000059904 00000 n 0000058647 00000 n 0000041528 00000 n 0000045237 00000 n 0000059943 00000 n 0000058791 00000 n 0000045258 00000 n 0000049932 00000 n 0000059973 00000 n 0000058935 00000 n 0000049953 00000 n 0000054679 00000 n 0000060023 00000 n 0000059079 00000 n 0000054700 00000 n 0000057044 00000 n 0000060053 00000 n 0000062526 00000 n 0000069184 00000 n 0000076323 00000 n 0000060580 00000 n 0000061248 00000 n 0000061960 00000 n 0000085038 00000 n trailer << /Size 77 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 86455 %%EOF flawfinder-2.0.19/README.md000644 000765 000024 00000012221 14112766343 016152 0ustar00dwheelerstaff000000 000000 # About This is "flawfinder" by [David A. Wheeler](mailto:dwheeler@dwheeler.com). Flawfinder is a simple program that scans C/C++ source code and reports potential security flaws. It can be a useful tool for examining software for vulnerabilities, and it can also serve as a simple introduction to static source code analysis tools more generally. It is designed to be easy to install and use. Flawfinder supports the Common Weakness Enumeration (CWE) and is officially CWE-Compatible. For more information, see the [project website](http://dwheeler.com/flawfinder) # Platforms Flawfinder is designed for use on Unix/Linux/POSIX systems (including Cygwin, Linux-based systems, MacOS, and various BSDs) as a command line tool. It requires either Python 2.7 or Python 3. # Installation If you just want to *use* it, you can install flawfinder with Python's "pip" or with your system's package manager (flawfinder has packages for many systems). It also supports easy installation following usual `make install` source installation conventions. The file [INSTALL.md](INSTALL.md) has more detailed installation instructions. You don't HAVE to install it to run it, but it's easiest that way. # Usage To run flawfinder, just give it a list of source files or directories to example. For example, to examine all files in "src/" and down recursively: ~~~~ flawfinder src/ ~~~~ To examine all files in the *current* directory and down recursively: ~~~~ flawfinder ./ ~~~~ Hits (findings) are given a risk level from 0 (very low risk) to 5 (high risk), By default, findings of risk level 1 or higher are shown. You can show only the hits of risk level 4 or higher in the current directory and down this way: ~~~~ flawfinder --minlevel 4 ./ ~~~~ The manual page (flawfinder.1 or flawfinder.pdf) describes how to use flawfinder (including its various options) and related information (such as how it supports CWE). For example, the `--html` option generates output in HTML format. The `--help` option gives a brief list of options. # Character Encoding Errors Flawfinder must be able to correctly interpret your source code's character encoding. In the vast majority of cases this is not a problem, especially if the source code is correctly encoded using UTF-8 and your system is configured to use UTF-8 (the most common situation by far). However, it's possible for flawfinder to halt if there is a character encoding problem and you're running Python3. The usual symptom is error meesages like this: `Error: encoding error in FILENAME 'ENCODING' codec can't decode byte ... in position ...: invalid start byte` Unfortunately, Python3 fails to provide useful built-ins to deal with this. Thus, it's non-trivial to deal with this problem without depending on external libraries (which we're trying to avoid). If you have this problem, see the flawfinder manual page for a collection of various solutions. One of the simplest is to simply convert the source code and system configuration to UTF-8. You can convert source code to UTF-8 using tools such as the system tool `iconv` or the Python program [`cvt2utf`](https://pypi.org/project/cvt2utf/); you can install `cvt2utf` using `pip install cvt2utf`. # Under the hood More technically, flawfinder uses lexical scanning to find tokens (such as function names) that suggest likely vulnerabilities, estimates their level of risk (e.g., by the text of function calls), and reports the results. Flawfinder does not use or have access to information about control flow, data flow, or data types. Thus, flawfinder will necessarily produce many false positives for vulnerabilities and fail to report many vulnerabilities. On the other hand, flawfinder can find vulnerabilities in programs that cannot be built or cannot be linked. Flawfinder also doesn't get as confused by macro definitions and other oddities that more sophisticated tools have trouble with. # Flawfinder GitHub Action There's a GitHub action available for those who use GitHub. ## Usage See [action.yml](https://github.com/david-a-wheeler/flawfinder/blob/main/action.yml) Create a .yml file under .github/workflows with the following contents: ### Basic demo: ```yml - name: flawfinder_scan uses: david-a-wheeler/flawfinder@2.0.19 with: arguments: '--sarif ./' output: 'flawfinder_results.sarif' ``` You can add many other additions to the arguments. For example, `--error-level=4` will cause an error to be returned if flawfinder finds a vulnerability of level 4 or higher. Notice the version number after the `@` symbol; you can select a different version. You can find the action name and version string from [Marketplace](https://github.com/marketplace/actions/flawfinder_scan) by clicking "Use latest/xxx version" button. ### Input options: - arguments: [Flawfinder command arguments](ttps://github.com/david-a-wheeler/flawfinder/blob/master/README.md#usage) - output: Flawfinder output file name. Can be uploaded to GitHub. # Contributions We love contributions! For more information on contributing, see the file [CONTRIBUTING.md](CONTRIBUTING.md). # License Flawfinder is released under the GNU GPL license version 2 or later (GPL-2.0+). See the [COPYING](COPYING) file for license information. flawfinder-2.0.19/COPYING000644 000765 000024 00000043127 13774402305 015735 0ustar00dwheelerstaff000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. flawfinder-2.0.19/setup.py000644 000765 000024 00000004134 14112766023 016404 0ustar00dwheelerstaff000000 000000 #!/usr/bin/env python # This is the setup.py script for "flawfinder" by David A. Wheeler. # My thanks to Jon Nelson, who created the initial setup.py script. """Setup script for the flawfinder tool.""" from setuptools import setup # Don't need find_packages setup (# Distribution meta-data name = "flawfinder", version = "2.0.19", # We install a script, not a separate package. # packages = ["flawfinder"], # Must be same as name # Do not need: packages=find_packages(), description = "a program that examines source code looking for security weaknesses", author = "David A. Wheeler", author_email = "dwheeler@dwheeler.com", license = 'GPL-2.0+', long_description = """Flawfinder is a program that can scan C/C++ source code and identify out potential security flaws, ranking them by likely severity. It is released under the GNU GPL license.""", url = "http://dwheeler.com/flawfinder/", download_url = "https://sourceforge.net/projects/flawfinder/files/flawfinder-2.0.8.tar.gz/download", zip_safe = True, keywords = ['analysis', 'security', 'analyzer'], classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', 'Natural Language :: English', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Operating System :: OS Independent', 'Topic :: Security', 'Topic :: Software Development :: Build Tools', 'Topic :: Software Development :: Quality Assurance', 'Topic :: Software Development :: Testing' ], python_requires = '>=2.7', entry_points={ 'console_scripts': [ 'flawfinder = flawfinder:main', ], }, data_files = [ ('share/man/man1', [ 'flawfinder.1.gz' ]) ], py_modules = ['flawfinder'], ) flawfinder-2.0.19/CONTRIBUTING.md000644 000765 000024 00000011445 13774402305 017131 0ustar00dwheelerstaff000000 000000 # How to contribute to Flawfinder We love contributions! Here's how to do them in a way that will make everyone's lives easy. Flawfinder has long been maintained on SourceForge. We now support reporting and changes using either SourceForge or GitHub. ## Reporting For normal problems, bugs, and feature requests, *except* for vulnerabilities, please file a [GitHub issue](https://github.com/david-a-wheeler/flawfinder/issues) or [SourceForge ticket](https://sourceforge.net/p/flawfinder/_list/tickets). If you find a vulnerability, please separately send a private email to [David A. Wheeler](https://dwheeler.com/contactme.html). To maintain confidentiality, please use an email system that implements STARTTLS hop-by-hop email encryption on outgoing email (many do, including Gmail, hotmail.com, live.com, outlook.com, and runbox.com). For more about STARTTLS, see the EFF's [STARTTLS Everywhere](https://www.starttls-everywhere.org/) project. We plan to handle vulnerabilities separately, fixing them and *then* telling the world. We will gladly provide credit to vulnerability reporters (unless you don't want the credit). We've never had a vulnerability report, so this is theoretical at this time. ## Change process We use "git" to track changes. To propose a change, create a fork (copy) of the repository, make your changes, and create a GitHub pull request or SourceForge merge request (they are the same thing). If you're not familiar with the process, here's some documentation for [GitHub](https://help.github.com/articles/about-pull-requests/) and [SourceForge](https://sourceforge.net/p/forge/documentation/Git/). ## License and DCO All proposed changes must be released under at least the project license, in this case the GNU GPL version 2 or later (GPL-2.0+). Proposers must agree to the [Developer's Certificate of Origin](https://developercertificate.org/), aka DCO. The DCO basically says that you assert that you're legally allowed to provide the commit. Please include in your commit a statement of the form to confirm this ("git commit -s" will do this): > Signed-off-by: Your-name \ You must include the DCO in your first commit proposal. If you forget occasionally, we'll assume that you just forgot, but please try to not forget. ## Development environment setup As always, if you're modifying the software, you'll need to have your development environment set up. You need: * make * python2 (invokable as "python2") * python3 (invokable as "python3") * pylint (see below) An easy way to install pylint is to use pip. Most python installs have pip, but if yours does not (e.g., Cygwin), install pip with: ~~~~ python -m ensurepip ~~~~ You may want to upgrade pip with: ~~~~ pip install --upgrade pip ~~~~ Finally, you can actually install pylint using: ~~~~ pip install pylint ~~~~ ## Code Conventions To make the program easy to install everywhere, the main executable is exactly one self-contained file. That involves some compromises, but for now, please keep it that way. We generally use the code conventions of [PEP 8](https://www.python.org/dev/peps/pep-0008/). The Python code uses 4-space indents (we used to use 2-space indents). Do not use tabs. In some cases the code doesn't yet comply; patches to improve that are often welcome. The code must run on both Python 2.7 and Python 3. To check that it works on both, run: ~~~~ make check ~~~~ We use "pylint" to check for style and other generic quality problems. To check that the code passes these quality tests, run: ~~~~ make pylint ~~~~ We require that the pylint results for contributions be at least 9.5/10 as configured with the provided "pylintrc" file, without any errors ("E"). Better is better. The current version *does* cause some pylint reports (patches to fix those are welcome!). Note that we configure pylint with the included "pylintrc" file. We intentionally disable some checks as being "less important", for example, the current code has many lines longer than 80 characters. That said, patches to make lines fit in 80 characters are welcome. ## Tests Make *sure* that your code passes the automated tests. As noted above, invoke tests with "make check", which tests the code using both Python2 and Python3. It's our policy that as major new functionality is added to the software produced by the project, tests of that functionality should be added to the automated test suite. ## Other Project documentation tends to be in markdown (.md) format. We use "~~~~" so that it's easy to cut-and-paste commands if desired. The main document is a man page, which is then converted to PDF. Avoid trailing space or tab on a line in source files - those can create hard-to-understand "differences" on lines. We have earned a [CII Best Practices Badge](https://bestpractices.coreinfrastructure.org/projects/323)... make sure we keep it! flawfinder-2.0.19/flawfinder.ps000644 000765 000024 00000330420 14056170370 017360 0ustar00dwheelerstaff000000 000000 %!PS-Adobe-3.0 %%Creator: groff version 1.19.2 %%CreationDate: Thu Jun 3 11:10:48 2021 %%DocumentNeededResources: font Times-Roman %%+ font Times-Bold %%+ font Times-Italic %%DocumentSuppliedResources: procset grops 1.19 2 %%Pages: 15 %%PageOrder: Ascend %%DocumentMedia: Default 612 792 0 () () %%Orientation: Portrait %%EndComments %%BeginDefaults %%PageMedia: Default %%EndDefaults %%BeginProlog %%BeginResource: procset grops 1.19 2 %!PS-Adobe-3.0 Resource-ProcSet /setpacking where{ pop currentpacking true setpacking }if /grops 120 dict dup begin /SC 32 def /A/show load def /B{0 SC 3 -1 roll widthshow}bind def /C{0 exch ashow}bind def /D{0 exch 0 SC 5 2 roll awidthshow}bind def /E{0 rmoveto show}bind def /F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def /G{0 rmoveto 0 exch ashow}bind def /H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /I{0 exch rmoveto show}bind def /J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def /K{0 exch rmoveto 0 exch ashow}bind def /L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /M{rmoveto show}bind def /N{rmoveto 0 SC 3 -1 roll widthshow}bind def /O{rmoveto 0 exch ashow}bind def /P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /Q{moveto show}bind def /R{moveto 0 SC 3 -1 roll widthshow}bind def /S{moveto 0 exch ashow}bind def /T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def /SF{ findfont exch [exch dup 0 exch 0 exch neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /MF{ findfont [5 2 roll 0 3 1 roll neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /level0 0 def /RES 0 def /PL 0 def /LS 0 def /MANUAL{ statusdict begin/manualfeed true store end }bind def /PLG{ gsave newpath clippath pathbbox grestore exch pop add exch pop }bind def /BP{ /level0 save def 1 setlinecap 1 setlinejoin 72 RES div dup scale LS{ 90 rotate }{ 0 PL translate }ifelse 1 -1 scale }bind def /EP{ level0 restore showpage }def /DA{ newpath arcn stroke }bind def /SN{ transform .25 sub exch .25 sub exch round .25 add exch round .25 add exch itransform }bind def /DL{ SN moveto SN lineto stroke }bind def /DC{ newpath 0 360 arc closepath }bind def /TM matrix def /DE{ TM currentmatrix pop translate scale newpath 0 0 .5 0 360 arc closepath TM setmatrix }bind def /RC/rcurveto load def /RL/rlineto load def /ST/stroke load def /MT/moveto load def /CL/closepath load def /Fr{ setrgbcolor fill }bind def /setcmykcolor where{ pop /Fk{ setcmykcolor fill }bind def }if /Fg{ setgray fill }bind def /FL/fill load def /LW/setlinewidth load def /Cr/setrgbcolor load def /setcmykcolor where{ pop /Ck/setcmykcolor load def }if /Cg/setgray load def /RE{ findfont dup maxlength 1 index/FontName known not{1 add}if dict begin { 1 index/FID ne{def}{pop pop}ifelse }forall /Encoding exch def dup/FontName exch def currentdict end definefont pop }bind def /DEFS 0 def /EBEGIN{ moveto DEFS begin }bind def /EEND/end load def /CNT 0 def /level1 0 def /PBEGIN{ /level1 save def translate div 3 1 roll div exch scale neg exch neg exch translate 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit []0 setdash /setstrokeadjust where{ pop false setstrokeadjust }if /setoverprint where{ pop false setoverprint }if newpath /CNT countdictstack def userdict begin /showpage{}def /setpagedevice{}def }bind def /PEND{ countdictstack CNT sub{end}repeat level1 restore }bind def end def /setpacking where{ pop setpacking }if %%EndResource %%EndProlog %%BeginSetup %%BeginFeature: *PageSize Default << /PageSize [ 612 792 ] /ImagingBBox null >> setpagedevice %%EndFeature %%IncludeResource: font Times-Roman %%IncludeResource: font Times-Bold %%IncludeResource: font Times-Italic grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron /scaron/zcaron/Ydieresis/trademark/quotesingle/Euro/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent /ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen /period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon /semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O /P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex /underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y /z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft /guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl /endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut /dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash /quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen /brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft /logicalnot/minus/registered/macron/degree/plusminus/twosuperior /threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior /ordmasculine/guilsinglright/onequarter/onehalf/threequarters /questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE /Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex /Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis /multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn /germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash /ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def /Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE /Times-Roman@0 ENC0/Times-Roman RE %%EndSetup %%Page: 1 1 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E/F1 10.95/Times-Bold@0 SF -.219 (NA)72 84 S(ME).219 E F0<8d61>108 96 Q(w\214nder \255 le)-.15 E (xically \214nd potential security \215a)-.15 E (ws \("hits"\) in source code)-.15 E F1(SYNOPSIS)72 112.8 Q/F2 10 /Times-Bold@0 SF(\215aw\214nder)108 124.8 Q F0([)2.5 E F2(\255\255help)A F0(|)A F2A F0 2.5(][)C F2-2.5 E(ersion)-.1 E F0 2.5(][)C F2(\255\255listrules)-2.5 E F0(])A([)108 136.8 Q F2(\255\255allo)A (wlink)-.1 E F0 2.5(][)C F2-2.5 E(ollo)-.25 E(wdotdir)-.1 E F0 2.5(][)C F2(\255\255nolink)-2.5 E F0(])A([)108 148.8 Q F2 (\255\255patch=)A/F3 10/Times-Italic@0 SF(\214lename)A F0(|)A F2A F3(\214lename)2.5 E F0(])A([)108 160.8 Q F2(\255\255inputs)A F0(|)A F2 A F0 2.5(][)C F2(\255\255minle)A -.1(ve)-.15 G(l=).1 E F3(X)A F0 (|)2.5 E F22.5 E F3(X)2.5 E F0 2.5(][)2.5 G F2 (\255\255falsepositi)-2.5 E -.1(ve)-.1 G F0(|).1 E F2A F0(])A([) 108 172.8 Q F2A -.1(ve)-.15 G(rignor).1 E(e)-.18 E F0(|)A F2 A F0(])A([)108 184.8 Q F2A(egex=)-.18 E F3 -1.07 -.9(PA T) D(TERN).9 E F0(|)2.5 E F22.5 E F3 -1.07 -.9(PA T)2.5 H(TERN).9 E F0(])A([)108 196.8 Q F2(\255\255context)A F0(|)A F2A F0 6.394(][)C F2(\255\255columns)-6.394 E F0(|)A F2A F0 6.394(][)C F2 -6.394 E F0 6.393(][)C F2(\255\255dataonly)-6.393 E F0(|)A F2A F0 6.393(][)C F2(\255\255html)-6.393 E F0(|)A F2A F0 6.393(][)C F2(\255\255immediate)-6.393 E F0(|)A F2(-i)A F0 6.393(][)C F2 (\255\255sarif)-6.393 E F0(])A([)108 208.8 Q F2(\255\255singleline)A F0 (|)A F2A F0 2.5(][)C F2(\255\255omittime)-2.5 E F0 2.5(][)C F2 (\255\255quiet)-2.5 E F0(|)A F2A F0 2.5(][)C F2-2.5 E (or)-.18 E(-le)-.37 E -.1(ve)-.15 G(l=).1 E F0(LEVEL])A([)108 220.8 Q F2 (\255\255loadhitlist=)A F3(F)A F0 2.5(][)C F2-2.5 E -.1(ve) -.25 G(hitlist=).1 E F3(F)A F0 2.5(][)C F2(\255\255diffhitlist=)-2.5 E F3(F)A F0(])A([)108 232.8 Q F2A F0(])A F3 2.5([s)2.79 G(our)-2.5 E (ce code \214le or sour)-.37 E(ce r)-.37 E(oot dir)-.45 E(ectory ]+)-.37 E F1(DESCRIPTION)72 249.6 Q F0(Fla)108 261.6 Q 1.383(w\214nder searches\ through C/C++ source code looking for potential security \215a)-.15 F 3.883(ws. T)-.15 F 3.883(or)-.8 G 1.384(un \215a)-3.883 F(w\214nder)-.15 E(,)-.4 E .509(simply gi)108 273.6 R .809 -.15(ve \215)-.25 H -.15(aw) .15 G .509(\214nder a list of directories or \214les.).15 F -.15(Fo) 5.508 G 3.008(re).15 G .508(ach directory gi)-3.008 F -.15(ve)-.25 G .508(n, all \214les that ha).15 F .808 -.15(ve C)-.2 H .508 (/C++ \214le-).15 F 1.347(name e)108 285.6 R 1.348 (xtensions in that directory \(and its subdirectories, recursi)-.15 F -.15(ve)-.25 G 1.348(ly\) will be e).15 F 3.848(xamined. Thus,)-.15 F 1.348(for most)3.848 F 1.03(projects, simply gi)108 297.6 R 1.33 -.15 (ve \215)-.25 H -.15(aw).15 G 1.03 (\214nder the name of the source code').15 F 3.53(st)-.55 G 1.03 (opmost directory \(use `)-3.53 F(`.)-.74 E 2.51 -.74('' f)-.7 H 1.03 (or the current).74 F .23(directory\), and \215a)108 309.6 R .23 (w\214nder will e)-.15 F .231(xamine all of the project')-.15 F 2.731 (sC)-.55 G .231(/C++ source code.)-2.731 F(Fla)5.231 E .231 (w\214nder does)-.15 F F3(not)2.731 E F0(require)2.731 E .819 (that you be able to b)108 321.6 R .819(uild your softw)-.2 F .819 (are, so it can be used e)-.1 F -.15(ve)-.25 G 3.319(nw).15 G .819 (ith incomplete source code.)-3.319 F .819(If you only)5.819 F -.1(wa) 108 333.6 S .162(nt to ha).1 F -.15(ve)-.2 G F3 -.15(ch)2.812 G(ang).15 E(es)-.1 E F0(re)2.662 E(vie)-.25 E .162(wed, sa)-.25 F .462 -.15 (ve a u)-.2 H .163(ni\214ed dif).15 F 2.663(fo)-.25 G 2.663(ft)-2.663 G .163(hose changes \(created by GNU "dif)-2.663 F 2.663(f-)-.25 G .163 (u" or "svn dif)-2.663 F(f")-.25 E(or "git dif)108 345.6 Q (f"\) in a patch \214le and use the \255\255patch \(\255P\) option.)-.25 E(Fla)108 362.4 Q .864(w\214nder will produce a list of `)-.15 F(`hits') -.74 E 3.364('\()-.74 G .864(potential security \215a)-3.364 F .863 (ws, also called \214ndings\), sorted by risk; the)-.15 F 1.04 (riskiest hits are sho)108 374.4 R 1.04(wn \214rst.)-.25 F 1.04 (The risk le)6.04 F -.15(ve)-.25 G 3.54(li).15 G 3.541(ss)-3.54 G(ho) -3.541 E 1.041(wn inside square brack)-.25 F 1.041(ets and v)-.1 F 1.041 (aries from 0, v)-.25 F 1.041(ery little)-.15 F .033 (risk, to 5, great risk.)108 386.4 R .033(This risk le)5.033 F -.15(ve) -.25 G 2.533(ld).15 G .032(epends not only on the function, b)-2.533 F .032(ut on the v)-.2 F .032(alues of the parameters of)-.25 F .225 (the function.)108 398.4 R -.15(Fo)5.225 G 2.725(re).15 G .225 (xample, constant strings are often less risk)-2.875 F 2.725(yt)-.15 G .225(han fully v)-2.725 F .225(ariable strings in man)-.25 F 2.725(yc) -.15 G(onte)-2.725 E(xts,)-.15 E 1.707(and in those conte)108 410.4 R 1.707(xts the hit will ha)-.15 F 2.007 -.15(ve a l)-.2 H -.25(ow).15 G 1.707(er risk le).25 F -.15(ve)-.25 G 4.207(l. Fla).15 F 1.707 (w\214nder kno)-.15 F 1.707(ws about gette)-.25 F 1.707(xt \(a common) -.15 F .327(library for internationalized programs\) and will treat con\ stant strings passed through gette)108 422.4 R .328(xt as though the) -.15 F(y)-.15 E .641 (were constant strings; this reduces the number of f)108 434.4 R .641 (alse hits in internationalized programs.)-.1 F(Fla)5.64 E .64 (w\214nder will)-.15 F .063(do the same sort of thing with _T\(\) and _\ TEXT\(\), common Microsoft macros for handling internationalized)108 446.4 R 3.47(programs. Fla)108 458.4 R .969 (w\214nder correctly ignores te)-.15 F .969 (xt inside comments and strings.)-.15 F .969(Normally \215a)5.969 F .969 (w\214nder sho)-.15 F .969(ws all)-.25 F .33(hits with a risk le)108 470.4 R -.15(ve)-.25 G 2.83(lo).15 G 2.83(fa)-2.83 G 2.83(tl)-2.83 G .33 (east 1, b)-2.83 F .33(ut you can use the \255\255minle)-.2 F -.15(ve) -.25 G 2.83(lo).15 G .33(ption to sho)-2.83 F 2.83(wo)-.25 G .33 (nly hits with higher risk)-2.83 F(le)108 482.4 Q -.15(ve)-.25 G .506 (ls if you wish.).15 F .506(Hit descriptions also note the rele)5.506 F -.25(va)-.25 G .506(nt Common W).25 F .505 (eakness Enumeration \(CWE\) identi-)-.8 F .347 (\214er\(s\) in parentheses, as discussed belo)108 494.4 R 4.147 -.65 (w. F)-.25 H(la).65 E .348(w\214nder is of)-.15 F .348 (\214cially CWE-Compatible.)-.25 F .348(Hit descriptions with)5.348 F 2.501("[MS-banned]" indicate functions that are in the banned list of f\ unctions released by Microsoft; see)108 506.4 R(http://msdn.microsoft.c\ om/en-us/library/bb288454.aspx for more information about banned functi\ ons.)108 518.4 Q .271(Not e)108 535.2 R -.15(ve)-.25 G .272 (ry hit \(aka \214nding\) is actually a security vulnerability).15 F 2.772(,a)-.65 G .272(nd not e)-2.772 F -.15(ve)-.25 G .272 (ry security vulnerability is neces-).15 F 1.249(sarily found.)108 547.2 R(Ne)6.249 E -.15(ve)-.25 G 1.249(rtheless, \215a).15 F 1.249 (w\214nder can be an aid in \214nding and remo)-.15 F 1.248 (ving security vulnerabilities.)-.15 F(A)6.248 E .502(common w)108 559.2 R .502(ay to use \215a)-.1 F .502(w\214nder is to \214rst apply \215a) -.15 F .503(w\214nder to a set of source code and e)-.15 F .503 (xamine the highest-)-.15 F .562(risk items.)108 571.2 R .561 (Then, use \255\255inputs to e)5.562 F .561 (xamine the input locations, and check to mak)-.15 F 3.061(es)-.1 G .561 (ure that only le)-3.061 F -.05(ga)-.15 G 3.061(la).05 G(nd)-3.061 E (safe input v)108 583.2 Q(alues are accepted from untrusted users.)-.25 E .892(Once you')108 600 R 1.192 -.15(ve a)-.5 H .892(udited a program,\ you can mark source code lines that are actually \214ne b).15 F .893 (ut cause spurious)-.2 F -.1(wa)108 612 S .923(rnings so that \215a).1 F .923(w\214nder will stop complaining about them.)-.15 F 2.523 -.8(To m) 5.923 H .923(ark a line so that these w).8 F .922(arnings are)-.1 F 1.398(suppressed, put a specially-formatted comment either on the same \ line \(after the source code\) or all by)108 624 R(itself in the pre)108 636 Q(vious line.)-.25 E(The comment must ha)5 E .3 -.15(ve o)-.2 H (ne of the tw).15 E 2.5(of)-.1 G(ollo)-2.5 E(wing formats:)-.25 E 32.5 <832f>108 652.8 S 2.5(/F)-32.5 G(la)-2.5 E(w\214nder: ignore)-.15 E 32.5 <832f>108 669.6 S 2.5(*F)-32.5 G(la)-2.5 E(w\214nder: ignore */)-.15 E -.15(Fo)108 686.4 S 2.814(rc).15 G(ompatibility')-2.814 E 2.813(ss)-.55 G(ak)-2.813 E .313(e, you can replace "Fla)-.1 F .313 (w\214nder:" with "ITS4:" or "RA)-.15 F .313 (TS:" in these specially-format-)-1.11 F .524(ted comments.)108 698.4 R .524(Since it')5.524 F 3.024(sp)-.55 G .524 (ossible that such lines are wrong, you can use the \255\255ne)-3.024 F -.15(ve)-.25 G .525(rignore option, which).15 F .959(causes \215a)108 710.4 R .959(w\214nder to ne)-.15 F -.15(ve)-.25 G 3.459(ri).15 G .959 (gnore an)-3.459 F 3.459(yl)-.15 G .959 (ine no matter what the comment directi)-3.459 F -.15(ve)-.25 G 3.458 (ss).15 G .958(ay \(more confusingly)-3.458 F(,)-.65 E108 722.4 Q -.15(ve)-.25 G(rignore ignores the ignores\).).15 E(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(1)207.055 E 0 Cg EP %%Page: 2 2 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E(Fla)108 84 Q .701 (w\214nder uses an internal database called the `)-.15 F(`ruleset')-.74 E .702('; the ruleset identi\214es functions that are common)-.74 F 1.679(causes of security \215a)108 96 R 4.179(ws. The)-.15 F 1.679 (standard ruleset includes a lar)4.179 F 1.678(ge number of dif)-.18 F 1.678(ferent potential problems,)-.25 F .027 (including both general issues that can impact an)108 108 R 2.528(yC) -.15 G .028(/C++ program, as well as a number of speci\214c Unix-lik) -2.528 F(e)-.1 E 1.055(and W)108 120 R(indo)-.4 E 1.055 (ws functions that are especially problematic.)-.25 F 1.054 (The \255\255listrules option reports the list of current)6.054 F 1.074 (rules and their def)108 132 R 1.074(ault risk le)-.1 F -.15(ve)-.25 G 3.575(ls. As).15 F 1.075(noted abo)3.575 F -.15(ve)-.15 G 3.575(,e).15 G -.15(ve)-3.825 G 1.075(ry potential security \215a).15 F 3.575(wf)-.15 G 1.075(ound in a gi)-3.575 F -.15(ve)-.25 G 3.575(ns).15 G(ource)-3.575 E .401(code \214le \(matching an entry in the ruleset\) is called a `)108 144 R(`hit,)-.74 E 1.881 -.74('' a)-.7 H .401 (nd the set of hits found during an).74 F 2.901(yp)-.15 G(articular) -2.901 E 1.288(run of the program is called the `)108 156 R(`hitlist.) -.74 E 5.268 -.74('' H)-.7 H 1.288(itlists can be sa).74 F -.15(ve)-.2 G 3.788(d\().15 G 1.288(using \255\255sa)-3.788 F -.15(ve)-.2 G 1.289 (hitlist\), reloaded back for).15 F .965 (redisplay \(using \255\255loadhitlist\), and you can sho)108 168 R 3.465(wo)-.25 G .965(nly the hits that are dif)-3.465 F .965 (ferent from another run \(using)-.25 F108 180 Q (fhitlist\).)-.25 E(Fla)108 196.8 Q .169 (w\214nder is a simple tool, leading to some fundamental pros and cons.) -.15 F(Fla)5.169 E .169(w\214nder w)-.15 F .169(orks by doing simple)-.1 F(le)108 208.8 Q .235(xical tok)-.15 F .235 (enization \(skipping comments and correctly tok)-.1 F .235 (enizing strings\), looking for tok)-.1 F .234(en matches to the)-.1 F .466(database \(particularly to \214nd function calls\).)108 220.8 R (Fla)5.466 E .466(w\214nder is thus similar to RA)-.15 F .467 (TS and ITS4, which also use)-1.11 F .574(simple le)108 232.8 R .574 (xical tok)-.15 F 3.074(enization. Fla)-.1 F .574(w\214nder then e)-.15 F .574(xamines the te)-.15 F .573 (xt of the function parameters to estimate risk.)-.15 F(Unlik)108 244.8 Q 2.957(et)-.1 G .457(ools such as splint, gcc')-2.957 F 2.958(sw)-.55 G .458(arning \215ags, and clang, \215a)-3.058 F .458(w\214nder does)-.15 F/F1 10/Times-Italic@0 SF(not)2.958 E F0 .458(use or ha)2.958 F .758 -.15(ve a)-.2 H .458(ccess to infor).15 F(-)-.2 E .053 (mation about control \215o)108 256.8 R 1.353 -.65(w, d)-.25 H .053 (ata \215o).65 F 1.353 -.65(w, o)-.25 H 2.553(rd).65 G .052 (ata types when searching for potential vulnerabilities or estimating) -2.553 F .483(the le)108 268.8 R -.15(ve)-.25 G 2.983(lo).15 G 2.983(fr) -2.983 G 2.983(isk. Thus,)-2.983 F<8d61>2.983 E .483 (w\214nder will necessarily produce man)-.15 F 2.983(yf)-.15 G .484 (alse positi)-3.083 F -.15(ve)-.25 G 2.984(sf).15 G .484 (or vulnerabilities and f)-2.984 F(ail)-.1 E .454(to report man)108 280.8 R 2.954(yv)-.15 G 2.954(ulnerabilities. On)-2.954 F .453 (the other hand, \215a)2.954 F .453 (w\214nder can \214nd vulnerabilities in programs that can-)-.15 F .254 (not be b)108 292.8 R .254(uilt or cannot be link)-.2 F 2.754(ed. It)-.1 F .254(can often w)2.754 F .255(ork with programs that cannot e)-.1 F -.15(ve)-.25 G 2.755(nb).15 G 2.755(ec)-2.755 G .255 (ompiled \(at least by)-2.755 F .618(the re)108 304.8 R(vie)-.25 E(wer') -.25 E 3.118(st)-.55 G 3.118(ools\). Fla)-3.118 F .618 (w\214nder also doesn')-.15 F 3.118(tg)-.18 G .618 (et as confused by macro de\214nitions and other oddities that)-3.118 F .366(more sophisticated tools ha)108 316.8 R .667 -.15(ve t)-.2 H .367 (rouble with.).15 F(Fla)5.367 E .367 (w\214nder can also be useful as a simple introduction to static)-.15 F (analysis tools in general, since it is easy to start using and easy to\ understand.)108 328.8 Q(An)108 345.6 Q 2.757<798c>-.15 G .257 (lename gi)-2.757 F -.15(ve)-.25 G 2.757(no).15 G 2.757(nt)-2.757 G .257 (he command line will be e)-2.757 F .257(xamined \(e)-.15 F -.15(ve)-.25 G 2.757(ni).15 G 2.757(fi)-2.757 G 2.756(td)-2.757 G(oesn')-2.756 E 2.756(th)-.18 G -2.25 -.2(av e)-2.756 H 2.756(au)2.956 G .256 (sual C/C++ \214lename)-2.756 F -.15(ex)108 357.6 S .197 (tension\); thus you can force \215a).15 F .197(w\214nder to e)-.15 F .197(xamine an)-.15 F 2.697(ys)-.15 G .198 (peci\214c \214les you desire.)-2.697 F .198(While searching directo-) 5.198 F 1.603(ries recursi)108 369.6 R -.15(ve)-.25 G(ly).15 E 4.103 <2c8d>-.65 G -.15(aw)-4.103 G 1.603(\214nder only opens and e).15 F 1.602(xamines re)-.15 F 1.602(gular \214les that ha)-.15 F 1.902 -.15 (ve C)-.2 H 1.602(/C++ \214lename e).15 F(xtensions.)-.15 E(Fla)108 381.6 Q .916(w\214nder presumes that \214les are C/C++ \214les if the) -.15 F 3.416(yh)-.15 G -2.25 -.2(av e)-3.416 H .916(the e)3.616 F .917 (xtensions ".c", ".h", ".ec", ".ecp", ".pgc",)-.15 F 1.297(".C", ".cpp"\ , ".CPP", ".cxx", ".c++", ".cc", ".CC", ".pcc", ".hpp", or ".H".)108 393.6 R 1.296(The \214lename `)6.296 F(`\255')-.74 E 3.796('m)-.74 G 1.296(eans the)-3.796 F .901(standard input.)108 405.6 R 2.501 -.8(To p) 5.901 H(re).8 E -.15(ve)-.25 G .901 (nt security problems, special \214les \(such as de).15 F .902 (vice special \214les and named pipes\))-.25 F 1.123(are al)108 417.6 R -.1(wa)-.1 G 1.123(ys skipped, and by def).1 F 1.123 (ault symbolic links are skipped \(the \255\255allo)-.1 F 1.123 (wlink option follo)-.25 F 1.122(ws symbolic)-.25 F(links\).)108 429.6 Q .375(After the list of hits is a brief summary of the results \(use -D \ to remo)108 446.4 R .675 -.15(ve t)-.15 H .375(his information\).).15 F .375(It will sho)5.375 F 2.875(wt)-.25 G(he)-2.875 E .794 (number of hits, lines analyzed \(as reported by wc \255l\), and the ph) 108 458.4 R .793(ysical source lines of code \(SLOC\) ana-)-.05 F 3.262 (lyzed. A)108 470.4 R(ph)3.262 E .763 (ysical SLOC is a non-blank, non-comment line.)-.05 F .763 (It will then sho)5.763 F 3.263(wt)-.25 G .763 (he number of hits at each)-3.263 F(le)108 482.4 Q -.15(ve)-.25 G .242 (l; note that there will ne).15 F -.15(ve)-.25 G 2.742(rb).15 G 2.742 (eah)-2.742 G .241(it at a le)-2.742 F -.15(ve)-.25 G 2.741(ll).15 G -.25(ow)-2.741 G .241(er than minle).25 F -.15(ve)-.25 G 2.741(l\().15 G 2.741(1b)-2.741 G 2.741(yd)-2.741 G(ef)-2.741 E 2.741 (ault\). Thus, "[0])-.1 F 2.741(0[)7.741 G 5.241(1] 9")-2.741 F .364 (means that at le)108 494.4 R -.15(ve)-.25 G 2.864(l0t).15 G .364 (here were 0 hits reported, and at le)-2.864 F -.15(ve)-.25 G 2.864(l1t) .15 G .364(here were 9 hits reported.)-2.864 F .364(It will ne)5.364 F .365(xt sho)-.15 F(w)-.25 E .251(the number of hits at a gi)108 506.4 R -.15(ve)-.25 G 2.751(nl).15 G -2.15 -.25(ev e)-2.751 H 2.751(lo).25 G 2.751(rl)-2.751 G(ar)-2.751 E .251(ger \(so le)-.18 F -.15(ve)-.25 G 2.75(l3).15 G 2.75(+h)-2.75 G .25 (as the sum of the number of hits at le)-2.75 F -.15(ve)-.25 G 2.75(l3) .15 G 2.75(,4)-2.75 G 2.75(,a)-2.75 G(nd)-2.75 E 2.784(5\). Thus,)108 518.4 R .284(an entry of "[0+])2.784 F .284(37" sho)5.284 F .284 (ws that at le)-.25 F -.15(ve)-.25 G 2.785(l0o).15 G 2.785(rh)-2.785 G .285(igher there were 37 hits \(the 0+ entry will al)-2.785 F -.1(wa)-.1 G(ys).1 E 1.407(be the same as the "hits" number abo)108 530.4 R -.15 (ve)-.15 G 3.907(\). Hits).15 F 1.406(per KSLOC is ne)3.907 F 1.406 (xt sho)-.15 F 1.406(wn; this is each of the "le)-.25 F -.15(ve)-.25 G 3.906(lo).15 G(r)-3.906 E .34(higher" v)108 542.4 R .34 (alues multiplied by 1000 and di)-.25 F .34(vided by the ph)-.25 F .34 (ysical SLOC.)-.05 F .34(If symlinks were skipped, the count)5.34 F 1.59 (of those is reported.)108 554.4 R 1.589 (If hits were suppressed \(using the "ignore" directi)6.59 F 1.889 -.15 (ve i)-.25 H 4.089(ns).15 G 1.589(ource code comments as)-4.089 F .537 (described abo)108 566.4 R -.15(ve)-.15 G .537 (\), the number suppressed is reported.).15 F .538(The minimum risk le) 5.537 F -.15(ve)-.25 G 3.038(lt).15 G 3.038(ob)-3.038 G 3.038(ei)-3.038 G .538(ncluded in the report)-3.038 F 1.953(is displayed; by def)108 578.4 R 1.953(ault this is 1 \(use \255\255minle)-.1 F -.15(ve)-.25 G 4.452(lt).15 G 4.452(oc)-4.452 G 1.952(hange this\).)-4.452 F 1.952 (The summary ends with important)6.952 F .282(reminders: Not e)108 590.4 R -.15(ve)-.25 G .282(ry hit is necessarily a security vulnerability).15 F 2.783(,a)-.65 G .283(nd there may be other security vulnerabili-) -2.783 F(ties not reported by the tool.)108 602.4 Q(Fla)108 619.2 Q 1.635(w\214nder can easily inte)-.15 F 1.635 (grate into a continuous inte)-.15 F 1.635(gration system.)-.15 F -1.1 (Yo)6.635 G 4.135(um)1.1 G 1.634(ight w)-4.135 F 1.634 (ant to check out the)-.1 F(\255\255error\255le)108 631.2 Q -.15(ve)-.25 G 4.413(lo).15 G 1.914 (ption to help do that, e.g., using \255\255error\255le)-4.413 F -.15 (ve)-.25 G 1.914(l=4 will cause an error to be returned if).15 F<8d61> 108 643.2 Q(w\214nder \214nds a vulnerability of le)-.15 E -.15(ve)-.25 G 2.5(l4o).15 G 2.5(rh)-2.5 G(igher)-2.5 E(.)-.55 E(Fla)108 672 Q (w\214nder is released under the GNU GPL license v)-.15 E (ersion 2 or later \(GPLv2+\).)-.15 E(Fla)108 688.8 Q .047(w\214nder w) -.15 F .046(orks similarly to another program, ITS4, which is not fully\ open source softw)-.1 F .046(are \(as de\214ned in)-.1 F .187 (the Open Source De\214nition\) nor free softw)108 700.8 R .188 (are \(as de\214ned by the Free Softw)-.1 F .188(are F)-.1 F 2.688 (oundation\). The)-.15 F .188(author of)2.688 F(Fla)108 712.8 Q 1.223 (w\214nder has ne)-.15 F -.15(ve)-.25 G 3.723(rs).15 G 1.223(een ITS4') -3.723 F 3.723(ss)-.55 G 1.223(ource code.)-3.723 F(Fla)6.222 E 1.222 (w\214nder is similar in man)-.15 F 3.722(yw)-.15 G 1.222(ays to RA) -3.822 F 1.222(TS, if you are)-1.11 F -.1(fa)108 724.8 S(miliar with RA) .1 E(TS.)-1.11 E(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E (2)207.055 E 0 Cg EP %%Page: 3 3 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E/F1 10.95/Times-Bold@0 SF (BRIEF TUT)72 84 Q(ORIAL)-.197 E F0(Here')108 96 Q 2.748(sab)-.55 G .249 (rief e)-2.748 F .249(xample of ho)-.15 F 2.749<778d>-.25 G -.15(aw) -2.749 G .249(\214nder might be used.).15 F .249(Imagine that you ha) 5.249 F .549 -.15(ve t)-.2 H .249(he C/C++ source code for).15 F .861 (some program named xyzzy \(which you may or may not ha)108 108 R 1.161 -.15(ve w)-.2 H .861(ritten\), and you').15 F .861 (re searching for security)-.5 F .938(vulnerabilities \(so you can \214\ x them before customers encounter the vulnerabilities\).)108 120 R -.15 (Fo)5.938 G 3.438(rt).15 G .938(his tutorial, I')-3.438 F(ll)-.1 E (assume that you')108 132 Q(re using a Unix-lik)-.5 E 2.5(es)-.1 G (ystem, such as Linux, OpenBSD, or MacOS X.)-2.5 E .874 (If the source code is in a subdirectory named xyzzy)108 148.8 R 3.373 (,y)-.65 G .873(ou w)-3.373 F .873(ould probably start by opening a te) -.1 F .873(xt windo)-.15 F(w)-.25 E .161(and using \215a)108 160.8 R (w\214nder')-.15 E 2.662(sd)-.55 G(ef)-2.662 E .162(ault settings, to a\ nalyze the program and report a prioritized list of potential secu-)-.1 F(rity vulnerabilities \(the `)108 172.8 Q(`less')-.74 E 2.5('j)-.74 G (ust mak)-2.5 E(es sure the results stay on the screen\):)-.1 E<8d61>144 184.8 Q(w\214nder xyzzy | less)-.15 E .616 (At this point, you will see a lar)108 213.6 R .616 (ge number of entries.)-.18 F .615 (Each entry has a \214lename, a colon, a line number)5.616 F 3.115(,a) -.4 G .385(risk le)108 225.6 R -.15(ve)-.25 G 2.885(li).15 G 2.885(nb) -2.885 G(rack)-2.885 E .385(ets \(where 5 is the most risk)-.1 F .385 (y\), a cate)-.15 F(gory)-.15 E 2.885(,t)-.65 G .385 (he name of the function, and a description of)-2.885 F(wh)108 237.6 Q 2.782<798d>-.05 G -.15(aw)-2.782 G .282 (\214nder thinks the line is a vulnerability).15 F 5.281(.F)-.65 G(la) -5.281 E .281(w\214nder normally sorts by risk le)-.15 F -.15(ve)-.25 G .281(l, sho).15 F .281(wing the riski-)-.25 F .07 (est items \214rst; if you ha)108 249.6 R .37 -.15(ve l)-.2 H .07 (imited time, it').15 F 2.57(sp)-.55 G .071(robably best to start w) -2.57 F .071(orking on the riskiest items and continue)-.1 F .625 (until you run out of time.)108 261.6 R .625(If you w)5.625 F .625 (ant to limit the display to risks with only a certain risk le)-.1 F -.15(ve)-.25 G 3.125(lo).15 G 3.125(rh)-3.125 G(igher)-3.125 E(,)-.4 E 1.098(use the \255\255minle)108 273.6 R -.15(ve)-.25 G 3.598(lo).15 G 3.598(ption. If)-3.598 F(you')3.598 E 1.099(re getting an e)-.5 F 1.099 (xtraordinary number of f)-.15 F 1.099(alse positi)-.1 F -.15(ve)-.25 G 3.599(sb).15 G 1.099(ecause v)-3.599 F(ariable)-.25 E .673 (names look lik)108 285.6 R 3.173(ed)-.1 G .672 (angerous function names, use the \255F option to remo)-3.173 F .972 -.15(ve r)-.15 H .672(eports about them.).15 F .672(If you don')5.672 F (t)-.18 E 3.283 (understand the error message, please see documents such as the)108 297.6 R/F2 10/Times-Italic@0 SF(Secur)6.113 E 5.783(eP)-.37 G -1.7 -.45 (ro g)-5.783 H -.15(ra).45 G 3.283(mming HO).15 F(WT)-.5 E(O)-.18 E F0 (at)6.054 E(https://dwheeler)108 309.6 Q(.com/secure-programs which pro) -.55 E(vides more information on writing secure programs.)-.15 E .722 (Once you identify the problem and understand it, you can \214x it.)108 326.4 R .721(Occasionally you may w)5.722 F .721(ant to re-do the)-.1 F .545(analysis, both because the line numbers will change)108 338.4 R F2 (and)3.045 E F0 .545(to mak)3.045 F 3.045(es)-.1 G .546(ure that the ne) -3.045 F 3.046(wc)-.25 G .546(ode doesn')-3.046 F 3.046(ti)-.18 G (ntroduce)-3.046 E(yet a dif)108 350.4 Q(ferent vulnerability)-.25 E(.) -.65 E .516(If you')108 367.2 R .816 -.15(ve d)-.5 H .516 (etermined that some line isn').15 F 3.016(tr)-.18 G .516 (eally a problem, and you')-3.016 F .516 (re sure of it, you can insert just before)-.5 F(or on the of)108 379.2 Q(fending line a comment lik)-.25 E(e)-.1 E(/* Fla)146.5 391.2 Q (w\214nder: ignore */)-.15 E(to k)108 403.2 Q(eep them from sho)-.1 E (wing up in the output.)-.25 E .397(Once you')108 420 R .697 -.15(ve d) -.5 H .397(one that, you should go back and search for the program').15 F 2.898(si)-.55 G .398(nputs, to mak)-2.898 F 2.898(es)-.1 G .398 (ure that the pro-)-2.898 F .294(gram strongly \214lters an)108 432 R 2.793(yo)-.15 G 2.793(fi)-2.793 G .293(ts untrusted inputs.)-2.793 F (Fla)5.293 E .293(w\214nder can identify man)-.15 F 2.793(yp)-.15 G .293 (rogram inputs by using the)-2.793 F(\255\255inputs option, lik)108 444 Q 2.5(et)-.1 G(his:)-2.5 E<8d61>144 456 Q (w\214nder \255\255inputs xyzzy)-.15 E(Fla)108 472.8 Q .427 (w\214nder can inte)-.15 F .427(grate well with te)-.15 F .428 (xt editors and inte)-.15 F .428(grated de)-.15 F -.15(ve)-.25 G .428 (lopment en).15 F .428(vironments; see the e)-.4 F(xamples)-.15 E (for more information.)108 484.8 Q(Fla)108 501.6 Q .574 (w\214nder includes man)-.15 F 3.074(yo)-.15 G .574 (ther options, including ones to create HTML v)-3.074 F .574 (ersions of the output \(useful for)-.15 F .142 (prettier displays\) and O)108 513.6 R .142 (ASIS Static Analysis Results Interchange F)-.35 F .142 (ormat \(SARIF\) output.)-.15 F .143(The ne)5.143 F .143(xt section)-.15 F(describes those options in more detail.)108 525.6 Q F1(OPTIONS)72 554.4 Q F0(Fla)108 566.4 Q .187(w\214nder has a number of options, whic\ h can be grouped into options that control its o)-.15 F .186 (wn documentation,)-.25 F 1.272 (select input data, select which hits to display)108 578.4 R 3.772(,s) -.65 G 1.272(elect the output format, and perform hitlist management.) -3.772 F .692(The commonly-used \215a)108 590.4 R .691(w\214nder option\ s support the standard option syntax de\214ned in the POSIX \(Issue 7,) -.15 F .118(2013 Edition\) section `)108 602.4 R .118(`Utility Con)-.74 F -.15(ve)-.4 G(ntions').15 E 2.618('. Fla)-.74 F .119 (w\214nder also supports the GNU long options \(double-dash)-.15 F .128 (options of form \255\255)108 614.4 R F2(option)A F0 2.628(\)a)C 2.628 (sd)-2.628 G .128(e\214ned in the)-2.628 F F2 .128(GNU C Libr)2.628 F .128(ary Refer)-.15 F .128(ence Manual)-.37 F F0 -.74(``)2.628 G .128 (Program Ar).74 F .128(gument Syntax)-.18 F(Con)108 626.4 Q -.15(ve)-.4 G(ntions').15 E 3.002('a)-.74 G(nd)-3.002 E F2 .502(GNU Coding Standar) 3.002 F(ds)-.37 E F0 -.74(``)3.002 G .503 (Standards for Command Line Interf).74 F(aces')-.1 E 3.003('. Long)-.74 F .503(option ar)3.003 F(gu-)-.18 E .457(ments can be pro)108 638.4 R .457(vided as `)-.15 F(`--name=v)-.74 E(alue')-.25 E 2.957('o)-.74 G 2.957(r`)-2.957 G .457(`-name v)-3.697 F(alue')-.25 E 2.957('. All)-.74 F .457(options can be accessed using the more)2.957 F .228 (readable GNU long option con)108 650.4 R -.15(ve)-.4 G .229 (ntions; some less commonly used options can).15 F F2(only)2.729 E F0 .229(be accessed using long)2.729 F(option con)108 662.4 Q -.15(ve)-.4 G (ntions.).15 E/F3 10/Times-Bold@0 SF(Documentation)87 691.2 Q (\255\255help)108 703.2 Q F0(Fla)72 768 Q 166.375(w\214nder 3)-.15 F (Jun 2021)2.5 E(3)207.055 E 0 Cg EP %%Page: 4 4 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E/F1 10/Times-Bold@0 SF108 84 Q F0(Sho)48.74 E 2.5(wu)-.25 G(sage \(help\) information.)-2.5 E F1 108 112.8 Q(ersion)-.1 E F0(Sho)17.59 E(ws \(just\) the v)-.25 E (ersion number and e)-.15 E(xits.)-.15 E F1(\255\255listrules)108 141.6 Q F0 2.075(List the terms \(tok)14.71 F 2.075 (ens\) that trigger further e)-.1 F 2.075(xamination, their def)-.15 F 2.074(ault risk le)-.1 F -.15(ve)-.25 G 2.074(l, and the).15 F(def)168 153.6 Q .03(ault w)-.1 F .03(arning \(including the CWE identi\214er\(s\ \), if applicable\), all tab-separated.)-.1 F .03(The terms)5.03 F .067 (are primarily names of potentially-dangerous functions.)168 165.6 R .066(Note that the reported risk le)5.067 F -.15(ve)-.25 G 2.566(la).15 G(nd)-2.566 E -.1(wa)168 177.6 S (rning for some speci\214c code may be dif).1 E(ferent than the def)-.25 E(ault, depending on ho)-.1 E 2.5(wt)-.25 G(he term)-2.5 E 1.304 (is used.)168 189.6 R 1.304(Combine with \255D if you do not w)6.304 F 1.304(ant the usual header)-.1 F 6.304(.F)-.55 G(la)-6.304 E 1.304 (w\214nder v)-.15 F 1.304(ersion 1.29)-.15 F (changed the separator from spaces to tabs, and added the def)168 201.6 Q(ault w)-.1 E(arning \214eld.)-.1 E F1(Selecting Input Data)87 230.4 Q (\255\255allo)108 242.4 Q(wlink)-.1 E F0(Allo)9.24 E 2.673(wt)-.25 G .173(he use of symbolic links; normally symbolic links are skipped.) -2.673 F(Don')5.174 E 2.674(tu)-.18 G .174(se this option)-2.674 F .355 (if you')168 254.4 R .355(re analyzing code by others; attack)-.5 F .355 (ers could do man)-.1 F 2.855(yt)-.15 G .354 (hings to cause problems for an)-2.855 F 1.083 (analysis with this option enabled.)168 266.4 R -.15(Fo)6.084 G 3.584 (re).15 G 1.084(xample, an attack)-3.734 F 1.084 (er could insert symbolic links to)-.1 F .326(\214les such as /etc/pass\ wd \(leaking information about the \214le\) or create a circular loop, \ which)168 278.4 R -.1(wo)168 290.4 S .428(uld cause \215a).1 F .428 (w\214nder to run `)-.15 F(`fore)-.74 E -.15(ve)-.25 G(r').15 E 2.928 ('. Another)-.74 F .429(problem with enabling this option is that)2.928 F .542(if the same \214le is referenced multiple times using symbolic l\ inks, it will be analyzed multi-)168 302.4 R 1.525 (ple times \(and thus reported multiple times\).)168 314.4 R 1.525 (Note that \215a)6.525 F 1.525(w\214nder already includes some)-.15 F 2.957(protection ag)168 326.4 R 2.957 (ainst symbolic links to special \214le types such as de)-.05 F 2.957 (vice \214le types \(e.g.,)-.25 F(/de)168 338.4 Q 1.218 (v/zero or C:\\mystuf)-.25 F 3.718(f\\com1\). Note)-.25 F 1.218 (that for \215a)3.718 F 1.218(w\214nder v)-.15 F 1.219 (ersion 1.01 and before, this w)-.15 F(as)-.1 E(the def)168 350.4 Q (ault.)-.1 E F1108 379.2 Q(ollo)-.25 E(wdotdir)-.1 E F0 .57 (Enter directories whose names be)168 391.2 R .57(gin with ".".)-.15 F .57(Normally such directories are ignored, since)5.57 F(the)168 403.2 Q 4.016(yn)-.15 G 1.516(ormally include v)-4.016 F 1.516 (ersion control pri)-.15 F -.25(va)-.25 G 1.516 (te data \(such as .git/ or .svn/\), b).25 F 1.517(uild metadata)-.2 F (\(such as .mak)168 415.2 Q (epp\), con\214guration information, and so on.)-.1 E F1(\255\255nolink) 108 444 Q F0 5.297(Ignored. Historically)21.36 F 2.797 (this disabled follo)5.297 F 2.796(wing symbolic links; this beha)-.25 F 2.796(vior is no)-.2 F 5.296(wt)-.25 G(he)-5.296 E(def)168 456 Q(ault.) -.1 E F1(\255\255patch=)108 484.8 Q/F2 10/Times-Italic@0 SF(patc)A (h\214le)-.15 E F1108 501.6 Q F2(patc)2.5 E(h\214le)-.15 E F0 .227 (Examine the selected \214les or directories, b)11.4 F .228 (ut only report hits in lines that are added or modi-)-.2 F .568 (\214ed as described in the gi)168 513.6 R -.15(ve)-.25 G 3.068(np).15 G .568(atch \214le.)-3.068 F .567 (The patch \214le must be in a recognized uni\214ed dif)5.568 F(f)-.25 E 2.293(format \(e.g., the output of GNU "dif)168 525.6 R 4.793(f-)-.25 G 4.793(uo)-4.793 G 2.293(ld ne)-4.793 F 2.293(w", "svn dif)-.25 F 2.294 (f", or "git dif)-.25 F 4.794(f[)-.25 G(commit]"\).)-4.794 E(Fla)168 537.6 Q .833(w\214nder assumes that the patch has already been applied \ to the \214les.)-.15 F .832(The patch \214le can)5.832 F 1.767 (also include changes to irrele)168 549.6 R -.25(va)-.25 G 1.767 (nt \214les \(the).25 F 4.267(yw)-.15 G 1.767(ill simply be ignored\).) -4.267 F 1.767(The line numbers)6.767 F(gi)168 561.6 Q -.15(ve)-.25 G 2.732(ni).15 G 2.732(nt)-2.732 G .231(he patch \214le are used to deter\ mine which lines were changed, so if you ha)-2.732 F .531 -.15(ve m)-.2 H(odi-).15 E .497(\214ed the \214les since the patch \214le w)168 573.6 R .497(as created, re)-.1 F .498(generate the patch \214le \214rst.)-.15 F(Be)5.498 E -.1(wa)-.25 G .498(re that the).1 F .398 (\214le names of the ne)168 585.6 R 2.898<778c>-.25 G .397(les gi)-2.898 F -.15(ve)-.25 G 2.897(ni).15 G 2.897(nt)-2.897 G .397 (he patch \214le must match e)-2.897 F(xactly)-.15 E 2.897(,i)-.65 G .397(ncluding upper/lo)-2.897 F(wer)-.25 E .044 (case, path pre\214x, and directory separator \(\\ vs. /\).)168 597.6 R .045(Only uni\214ed dif)5.045 F 2.545(ff)-.25 G .045 (ormat is accepted \(GNU)-2.545 F(dif)168 609.6 Q .54(f, svn dif)-.25 F .54(f, and git dif)-.25 F 3.04(fo)-.25 G .54(utput is okay\); if you ha) -3.04 F .84 -.15(ve a d)-.2 H(if).15 E .54(ferent format, ag)-.25 F .54 (ain re)-.05 F .54(generate it)-.15 F 2.685(\214rst. Only)168 621.6 R .185(hits that occur on resultant changed lines, or immediately abo) 2.685 F .485 -.15(ve a)-.15 H .185(nd belo).15 F 2.685(wt)-.25 G(hem,) -2.685 E .044(are reported.)168 633.6 R .043 (This option implies \255\255ne)5.043 F -.15(ve)-.25 G(rignore.).15 E F1 -.65(Wa)5.043 G -.15(rn).65 G(ing).15 E F0 2.543(:D)C(o)-2.543 E F2(not) 2.543 E F0 .043(pass a patch \214le without)2.543 F(the)168 645.6 Q F1 2.527 E F0 2.527(,b)C .027(ecause \215a)-2.527 F .027 (w\214nder will then try to treat the \214le as a source \214le.)-.15 F .028(This will often w)5.028 F(ork,)-.1 E -.2(bu)168 657.6 S 3.349(tt).2 G .849(he line numbers will be relati)-3.349 F 1.149 -.15(ve t)-.25 H 3.349(ot).15 G .849(he be)-3.349 F .849 (ginning of the patch \214le, not the positions in)-.15 F .162 (the source code.)168 669.6 R .162(Note that you)5.162 F F1(must)2.662 E F0 .162(also pro)2.662 F .163 (vide the actual \214les to analyze, and not just the)-.15 F .423 (patch \214le; when using)168 681.6 R F12.923 E F0 .423 (\214les are only reported if the)2.923 F 2.923(ya)-.15 G .422 (re both listed in the patch and also)-2.923 F (listed \(directly or indirectly\) in the list of \214les to analyze.) 168 693.6 Q(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(4) 207.055 E 0 Cg EP %%Page: 5 5 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E/F1 10/Times-Bold@0 SF (Selecting Hits to Display)87 84 Q(\255\255inputs)108 96 Q108 112.8 Q F0(Sho)26.41 E 2.5(wo)-.25 G(nly functions that obtain data fro\ m outside the program; this also sets minle)-2.5 E -.15(ve)-.25 G 2.5 (lt).15 G 2.5(o0)-2.5 G(.)-2.5 E F1(\255\255minle)108 141.6 Q -.1(ve) -.15 G(l=).1 E/F2 10/Times-Italic@0 SF(X)A F1(-m)108 158.4 Q F2(X)2.5 E F0 .499(Set minimum risk le)15.73 F -.15(ve)-.25 G 2.999(lt).15 G 2.999 (oXf)-2.999 G .499(or inclusion in hitlist.)-2.999 F .499 (This can be from 0 \(`)5.499 F .499(`no risk')-.74 F .499('\) to 5 \(`) -.74 F(`maxi-)-.74 E(mum risk')144 170.4 Q('\); the def)-.74 E (ault is 1.)-.1 E F1(\255\255falsepositi)108 199.2 Q -.1(ve)-.1 G 108 216 Q F0 .438(Do not include hits that are lik)24.19 F .438 (ely to be f)-.1 F .437(alse positi)-.1 F -.15(ve)-.25 G 2.937 (s. Currently).15 F 2.937(,t)-.65 G .437(his means that function names) -2.937 F .991(are ignored if the)144 228 R(y')-.15 E .991(re not follo) -.5 F .991(wed by "\(", and that declarations of character arrays aren') -.25 F 3.492(tn)-.18 G(oted.)-3.492 E .466(Thus, if you ha)144 240 R .766 -.15(ve u)-.2 H .466(se a v).15 F .466(ariable named "access" e) -.25 F -.15(ve)-.25 G .466 (rywhere, this will eliminate references to this).15 F 1.838(ordinary v) 144 252 R 4.338(ariable. This)-.25 F(isn')4.338 E 4.338(tt)-.18 G 1.838 (he def)-4.338 F 1.839(ault, because this also increases the lik)-.1 F 1.839(elihood of missing)-.1 F .367(important hits; in particular)144 264 R 2.867(,f)-.4 G .367 (unction names in #de\214ne clauses and calls through function pointers) -2.867 F(will be missed.)144 276 Q F1108 304.8 Q -.1(ve)-.15 G (rignor).1 E(e)-.18 E(-n)108 321.6 Q F0(Ne)27.11 E -.15(ve)-.25 G 2.5 (ri).15 G(gnore security issues, e)-2.5 E -.15(ve)-.25 G 2.5(ni).15 G 2.5(ft)-2.5 G(he)-2.5 E 2.5(yh)-.15 G -2.25 -.2(av e)-2.5 H(an `)2.7 E (`ignore')-.74 E 2.5('d)-.74 G(irecti)-2.5 E .3 -.15(ve i)-.25 H 2.5 (nac).15 G(omment.)-2.5 E F1108 350.4 Q(egexp=)-.18 E F2 -1.07 -.9(PA T)D(TERN).9 E F1(-e)108 367.2 Q F2 -1.07 -.9(PA T)2.5 H(TERN).9 E F0 .412(Only report hits with te)144 379.2 R .412 (xt that matches the re)-.15 F .412(gular e)-.15 F .412 (xpression pattern P)-.15 F -1.11(AT)-.92 G 2.912(TERN. F)1.11 F .413 (or e)-.15 F .413(xample, to)-.15 F 1.754 (only report hits containing the te)144 391.2 R 1.753 (xt "CWE-120", use `)-.15 F<60adad7265>-.74 E(ge)-.15 E 4.253(xC)-.15 G (WE-120')-4.253 E 4.253('. These)-.74 F 1.753(option \215ag)4.253 F (names are the same as grep.)144 403.2 Q F1(Selecting Output F)87 444 Q (ormat)-.25 E(\255\255columns)108 456 Q108 472.8 Q F0(Sho)47.08 E 4.023(wt)-.25 G 1.524(he column number \(as well as the \214le name and\ line number\) of each hit; this is)-4.023 F(sho)168 484.8 Q .609(wn af\ ter the line number by adding a colon and the column number in the line\ \(the \214rst)-.25 F .561(character in a line is column number 1\).)168 496.8 R .562(This is useful for editors that can jump to speci\214c) 5.562 F 1.375(columns, or for inte)168 508.8 R 1.375 (grating with other tools \(such as those to further \214lter out f)-.15 F 1.374(alse posi-)-.1 F(ti)168 520.8 Q -.15(ve)-.25 G(s\).).15 E F1 (\255\255context)108 549.6 Q108 566.4 Q F0(Sho)49.86 E 4.249(wc) -.25 G(onte)-4.249 E 1.749(xt, i.e., the line ha)-.15 F 1.749 (ving the "hit"/potential \215a)-.2 F 5.549 -.65(w. B)-.15 H 4.249(yd) .65 G(ef)-4.249 E 1.75(ault the line is sho)-.1 F(wn)-.25 E (immediately after the w)168 578.4 Q(arning.)-.1 E F1108 607.2 Q F0 .455(Generate output in comma-separated-v)35.27 F .455 (alue \(CSV\) format.)-.25 F .455(This is the recommended format)5.455 F .023(for sending to other tools for processing.)168 619.2 R .023 (It will al)5.023 F -.1(wa)-.1 G .023(ys generate a header ro).1 F 1.323 -.65(w, f)-.25 H(ollo).65 E .024(wed by 0)-.25 F .858(or more data ro) 168 631.2 R .858(ws \(one data ro)-.25 F 3.358(wf)-.25 G .858 (or each hit\).)-3.358 F .858 (Selecting this option automatically enables)5.858 F 1.313 (\255\255quiet and \255\255dataonly)168 643.2 R 6.313(.T)-.65 G 1.314 (he headers are mostly self-e)-6.313 F(xplanatory)-.15 E 6.314(.")-.65 G 1.314(File" is the \214lename,)-6.314 F .165("Line" is the line number) 168 655.2 R 2.665(,")-.4 G .164 (Column" is the column \(starting from 1\), "Le)-2.665 F -.15(ve)-.25 G .164(l" is the risk le).15 F -.15(ve)-.25 G(l).15 E .419 (\(0-5, 5 is riskiest\), "Cate)168 667.2 R .419 (gory" is the general \215a)-.15 F .419(w\214nder cate)-.15 F(gory)-.15 E 2.919(,")-.65 G .42(Name" is the name of the)-2.919 F 1.253 (triggering rule, "W)168 679.2 R 1.253(arning" is te)-.8 F 1.253(xt e) -.15 F 1.253(xplaining wh)-.15 F 3.753(yi)-.05 G 3.753(ti)-3.753 G 3.753 (sah)-3.753 G 1.253(it \(\214nding\), "Suggestion" is te)-3.753 F(xt) -.15 E .99(suggesting ho)168 691.2 R 3.49(wi)-.25 G 3.49(tm)-3.49 G .99 (ight be \214x)-3.49 F .99(ed, "Note" is other e)-.15 F .99 (xplanatory notes, "CWEs" is the list of)-.15 F .336 (one or more CWEs, "Conte)168 703.2 R .335 (xt" is the source code line triggering the hit, and "Fingerprint" is) -.15 F .046(the SHA-256 hash of the conte)168 715.2 R .047 (xt once its leading and trailing whitespace ha)-.15 F .347 -.15(ve b) -.2 H .047(een remo).15 F -.15(ve)-.15 G(d).15 E 1.055(\(the \214ngerpr\ int may help detect and eliminate later duplications\).)168 727.2 R 1.054(If you use Python3, the)6.054 F(Fla)72 768 Q 166.375(w\214nder 3) -.15 F(Jun 2021)2.5 E(5)207.055 E 0 Cg EP %%Page: 6 6 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E(hash is of the conte)168 84 Q (xt when encoded as UTF-8.)-.15 E/F1 10/Times-Bold@0 SF (\255\255dataonly)108 112.8 Q108 129.6 Q F0(Don')47.08 E 2.5(td) -.18 G(isplay the header and footer)-2.5 E 5(.U)-.55 G (se this along with \255\255quiet to see just the data itself.)-5 E F1 (\255\255html)108 158.4 Q108 175.2 Q F0 -.15(Fo)46.52 G (rmat the output as HTML instead of as simple te).15 E(xt.)-.15 E F1 (\255\255immediate)108 204 Q(-i)108 220.8 Q F0 (Immediately display hits \(don')53.89 E 2.5(tj)-.18 G(ust w)-2.5 E (ait until the end\).)-.1 E F1(\255\255sarif)108 261.6 Q F0 .21 (Produce output in the O)29.16 F .211 (ASIS Static Analysis Results Interchange F)-.35 F .211 (ormat \(SARIF\) format \(a)-.15 F 1.72(JSON-based format\).)168 273.6 R 1.719(The goals of the SARIF format, as e)6.72 F 1.719(xplained in v) -.15 F 1.719(ersion 2.1.0 \(27)-.15 F .815(March 2020\) of its speci\ \214cation, include being able to "comprehensi)168 285.6 R -.15(ve)-.25 G .815(ly capture the range).15 F .46 (of data produced by commonly used static analysis tools.")168 297.6 R .46(SARIF output identi\214es the tool)5.46 F 1.399(name as "Fla)168 309.6 R 3.899(w\214nder". The)-.15 F<8d61>3.899 E 1.399(w\214nder le) -.15 F -.15(ve)-.25 G 1.399 (ls 0 through 5 are mapped to SARIF rank \(by).15 F(di)168 321.6 Q (viding by 5\), SARIF le)-.25 E -.15(ve)-.25 G(l, and the def).15 E (ault vie)-.1 E(wer action as follo)-.25 E(ws:)-.25 E(Fla)168 345.6 Q (w\214nder 0: SARIF rank 0.0, SARIF le)-.15 E -.15(ve)-.25 G 2.5(ln).15 G(ote, Does not display by def)-2.5 E(ault)-.1 E(Fla)168 369.6 Q (w\214nder 1: SARIF rank 0.2, SARIF le)-.15 E -.15(ve)-.25 G 2.5(ln).15 G(ote, Does not display by def)-2.5 E(ault)-.1 E(Fla)168 393.6 Q (w\214nder 2: SARIF rank 0.4, SARIF le)-.15 E -.15(ve)-.25 G 2.5(ln).15 G(ote, Does not display by def)-2.5 E(ault)-.1 E(Fla)168 417.6 Q 1.261 (w\214nder 3: SARIF rank 0.6, SARIF le)-.15 F -.15(ve)-.25 G 3.761(lw) .15 G 1.261(arning, Displays by def)-3.861 F 1.26(ault, does not break) -.1 F -.2(bu)168 429.6 S(ild / other processes).2 E(Fla)168 453.6 Q 1.043(w\214nder 4: SARIF rank 0.8, SARIF le)-.15 F -.15(ve)-.25 G 3.543 (le).15 G(rror)-3.543 E 3.543(,D)-.4 G 1.043(isplays by def)-3.543 F 1.043(ault, breaks b)-.1 F 1.044(uild/ other)-.2 F(processes)168 465.6 Q (Fla)168 489.6 Q 1.043(w\214nder 5: SARIF rank 1.0, SARIF le)-.15 F -.15 (ve)-.25 G 3.543(le).15 G(rror)-3.543 E 3.543(,D)-.4 G 1.043 (isplays by def)-3.543 F 1.043(ault, breaks b)-.1 F 1.043(uild/ other) -.2 F(processes)168 501.6 Q 2.883(Ab)168 525.6 S .383(ig thanks to Y) -2.883 F .383(ong Y)-1.1 F .383 (an implementing SARIF output generation for \215a)-1 F 2.883 (w\214nder! F)-.15 F .384(or more)-.15 F 21.124 (about the SARIF format, see: https://www)168 537.6 R(.oasis-open.or) -.65 E(g/commit-)-.18 E(tees/tc_home.php?wg_abbre)168 549.6 Q(v=sarif) -.25 E F1(\255\255singleline)108 578.4 Q(-S)108 595.2 Q F0 1.267 (Display as single line of te)51.11 F 1.267(xt output for each hit.)-.15 F 1.267(Useful for interacting with compilation)6.267 F(tools.)168 607.2 Q F1(\255\255omittime)108 636 Q F0 .82(Omit timing information.)10.28 F .82(This is useful for re)5.82 F .82(gression tests of \215a)-.15 F .82 (w\214nder itself, so that the)-.15 F(output doesn')168 648 Q 2.5(tv) -.18 G(ary depending on ho)-2.75 E 2.5(wl)-.25 G(ong the analysis tak) -2.5 E(es.)-.1 E F1(\255\255quiet)108 676.8 Q108 693.6 Q F0(Don') 46.52 E 3.152(td)-.18 G .652 (isplay status information \(i.e., which \214les are being e)-3.152 F .653(xamined\) while the analysis is)-.15 F(going on.)168 705.6 Q(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(6)207.055 E 0 Cg EP %%Page: 7 7 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E/F1 10/Times-Bold@0 SF 108 84 Q(or)-.18 E(-le)-.37 E -.1(ve)-.15 G(l=LEVEL).1 E F0 1.48(Return a nonzero \(f)168 96 R 1.48 (alse\) error code if there is at least one hit of LEVEL or higher)-.1 F 6.48(.I)-.55 G 3.98(fa)-6.48 G(dif)168 108 Q .203(fhitlist is pro)-.25 F .203(vided, hits noted in it are ignored.)-.15 F .203 (This option can be useful within a contin-)5.203 F 1.792(uous inte)168 120 R 1.792(gration script, especially if you mark kno)-.15 F 1.792 (wn-okay lines as "\215a)-.25 F 1.791(w\214nder: ignore".)-.15 F 1.232 (Usually you w)168 132 R 1.232(ant le)-.1 F -.15(ve)-.25 G 3.732(lt).15 G 3.732(ob)-3.732 G 3.732(ef)-3.732 G 1.232(airly high, such as 4 or 5.) -3.832 F 1.233(By def)6.233 F 1.233(ault, \215a)-.1 F 1.233 (w\214nder returns 0)-.15 F(\(true\) on a successful run.)168 144 Q F1 (Hitlist Management)87 172.8 Q108 184.8 Q -.1(ve)-.25 G (hitlist=).1 E/F2 10/Times-Italic@0 SF(F)A F0(Sa)168 196.8 Q .3 -.15 (ve a)-.2 H(ll resulting hits \(the "hitlist"\) to F).15 E(.)-.8 E F1 (\255\255loadhitlist=)108 225.6 Q F2(F)A F0 .44 (Load the hitlist from F instead of analyzing source programs.)168 237.6 R -.8(Wa)5.44 G .44(rning: Do).8 F F2(not)2.94 E F0 .44(load hitlists) 2.94 F 2.707(from untrusted sources \(for security reasons\).)168 249.6 R 2.707(These are internally implemented using)7.707 F(Python')168 261.6 Q 3.709(s")-.55 G 1.209(pickle" f)-3.709 F(acility)-.1 E 3.709(,w)-.65 G 1.209(hich trusts the input.)-3.709 F 1.208 (Note that stored hitlists often cannot be)6.208 F 2.652 (read when using an older v)168 273.6 R 2.652 (ersion of Python, in particular)-.15 F 5.152(,i)-.4 G 5.152(fs)-5.152 G -2.25 -.2(av e)-5.152 H 2.652(hitlist w).2 F 2.653(as used b)-.1 F(ut) -.2 E<8d61>168 285.6 Q 1.436(w\214nder w)-.15 F 1.436 (as run using Python 3, the hitlist can')-.1 F 3.936(tb)-.18 G 3.936(el) -3.936 G 1.435(oaded by running \215a)-3.936 F 1.435(w\214nder with)-.15 F(Python 2.)168 297.6 Q F1(\255\255diffhitlist=)108 326.4 Q F2(F)A F0 (Sho)168 338.4 Q 3.539(wo)-.25 G 1.039 (nly hits \(loaded or analyzed\) not in F)-3.539 F 6.039(.F)-.8 G -.1 (wa)-2.5 G 3.54(sp).1 G 1.04(resumably created pre)-3.54 F 1.04 (viously using)-.25 F168 350.4 Q -.15(ve)-.2 G 2.866 (hitlist. W).15 F .366(arning: Do)-.8 F F2(not)2.866 E F0(dif)2.866 E 2.866(fh)-.25 G .366 (itlists from untrusted sources \(for security reasons\).)-2.866 F(If) 5.365 E .668(the \255\255loadhitlist option is not pro)168 362.4 R .668 (vided, this will sho)-.15 F 3.168(wt)-.25 G .668 (he hits in the analyzed source code)-3.168 F .144 (\214les that were not pre)168 374.4 R .144(viously stored in F)-.25 F 5.144(.I)-.8 G 2.644(fu)-5.144 G .144 (sed along with \255\255loadhitlist, this will sho)-2.644 F 2.643(wt) -.25 G(he)-2.643 E .094(hits in the loaded hitlist not in F)168 386.4 R 5.094(.T)-.8 G .094(he dif)-5.094 F .095(ference algorithm is conserv) -.25 F(ati)-.25 E -.15(ve)-.25 G 2.595(;h).15 G .095(its are only con-) -2.595 F .684(sidered the `)168 398.4 R(`same')-.74 E 3.183('i)-.74 G 3.183(ft)-3.183 G(he)-3.183 E 3.183(yh)-.15 G -2.25 -.2(av e)-3.183 H .683(the same \214lename, line number)3.383 F 3.183(,c)-.4 G .683 (olumn position, function)-3.183 F(name, and risk le)168 410.4 Q -.15 (ve)-.25 G(l.).15 E F1(Character Encoding Err)87 439.2 Q(ors)-.18 E F0 (Fla)108 451.2 Q .278 (w\214nder uses the character encoding rules set by Python.)-.15 F .278 (Sometimes source code does not perfectly fol-)5.278 F(lo)108 463.2 Q 3.035(ws)-.25 G .535(ome encoding rules.)-3.035 F .535(If you run \215a) 5.535 F .534 (w\214nder with Python 2 these non-conformities often do not impact)-.15 F(processing in practice.)108 475.2 Q(Ho)108 499.2 Q(we)-.25 E -.15(ve) -.25 G 1.075 -.4(r, i).15 H 2.775(fy).4 G .275(ou run \215a)-2.775 F .275(w\214nder with Python 3, this can be a problem.)-.15 F .276 (Python 3 de)5.276 F -.15(ve)-.25 G .276(lopers w).15 F .276(ants the w) -.1 F(orld)-.1 E .258(to al)108 511.2 R -.1(wa)-.1 G .258 (ys use encodings perfectly correctly).1 F 2.757(,e)-.65 G -.15(ve) -3.007 G .257(rywhere, and in general w).15 F .257(ants e)-.1 F -.15(ve) -.25 G .257(ryone to only use UTF-8.).15 F .175 (UTF-8 is a great encoding, and it is v)108 523.2 R .175(ery popular) -.15 F 2.675(,b)-.4 G .175(ut the w)-2.875 F .175(orld often doesn')-.1 F 2.675(tc)-.18 G .175(are what the Python 3 de)-2.675 F -.15(ve)-.25 G (l-).15 E(opers w)108 535.2 Q(ant.)-.1 E .752(When running \215a)108 559.2 R .751(w\214nder using Python 3, the program will crash hard if) -.15 F F2(any)3.251 E F0 .751(source \214le has)3.251 F F2(any)3.251 E F0(non-con-)3.251 E 1.54(forming te)108 571.2 R 4.04(xt. It)-.15 F 1.54 (will do this e)4.04 F -.15(ve)-.25 G 4.04(ni).15 G 4.04(ft)-4.04 G 1.541(he non-conforming te)-4.04 F 1.541 (xt is in comments or strings \(where it often)-.15 F(doesn')108 583.2 Q 3.225(tm)-.18 G 3.225(atter\). Python)-3.225 F 3.225(3f)3.225 G .725 (ails to pro)-3.325 F .725(vide useful b)-.15 F .724 (uilt-ins to deal with the messiness of the real w)-.2 F .724(orld, so) -.1 F(it')108 595.2 Q 3.936(sn)-.55 G(on-tri)-3.936 E 1.437 (vial to deal with this problem without depending on e)-.25 F 1.437 (xternal libraries \(which we')-.15 F 1.437(re trying to)-.5 F -.2(avo) 108 607.2 S(id\).).2 E 2.5(As)108 631.2 S (ymptom of this problem is if you run \215a)-2.5 E (w\214nder and you see an error message lik)-.15 E 2.5(et)-.1 G(his:) -2.5 E F2(Err)108 655.2 Q(or: encoding err)-.45 E(or in ,1.c)-.45 E ('utf-8' codec can')108 679.2 Q 2.5(td)-.3 G(ecode byte 0xf)-2.5 E 2.5 (fi)-.18 G 2.5(np)-2.5 G(osition 45: in)-2.5 E(valid start byte)-.4 E F0 (What you are seeing is the result of an internal UnicodeDecodeError)108 703.2 Q(.)-.55 E(If this happens to you, there are se)108 727.2 Q -.15 (ve)-.25 G(ral options:).15 E(Fla)72 768 Q 166.375(w\214nder 3)-.15 F (Jun 2021)2.5 E(7)207.055 E 0 Cg EP %%Page: 8 8 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E .346(Option #1 \(special case\ \): if your system normally uses an encoding other than UTF-8, is prope\ rly set up to)108 84 R 1.765(use that encoding \(using LC_ALL and maybe\ LC_CTYPE\), and the input \214les are in that non-UTF-8)108 96 R 1.636 (encoding, it may be that Python3 is \(incorrectly\) ignoring your con\ \214guration.)108 108 R 1.635(In that case, simply tell)6.635 F 3.086 (Python3 to use your con\214guration by setting the en)108 120 R 3.087 (vironment v)-.4 F 3.087(ariable PYTHONUTF8=0, e.g., run)-.25 F<8d61>108 132 Q(w\214nder as: "PYTHONUTF8=0 p)-.15 E(ython3 \215a)-.1 E (w\214nder ...".)-.15 E .311(Option #2 \(special case\): If you kno)108 156 R 2.811(ww)-.25 G .311(hat the encoding of the \214les is, you can \ force use of that encoding.)-2.811 F 3.507 (E.g., if the encoding is BLAH, run \215a)108 168 R 3.508 (w\214nder as: "PYTHONUTF8=0 LC_ALL=C.BLAH p)-.15 F(ython3)-.1 E<8d61> 108 180 Q(w\214nder ...".)-.15 E -1.1(Yo)5 G 2.5(uc)1.1 G(an replace "C\ " after LC_ALL= with your real language locale \(e.g., "en_US"\).)-2.5 E .447(Option #3: If you don')108 204 R 2.946(tk)-.18 G(no)-2.946 E 2.946 (ww)-.25 G .446(hat the encoding is, or the encoding is inconsistent \(\ e.g., the common case)-2.946 F .404 (of UTF-8 \214les with some characters encoded using W)108 216 R(indo) -.4 E .404(ws-1252 instead\), then you can force the system)-.25 F .382 (to use the ISO-8859-1 \(Latin-1\) encoding in which all bytes are allo) 108 228 R 2.882(wed. If)-.25 F .381(the inconsistencies are only in) 2.882 F .441(comments and strings, and the underlying character set is \ "close enough" to ASCII, this can get you going)108 240 R 1.116 (in a hurry)108 252 R 6.116(.Y)-.65 G 1.116 (ou can do this by running: "PYTHONUTF8=0 LC_ALL=C.ISO-8859-1 p)-7.216 F 1.115(ython3 \215a)-.1 F(w\214nder)-.15 E 4.194(...". In)108 264 R 1.694 (some cases you may not need the "PYTHONUTF8=0".)4.194 F -1.1(Yo)6.694 G 4.194(um)1.1 G 1.694(ay be able to replace "C" after)-4.194 F (LC_ALL= with your real language locale \(e.g., "en_US"\).)108 276 Q .018(Option #4: Con)108 300 R -.15(ve)-.4 G .018 (rt the encoding of the \214les to be analyzed so that it').15 F 2.518 (sas)-.55 G .018(ingle encoding - it')-2.518 F 2.518(sh)-.55 G .018 (ighly recom-)-2.518 F .269(mended to con)108 312 R -.15(ve)-.4 G .269 (rt to UTF-8.).15 F -.15(Fo)5.269 G 2.769(re).15 G .269 (xample, the system program "icon)-2.919 F .27 (v" or the Python program cvt2utf can)-.4 F .675(be used to con)108 324 R -.15(ve)-.4 G .674(rt encodings.).15 F(\(Y)5.674 E .674 (ou can install cvt2utf with "pip install cvtutf"\).)-1.1 F .674(This w) 5.674 F .674(orks well if some)-.1 F .101(\214les ha)108 336 R .401 -.15 (ve o)-.2 H .101(ne encoding, and some ha).15 F .401 -.15(ve a)-.2 H (nother).15 E 2.601(,b)-.4 G .101(ut the)-2.801 F 2.601(ya)-.15 G .101 (re consistent within a single \214le.)-2.601 F .101(If the \214les ha) 5.101 F -.15(ve)-.2 G(encoding errors, you')108 348 Q(ll ha)-.1 E .3 -.15(ve t)-.2 H 2.5<6f8c>.15 G 2.5(xt)-2.5 G(hem.)-2.5 E (Option #5: Run \215a)108 372 Q (w\214nder using Python 2 instead of Python 3.)-.15 E(E.g., "p)5 E (ython2 \215a)-.1 E(w\214nder ...".)-.15 E 2.031 -.8(To b)108 396 T 2.931(ec).8 G .431(lear: I strongly recommend using the UTF-8 encoding \ for all source code, and use continuous inte-)-2.931 F .873 (gration tests to ensure that the source code is al)108 408 R -.1(wa)-.1 G .873(ys v).1 F .873(alid UTF-8.)-.25 F .873(If you do that, man)5.873 F 3.373(yp)-.15 G .873(roblems disap-)-3.373 F(pear)108 420 Q 5.715(.B) -.55 G .715(ut in the real w)-5.715 F .715(orld this is not al)-.1 F -.1 (wa)-.1 G .715(ys the situation.).1 F .715 (Hopefully this information will help you deal)5.715 F(with real-w)108 432 Q(orld encoding problems.)-.1 E/F1 10.95/Times-Bold@0 SF(EXAMPLES)72 460.8 Q F0 .225(Here are v)108 472.8 R .225(arious e)-.25 F .225 (xamples of ho)-.15 F 2.725(wt)-.25 G 2.725(oi)-2.725 G -1.9 -.4(nv o) -2.725 H .425 -.1(ke \215).4 H -.15(aw).1 G(\214nder).15 E 5.225(.T)-.55 G .225(he \214rst e)-5.225 F .226(xamples sho)-.15 F 2.726(wv)-.25 G .226(arious simple command-)-2.976 F 1.274(line options.)108 484.8 R (Fla)6.274 E 1.274(w\214nder is designed to w)-.15 F 1.274 (ork well with te)-.1 F 1.273(xt editors and inte)-.15 F 1.273 (grated de)-.15 F -.15(ve)-.25 G 1.273(lopment en).15 F(viron-)-.4 E (ments, so the ne)108 496.8 Q(xt sections sho)-.15 E 2.5(wh)-.25 G .5 -.25(ow t)-2.5 H 2.5(oi).25 G(nte)-2.5 E(grate \215a)-.15 E (w\214nder into vim and emacs.)-.15 E/F2 10/Times-Bold@0 SF (Simple command-line options)87 525.6 Q(\215aw\214nder /usr/sr)108 537.6 Q(c/linux-3.16)-.18 E F0 1.705(Examine all the C/C++ \214les in the dir\ ectory /usr/src/linux-3.16 and all its subdirectories)168 549.6 R (\(recursi)168 561.6 Q -.15(ve)-.25 G .334 (ly\), reporting on all hits found.).15 F .334(By def)5.334 F .334 (ault \215a)-.1 F .334(w\214nder will skip symbolic links and)-.15 F (directories with names that start with a period.)168 573.6 Q F2 (\215aw\214nder \255\255err)108 602.4 Q(or)-.18 E(-le)-.37 E -.1(ve)-.15 G(l=4 .).1 E F0 1.857(Examine all the C/C++ \214les in the current dire\ ctory and its subdirectories \(recursi)168 614.4 R -.15(ve)-.25 G(ly\);) .15 E .829(return an error code if there are vulnerabilities le)168 626.4 R -.15(ve)-.25 G 3.329(l4a).15 G .829(nd up \(the tw)-3.329 F 3.328(oh)-.1 G .828(ighest risk le)-3.328 F -.15(ve)-.25 G(ls\).).15 E (This is a plausible w)168 638.4 Q(ay to use \215a)-.1 E (w\214nder in a continuous inte)-.15 E(gration system.)-.15 E F2 (\215aw\214nder \255\255minle)108 667.2 Q -.1(ve)-.15 G(l=4 .).1 E F0 .154(Examine all the C/C++ \214les in the current directory and its sub\ directories \(recursi)168 679.2 R -.15(ve)-.25 G .154(ly\); only).15 F (report vulnerabilities le)168 691.2 Q -.15(ve)-.25 G 2.5(l4a).15 G (nd up \(the tw)-2.5 E 2.5(oh)-.1 G(ighest risk le)-2.5 E -.15(ve)-.25 G (ls\).).15 E(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(8) 207.055 E 0 Cg EP %%Page: 9 9 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E/F1 10/Times-Bold@0 SF (\215aw\214nder \255\255inputs mydir)108 84 Q F0 1.03(Examine all the C\ /C++ \214les in mydir and its subdirectories \(recursi)168 96 R -.15(ve) -.25 G 1.03(ly\), and report func-).15 F(tions that tak)168 108 Q 2.5 (ei)-.1 G(nputs \(so that you can ensure that the)-2.5 E 2.5<798c>-.15 G (lter the inputs appropriately\).)-2.5 E F1(\215aw\214nder \255\255ne) 108 136.8 Q -.1(ve)-.15 G(rignor).1 E 2.5(em)-.18 G(ydir)-2.5 E F0 .3(E\ xamine all the C/C++ \214les in the directory mydir and its subdirector\ ies, including e)168 148.8 R -.15(ve)-.25 G 2.8(nt).15 G(he)-2.8 E (hits mark)168 160.8 Q(ed for ignoring in the code comments.)-.1 E F1 (\215aw\214nder \255\255csv .)108 189.6 Q F0 .253 (Examine the current directory do)168 201.6 R .253(wn \(recursi)-.25 F -.15(ve)-.25 G .253(ly\), and report all hits in CSV format.).15 F .252 (This is)5.252 F 1.394(the recommended form if you w)168 213.6 R 1.395 (ant to further process \215a)-.1 F 1.395 (w\214nder output using other tools)-.15 F (\(such as data correlation tools\).)168 225.6 Q F1 (\215aw\214nder \255QD mydir)108 254.4 Q F0 .093 (Examine mydir and report only the actual results \(remo)168 266.4 R .092(ving the header and footer of the out-)-.15 F 3.061(put\). This)168 278.4 R .561(form may be useful if the output will be piped into other \ tools for further analy-)3.061 F .341 (sis, though CSV format is probably the better choice in that case.)168 290.4 R .341(The \255C \(\255\255columns\) and)5.341 F (\255S \(\255\255singleline\) options can also be useful if you')168 302.4 Q(re piping the data into other tools.)-.5 E F1 (\215aw\214nder \255QDSC mydir)108 331.2 Q F0 .553(Examine mydir)168 343.2 R 3.053(,r)-.4 G .553 (eporting only the actual results \(no header or footer\).)-3.053 F .554 (Each hit is reported)5.554 F 1.12 (on one line, and column numbers are reported.)168 355.2 R 1.119 (This can be a useful command if you are)6.119 F(feeding \215a)168 367.2 Q(w\214nder output to other tools.)-.15 E F1 (\215aw\214nder \255\255quiet \255\255html \255\255context mydir > r)108 396 Q(esults.html)-.18 E F0 1.185(Examine all the C/C++ \214les in the \ directory mydir and its subdirectories, and produce an)168 408 R .278 (HTML formatted v)168 420 R .278(ersion of the results.)-.15 F .277 (Source code management systems \(such as Source-)5.278 F -.15(Fo)168 432 S -.18(rg).15 G 2.5(ea).18 G(nd Sa)-2.5 E -.25(va)-.2 G (nnah\) might use a command lik).25 E 2.5(et)-.1 G(his.)-2.5 E F1 (\215aw\214nder \255\255quiet \255\255sa)108 460.8 Q -.1(ve)-.25 G (hitlist sa).1 E -.1(ve)-.25 G(d.hits *.[ch]).1 E F0 .406 (Examine all .c and .h \214les in the current directory)168 472.8 R 5.406(.D)-.65 G(on')-5.406 E 2.906(tr)-.18 G .407 (eport on the status of processing,)-2.906 F(and sa)168 484.8 Q .3 -.15 (ve t)-.2 H (he resulting hitlist \(the set of all hits\) in the \214le sa).15 E -.15(ve)-.2 G(d.hits.).15 E F1(\215aw\214nder \255\255diffhitlist sa)108 513.6 Q -.1(ve)-.25 G(d.hits *.[ch]).1 E F0 .325 (Examine all .c and .h \214les in the current directory)168 525.6 R 2.825(,a)-.65 G .325(nd sho)-2.825 F 2.825(wa)-.25 G .624 -.15(ny h) -2.825 H .324(its that weren').15 F 2.824(ta)-.18 G .324(lready in) -2.824 F .92(the \214le sa)168 537.6 R -.15(ve)-.2 G 3.42(d.hits. This) .15 F .921(can be used to sho)3.42 F 3.421(wo)-.25 G .921(nly the `) -3.421 F(`ne)-.74 E(w')-.25 E 3.421('v)-.74 G .921 (ulnerabilities in a modi\214ed)-3.421 F(program, if sa)168 549.6 Q -.15 (ve)-.2 G(d.hits w).15 E(as created from the older v)-.1 E (ersion of the program being analyzed.)-.15 E F1 (\215aw\214nder \255\255patch r)108 578.4 Q(ecent.patch .)-.18 E F0 .642 (Examine the current directory recursi)168 590.4 R -.15(ve)-.25 G(ly).15 E 3.142(,b)-.65 G .641(ut only report lines that were changed or added) -3.342 F(in the already-applied patch\214le named)168 602.4 Q/F2 10 /Times-Italic@0 SF -.37(re)2.5 G(cent.patc).37 E(h)-.15 E F0(.)A F1 (\215aw\214nder \255\255r)108 631.2 Q(egex "CWE-120|CWE-126" sr)-.18 E (c/)-.18 E F0(Examine directory)168 643.2 Q F2(sr)2.5 E(c)-.37 E F0 (recursi)2.5 E -.15(ve)-.25 G(ly).15 E 2.5(,b)-.65 G (ut only report hits where CWE-120 or CWE-126 apply)-2.7 E(.)-.65 E F1 (In)87 672 Q -.1(vo)-.4 G(king fr).1 E(om vim)-.18 E F0 .177(The te)108 684 R .177(xt editor vim includes a "quick\214x" mechanism that w)-.15 F .177(orks well with \215a)-.1 F(w\214nder)-.15 E 2.677(,s)-.4 G 2.677 (ot)-2.677 G .177(hat you can easily)-2.677 F(vie)108 696 Q 2.5(wt)-.25 G(he w)-2.5 E(arning messages and jump to the rele)-.1 E -.25(va)-.25 G (nt source code.).25 E .323(First, you need to in)108 712.8 R -.2(vo)-.4 G .523 -.1(ke \215).2 H -.15(aw).1 G .322 (\214nder to create a list of hits, and there are tw).15 F 2.822(ow)-.1 G .322(ays to do this.)-2.922 F .322(The \214rst w)5.322 F(ay)-.1 E .218 (is to start \215a)108 724.8 R .218 (w\214nder \214rst, and then \(using its output\) in)-.15 F -.2(vo)-.4 G .418 -.1(ke v).2 H 2.718(im. The).1 F .218(second w)2.718 F .218 (ay is to start \(or continue to)-.1 F(Fla)72 768 Q 166.375(w\214nder 3) -.15 F(Jun 2021)2.5 E(9)207.055 E 0 Cg EP %%Page: 10 10 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E(run\) vim, and then in)108 84 Q -.2(vo)-.4 G .2 -.1(ke \215).2 H -.15(aw).1 G (\214nder \(typically from inside vim\).).15 E -.15(Fo)108 100.8 S 3.072 (rt).15 G .572(he \214rst w)-3.072 F(ay)-.1 E 3.072(,r)-.65 G .572 (un \215a)-3.072 F .572(w\214nder and store its output in some FLA)-.15 F .572(WFILE \(say "\215a)-.9 F .571(w\214le"\), then in)-.15 F -.2(vo) -.4 G .771 -.1(ke v).2 H(im).1 E .485(using its -q option, lik)108 112.8 R 2.986(et)-.1 G .486(his: "vim -q \215a)-2.986 F 2.986(w\214le". The) -.15 F .486(second w)2.986 F .486(ay \(starting \215a)-.1 F .486 (w\214nder after starting vim\) can)-.15 F 1.018(be done a le)108 124.8 R 1.018(gion of w)-.15 F 3.518(ays. One)-.1 F 1.018(is to in)3.518 F -.2 (vo)-.4 G 1.217 -.1(ke \215).2 H -.15(aw).1 G 1.017 (\214nder using a shell command, ":!\215a).15 F(w\214nder)-.15 E 1.017 (-command >)-.2 F(FLA)108 136.8 Q .251(WFILE", then follo)-.9 F 2.751 (wt)-.25 G .251(hat with the command ":cf FLA)-2.751 F 2.751 (WFILE". Another)-.9 F -.1(wa)2.751 G 2.752(yi).1 G 2.752(st)-2.752 G 2.752(os)-2.752 G .252(tore the \215a)-2.752 F(w\214nder)-.15 E (command in your mak)108 148.8 Q(e\214le \(as, say)-.1 E 2.5(,ap)-.65 G (seudocommand lik)-2.5 E 2.5(e")-.1 G<8d61>-2.5 E (w"\), and then run ":mak)-.15 E 2.5<658d>-.1 G -.15(aw)-2.5 G(".).15 E .417(In all these cases you need a command for \215a)108 165.6 R .417 (w\214nder to run.)-.15 F 2.917(Ap)5.417 G .417 (lausible command, which places each hit)-2.917 F(in its o)108 177.6 Q (wn line \(-S\) and remo)-.25 E -.15(ve)-.15 G 2.5(sh).15 G (eaders and footers that w)-2.5 E(ould confuse it, is:)-.1 E/F1 10 /Times-Bold@0 SF(\215aw\214nder \255SQD .)108 194.4 Q F0 -1.1(Yo)108 223.2 S 2.96(uc)1.1 G .46(an no)-2.96 F 2.96(wu)-.25 G .46(se v)-2.96 F .46(arious editing commands to vie)-.25 F 2.96(wt)-.25 G .46 (he results.)-2.96 F .46(The command ":cn" displays the ne)5.46 F .46 (xt hit;)-.15 F .012(":cN" displays the pre)108 235.2 R .012 (vious hit, and ":cr" re)-.25 F .012(winds back to the \214rst hit.)-.25 F .011(":copen" will open a windo)5.011 F 2.511(wt)-.25 G 2.511(os) -2.511 G(ho)-2.511 E(w)-.25 E .202 (the current list of hits, called the "quick\214x windo)108 247.2 R .202 (w"; ":cclose" will close the quick\214x windo)-.25 F 4.003 -.65(w. I) -.25 H 2.703(ft).65 G .203(he b)-2.703 F(uf)-.2 E(fer)-.25 E .25 (in the used windo)108 259.2 R 2.75(wh)-.25 G .25(as changed, and the e\ rror is in another \214le, jumping to the error will f)-2.75 F 2.75 (ail. Y)-.1 F .25(ou ha)-1.1 F .55 -.15(ve t)-.2 H(o).15 E(mak)108 271.2 Q 2.587(es)-.1 G .087(ure the windo)-2.587 F 2.587(wc)-.25 G .087 (ontains a b)-2.587 F(uf)-.2 E .088 (fer which can be abandoned before trying to jump to a ne)-.25 F 2.588 <778c>-.25 G .088(le, say by)-2.588 F(sa)108 283.2 Q (ving the \214le; this pre)-.2 E -.15(ve)-.25 G (nts accidental data loss.).15 E F1(In)87 312 Q -.1(vo)-.4 G(king fr).1 E(om emacs)-.18 E F0 .27(The te)108 324 R .269(xt editor / operating sy\ stem emacs includes "grep mode" and "compile mode" mechanisms that w) -.15 F(ork)-.1 E .824(well with \215a)108 336 R(w\214nder)-.15 E 3.324 (,m)-.4 G .824(aking it easy to vie)-3.324 F 3.324(ww)-.25 G .824 (arning messages, jump to the rele)-3.424 F -.25(va)-.25 G .824 (nt source code, and \214x).25 F(an)108 348 Q 2.5(yp)-.15 G (roblems you \214nd.)-2.5 E 1.427(First, you need to in)108 364.8 R -.2 (vo)-.4 G 1.627 -.1(ke \215).2 H -.15(aw).1 G 1.427 (\214nder to create a list of w).15 F 1.427(arning messages.)-.1 F -1.1 (Yo)6.426 G 3.926(uc)1.1 G 1.426(an use "grep mode" or)-3.926 F 2.645 ("compile mode" to create this list.)108 376.8 R 2.645 (Often "grep mode" is more con)7.645 F -.15(ve)-.4 G 2.646 (nient; it lea).15 F -.15(ve)-.2 G 5.146(sc).15 G 2.646(ompile mode) -5.146 F .537(untouched so you can easily recompile once you')108 388.8 R .837 -.15(ve c)-.5 H .537(hanged something.).15 F(Ho)5.537 E(we)-.25 E -.15(ve)-.25 G 1.337 -.4(r, i).15 H 3.037(fy).4 G .537(ou w)-3.037 F .536(ant to jump to)-.1 F .509(the e)108 400.8 R .509 (xact column position of a hit, compile mode may be more con)-.15 F -.15 (ve)-.4 G .51(nient because emacs can use the col-).15 F (umn output of \215a)108 412.8 Q (w\214nder to directly jump to the right location without an)-.15 E 2.5 (ys)-.15 G(pecial con\214guration.)-2.5 E 2.065 -.8(To u)108 429.6 T .465(se grep mode, enter the command "M-x grep" and then enter the need\ ed \215a).8 F .464(w\214nder command.)-.15 F 2.064 -.8(To u)5.464 H(se) .8 E 1.307(compile mode, enter the command "M-x compile" and enter the \ needed \215a)108 441.6 R 1.308(w\214nder command.)-.15 F 1.308 (This is a)6.308 F(meta-k)108 453.6 Q .437 -.15(ey c)-.1 H .137 (ommand, so you').15 F .137(ll need to use the meta k)-.1 F .437 -.15 (ey f)-.1 H .137(or your k).15 F -.15(ey)-.1 G .137 (board \(this is usually the ESC k).15 F -.15(ey)-.1 G 2.636(\). As).15 F 1.015(with all emacs commands, you')108 465.6 R 1.016 (ll need to press RETURN after typing "grep" or "compile".)-.1 F 1.016 (So on man)6.016 F(y)-.15 E(systems, the grep mode is in)108 477.6 Q -.2 (vo)-.4 G -.1(ke).2 G 2.5(db).1 G 2.5(yt)-2.5 G (yping ESC x g r e p RETURN.)-2.5 E -1.1(Yo)108 494.4 S 3.564(ut)1.1 G 1.063(hen need to enter a command, remo)-3.564 F 1.063(ving whate)-.15 F -.15(ve)-.25 G 3.563(rw).15 G 1.063(as there before if necessary)-3.663 F 6.063(.A)-.65 G 1.063(plausible com-)-2.5 F(mand is:)108 506.4 Q F1 (\215aw\214nder \255SQDC .)108 523.2 Q F0 .134(This command mak)108 540 R .134(es e)-.1 F -.15(ve)-.25 G .135 (ry hit report a single line, which is much easier for tools to handle.) .15 F .135(The quiet and)5.135 F .546(dataonly options remo)108 552 R .846 -.15(ve t)-.15 H .546 (he other status information not needed for use inside emacs.).15 F .546 (The trailing period)5.546 F(means that the current directory and all d\ escendents are searched for C/C++ code, and analyzed for \215a)108 564 Q (ws.)-.15 E 1.311(Once you')108 580.8 R 1.611 -.15(ve i)-.5 H -1.9 -.4 (nv o).15 H -.1(ke).4 G 3.811<648d>.1 G -.15(aw)-3.811 G(\214nder).15 E 3.811(,y)-.4 G 1.311(ou can use emacs to jump around in its results.) -3.811 F 1.312(The command C-x \222)6.311 F 1.248 (\(Control-x backtick\) visits the source code location for the ne)108 592.8 R 1.247(xt w)-.15 F 1.247(arning message.)-.1 F 1.247 (C-u C-x \222 \(control-u)6.247 F .807 (control-x backtick\) restarts from the be)108 604.8 R 3.307(ginning. Y) -.15 F .807(ou can visit the source for an)-1.1 F 3.308(yp)-.15 G .808 (articular error message)-3.308 F 1.641(by mo)108 616.8 R 1.641 (ving to that hit message in the *compilation* b)-.15 F(uf)-.2 E 1.64 (fer or *grep* b)-.25 F(uf)-.2 E 1.64(fer and typing the return k)-.25 F -.15(ey)-.1 G(.)-.5 E(\(T)108 628.8 Q 2.852 (echnical note: in the compilation b)-.7 F(uf)-.2 E(fer)-.25 E 5.352(,t) -.4 G 2.852(his in)-5.352 F -.2(vo)-.4 G -.1(ke).2 G 5.352(sc).1 G (ompile-goto-error)-5.352 E 5.352(.\) Y)-.55 F 2.853 (ou can also click the)-1.1 F(Mouse-2 b)108 640.8 Q (utton on the error message \(you don')-.2 E 2.5(tn)-.18 G (eed to switch to the *compilation* b)-2.5 E(uf)-.2 E(fer \214rst\).) -.25 E .238(If you w)108 657.6 R .238 (ant to use grep mode to jump to speci\214c columns of a hit, you')-.1 F .237(ll need to specially con\214gure emacs)-.1 F 1.278(to do this.)108 669.6 R 2.878 -.8(To d)6.278 H 3.779(ot).8 G 1.279 (his, modify the emacs v)-3.779 F 1.279(ariable "grep-re)-.25 F(ge)-.15 E 3.779(xp-alist". This)-.15 F -.25(va)3.779 G 1.279 (riable tells Emacs ho).25 F 3.779(wt)-.25 G(o)-3.779 E .349 (parse output of a "grep" command, similar to the v)108 681.6 R .348 (ariable "compilation-error)-.25 F(-re)-.2 E(ge)-.15 E .348 (xp-alist" which lists v)-.15 F(ari-)-.25 E (ous formats of compilation error messages.)108 693.6 Q(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(10)202.055 E 0 Cg EP %%Page: 11 11 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E/F1 10/Times-Bold@0 SF(In)87 84 Q -.1(vo)-.4 G(king fr).1 E(om Integrated De)-.18 E -.1(ve)-.15 G (lopment En).1 E(vir)-.4 E(onments \(IDEs\))-.18 E F0 -.15(Fo)108 96 S 2.5(r\().15 G(other\) IDEs, consult your IDE')-2.5 E 2.5(ss)-.55 G (et of plug-ins.)-2.5 E/F2 10.95/Times-Bold@0 SF (COMMON WEAKNESS ENUMERA)72 124.8 Q(TION \(CWE\))-1.04 E F0 1.217 (The Common W)108 136.8 R 1.218(eakness Enumeration \(CWE\) is `)-.8 F 1.218(`a formal list or dictionary of common softw)-.74 F 1.218 (are weak-)-.1 F .212(nesses that can occur in softw)108 148.8 R(are') -.1 E 2.711(sa)-.55 G .211 (rchitecture, design, code or implementation that can lead to e)-2.711 F (xploitable)-.15 E 1.185(security vulnerabilities...)108 160.8 R 1.185 (created to serv)6.185 F 3.685(ea)-.15 G 3.685(sac)-3.685 G 1.186 (ommon language for describing softw)-3.685 F 1.186(are security weak-) -.1 F(nesses')108 172.8 Q 2.5('\()-.74 G(https://cwe.mitre.or)-2.5 E (g/about/f)-.18 E 2.5(aq.html\). F)-.1 F (or more information on CWEs, see https://cwe.mitre.or)-.15 E(g.)-.18 E (Fla)108 189.6 Q .423(w\214nder supports the CWE and is of)-.15 F .422 (\214cially CWE-Compatible.)-.25 F .422 (Hit descriptions typically include a rele-)5.422 F -.25(va)108 201.6 S .762(nt Common W).25 F .763(eakness Enumeration \(CWE\) identi\214er in\ parentheses where there is kno)-.8 F .763(wn to be a rele-)-.25 F -.25 (va)108 213.6 S .068(nt CWE.).25 F -.15(Fo)5.068 G 2.568(re).15 G .068 (xample, man)-2.718 F 2.568(yo)-.15 G 2.567(ft)-2.568 G .067(he b)-2.567 F(uf)-.2 E(fer)-.25 E .067 (-related hits mention CWE-120, the CWE identi\214er for `)-.2 F(`b)-.74 E(uf)-.2 E(fer)-.25 E(cop)108 225.6 Q 2.535(yw)-.1 G .036 (ithout checking size of input')-2.535 F 2.536('\()-.74 G .036(aka `) -2.536 F .036(`Classic Buf)-.74 F .036(fer Ov)-.25 F(er\215o)-.15 E(w') -.25 E 2.536('\). In)-.74 F 2.536(af)2.536 G .536 -.25(ew c)-2.536 H .036(ases more than one CWE).25 F .66(identi\214er may be listed.)108 237.6 R .66(The HTML report also includes h)5.66 F(yperte)-.05 E .66 (xt links to the CWE de\214nitions hosted at)-.15 F 2.5(MITRE. In)108 249.6 R(this w)2.5 E(ay)-.1 E 2.5<2c8d>-.65 G -.15(aw)-2.5 G (\214nder is designed to meet the CWE-Output requirement.).15 E .686 (In some cases there are CWE mapping and usage challenges; here is ho) 108 266.4 R 3.186<778d>-.25 G -.15(aw)-3.186 G .686 (\214nder handles them.).15 F .686(If the)5.686 F .394 (same entry maps to multiple CWEs simultaneously)108 278.4 R 2.894(,a) -.65 G .394(ll the CWE mappings are listed as separated by com-)-2.894 F 3.376(mas. This)108 290.4 R .876 (often occurs with CWE-20, Improper Input V)3.376 F .876 (alidation; thus the report "CWE-676, CWE-120")-1.11 F .053(maps to tw) 108 302.4 R 2.553(oC)-.1 G 2.553(WEs. In)-2.553 F .053(addition, \215a) 2.553 F .053(w\214nder pro)-.15 F .052 (vides additional information for those who are are interested)-.15 F .493(in the CWE/SANS top 25 list 2011 \(https://cwe.mitre.or)108 314.4 R .494(g/top25/\) when mappings are not directly to them.)-.18 F(Man)108 326.4 Q 3.595(yp)-.15 G 1.095(eople will w)-3.595 F 1.094(ant to search\ for speci\214c CWEs in this top 25 list, such as CWE-120 \(classic b) -.1 F(uf)-.2 E(fer)-.25 E -.15(ove)108 338.4 S(r\215o).15 E 2.72 (w\). The)-.25 F .22(challenge is that some \215a)2.72 F .221 (w\214nder hits map to a more general CWE that w)-.15 F .221 (ould include a top)-.1 F .155(25 item, while in some other cases hits \ map to a more speci\214c vulnerability that is only a subset of a top 2\ 5)108 350.4 R 3.948(item. T)108 362.4 R 3.948(or)-.8 G(esolv)-3.948 E 3.948(et)-.15 G 1.449(his, in some cases \215a)-3.948 F 1.449 (w\214nder will list a sequence of CWEs in the format "more-gen-)-.15 F 1.797 (eral/more-speci\214c", where the CWE actually being mapped is follo)108 374.4 R 1.797(wed by a "!".)-.25 F 1.796(This is al)6.796 F -.1(wa)-.1 G 1.796(ys done).1 F(whene)108 386.4 Q -.15(ve)-.25 G 3.268(ra\215).15 G 1.068 -.15(aw i)-3.268 H 3.268(sn).15 G .768 (ot mapped directly to a top 25 CWE, b)-3.268 F .768 (ut the mapping is related to such a CWE.)-.2 F(So)5.769 E .356("CWE-11\ 9!/CWE-120" means that the vulnerability is mapped to CWE-119 and that \ CWE-120 is a subset)108 398.4 R .833(of CWE-119.)108 410.4 R .833(In co\ ntrast, "CWE-362/CWE-367!" means that the hit is mapped to CWE-367, a s\ ubset of)5.833 F 2.579(CWE-362. Note)108 422.4 R .078 (that this is a subtle syntax change from \215a)2.579 F .078 (w\214nder v)-.15 F .078(ersion 1.31; in \215a)-.15 F .078(w\214nder v) -.15 F .078(ersion 1.31,)-.15 F 1.241 (the form "more-general:more-speci\214c" meant what is no)108 434.4 R 3.741(wl)-.25 G 1.241(isted as "more-general!/more-speci\214c", while) -3.741 F .007 ("more-general/more-speci\214c" meant "more-general/more-speci\214c!".) 108 446.4 R -.8(To)5.007 G .007(ols can handle both the v).8 F .006 (ersion 1.31)-.15 F .688(and the current format, if the)108 458.4 R 3.188(yw)-.15 G .688(ish, by noting that the older format did not use "\ !" at all \(and thus this is)-3.188 F(easy to distinguish\).)108 470.4 Q (These mapping mechanisms simplify searching for certain CWEs.)5 E .771 (CWE v)108 487.2 R .771(ersion 2.7 \(released June 23, 2014\) w)-.15 F .771(as used for the mapping.)-.1 F .77(The current CWE mappings select) 5.77 F .213(the most speci\214c CWE the tool can determine.)108 499.2 R .213(In theory)5.213 F 2.713(,m)-.65 G .213 (ost CWE security elements \(signatures/patterns)-2.713 F .268(that the\ tool searches for\) could theoretically be mapped to CWE-676 \(Use of \ Potentially Dangerous Func-)108 511.2 R 1.016(tion\), b)108 523.2 R 1.017(ut such a mapping w)-.2 F 1.017(ould not be useful.)-.1 F 1.017 (Thus, more speci\214c mappings were preferred where one)6.017 F .52 (could be found.)108 535.2 R(Fla)5.52 E .52(w\214nder is a le)-.15 F .52 (xical analysis tool; as a result, it is impractical for it to be more \ speci\214c)-.15 F .966(than the mappings currently implemented.)108 547.2 R .966(This also means that it is unlik)5.966 F .967 (ely to need much updating for)-.1 F 1.689(map currenc)108 559.2 R 1.689 (y; it simply doesn')-.15 F 4.189(th)-.18 G -2.25 -.2(av e)-4.189 H 1.689(enough information to re\214ne to a detailed CWE le)4.389 F -.15 (ve)-.25 G 4.188(lt).15 G 1.688(hat CWE)-4.188 F 1.96(changes w)108 571.2 R 1.96(ould typically af)-.1 F 4.46(fect. The)-.25 F 1.96 (list of CWE identi\214ers w)4.46 F 1.96 (as generated automatically using "mak)-.1 F(e)-.1 E(sho)108 583.2 Q .104(w-cwes", so there is con\214dence that this list is correct.)-.25 F .103(Please report CWE mapping problems as b)5.103 F .103(ugs if)-.2 F (you \214nd an)108 595.2 Q -.65(y.)-.15 G(Fla)108 612 Q .707 (w\214nder may f)-.15 F .707(ail to \214nd a vulnerability)-.1 F 3.207 (,e)-.65 G -.15(ve)-3.457 G 3.207(ni).15 G 3.208<668d>-3.207 G -.15(aw) -3.208 G .708(\214nder co).15 F -.15(ve)-.15 G .708 (rs one of these CWE weaknesses.).15 F(That)5.708 E .815(said, \215a)108 624 R .815 (w\214nder does \214nd vulnerabilities listed by the CWEs it co)-.15 F -.15(ve)-.15 G .814(rs, and it will not report lines without).15 F 2.026 (those vulnerabilities in man)108 636 R 4.526(yc)-.15 G 4.526 (ases. Thus,)-4.526 F 2.027(as required for an)4.527 F 4.527(yt)-.15 G 2.027(ool intending to be CWE compatible,)-4.527 F<8d61>108 648 Q 2.213 (w\214nder has a rate of f)-.15 F 2.212(alse positi)-.1 F -.15(ve)-.25 G 4.712(sl).15 G 2.212(ess than 100% and a rate of f)-4.712 F 2.212 (alse ne)-.1 F -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G 4.712(sl).15 G 2.212(ess than 100%.)-4.712 F(Fla)108 660 Q .28(w\214nder almost al)-.15 F -.1(wa)-.1 G .28(ys reports whene).1 F -.15(ve)-.25 G 2.78(ri).15 G 2.781<748c>-2.78 G .281 (nds a match to a CWE security element \(a signature/pattern)-2.781 F(a\ s de\214ned in its database\), though certain obscure constructs can ca\ use it to f)108 672 Q(ail \(see B)-.1 E(UGS belo)-.1 E(w\).)-.25 E(Fla) 108 688.8 Q .207(w\214nder can report on the follo)-.15 F .206 (wing CWEs \(these are the CWEs that \215a)-.25 F .206(w\214nder co)-.15 F -.15(ve)-.15 G .206(rs; `).15 F(`*')-.74 E 2.706('m)-.74 G .206 (arks those)-2.706 F(in the CWE/SANS top 25 list\):)108 700.8 Q 6.5 <8343>108 717.6 S(WE-20: Improper Input V)-6.5 E(alidation)-1.11 E(Fla) 72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(11)202.055 E 0 Cg EP %%Page: 12 12 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E 6.5<8343>108 84 S (WE-22: Improper Limitation of a P)-6.5 E (athname to a Restricted Directory \(`)-.15 E(`P)-.74 E(ath T)-.15 E(ra) -.35 E -.15(ve)-.2 G(rsal').15 E('\))-.74 E 6.5<8343>108 100.8 S .365(W\ E-78: Improper Neutralization of Special Elements used in an OS Command\ \(`)-6.5 F .365(`OS Command Injec-)-.74 F(tion')118 112.8 Q('\)*)-.74 E 6.5<8343>108 129.6 S 1.991(WE-119: Improper Restriction of Operations w\ ithin the Bounds of a Memory Buf)-6.5 F 1.99(fer \(a parent of)-.25 F (CWE-120*, so this is sho)118 141.6 Q(wn as CWE-119!/CWE-120\))-.25 E 6.5<8343>108 158.4 S(WE-120: Buf)-6.5 E(fer Cop)-.25 E 2.5(yw)-.1 G (ithout Checking Size of Input \(`)-2.5 E(`Classic Buf)-.74 E(fer Ov) -.25 E(er\215o)-.15 E(w')-.25 E('\)*)-.74 E 6.5<8343>108 175.2 S (WE-126: Buf)-6.5 E(fer Ov)-.25 E(er)-.15 E(-read)-.2 E 6.5<8343>108 192 S(WE-134: Uncontrolled F)-6.5 E(ormat String*)-.15 E 6.5<8343>108 208.8 S(WE-190: Inte)-6.5 E(ger Ov)-.15 E(er\215o)-.15 E 2.5(wo)-.25 G 2.5(rW) -2.5 G(raparound*)-2.5 E 6.5<8343>108 225.6 S(WE-250: Ex)-6.5 E (ecution with Unnecessary Pri)-.15 E(vile)-.25 E(ges)-.15 E 6.5<8343>108 242.4 S(WE-327: Use of a Brok)-6.5 E(en or Risk)-.1 E 2.5(yC)-.15 G (ryptographic Algorithm*)-2.5 E 6.5<8343>108 259.2 S .407 (WE-362: Concurrent Ex)-6.5 F .407 (ecution using Shared Resource with Improper Synchronization \(`)-.15 F .407(`Race Condi-)-.74 F(tion')118 271.2 Q('\))-.74 E 6.5<8343>108 288 S (WE-377: Insecure T)-6.5 E(emporary File)-.7 E 6.5<8343>108 304.8 S (WE-676: Use of Potentially Dangerous Function*)-6.5 E 6.5<8343>108 321.6 S(WE-732: Incorrect Permission Assignment for Critical Resource*) -6.5 E 6.5<8343>108 338.4 S .596(WE-785: Use of P)-6.5 F .596 (ath Manipulation Function without Maximum-sized Buf)-.15 F .596 (fer \(child of CWE-120*, so)-.25 F(this is sho)118 350.4 Q (wn as CWE-120/CWE-785\))-.25 E 6.5<8343>108 367.2 S (WE-807: Reliance on Untrusted Inputs in a Security Decision*)-6.5 E 6.5 <8343>108 384 S (WE-829: Inclusion of Functionality from Untrusted Control Sphere*)-6.5 E -1.1(Yo)108 400.8 S 2.581(uc)1.1 G .081 (an select a speci\214c subset of CWEs to report by using the `)-2.581 F <60adad7265>-.74 E(ge)-.15 E(x')-.15 E 2.581('\()-.74 G .081 (-e\) option.)-2.581 F .082(This option accepts)5.081 F 3.992(ar)108 412.8 S -.15(eg)-3.992 G 1.492(ular e).15 F 1.492 (xpression, so you can select multiple CWEs, e.g., `)-.15 F<60adad7265> -.74 E(ge)-.15 E 3.991(x")-.15 G(CWE-120|CWE-126"')-3.991 E 3.991('. If) -.74 F(you)3.991 E .023(select multiple CWEs with `)108 424.8 R(`|')-.74 E 2.524('o)-.74 G 2.524(nac)-2.524 G .024 (ommand line you will typically need to quote the parameters \(since an) -2.524 F(unquoted `)108 436.8 Q(`|')-.74 E 2.5('i)-.74 G 2.5(st)-2.5 G (he pipe symbol\).)-2.5 E(Fla)5 E (w\214nder is designed to meet the CWE-Searchable requirement.)-.15 E .498(If your goal is to report a subset of CWEs that are listed in a \ \214le, that can be achie)108 453.6 R -.15(ve)-.25 G 2.998(do).15 G 2.998(naU)-2.998 G(nix-lik)-2.998 E 2.998(es)-.1 G(ys-)-2.998 E .893 (tem using the `)108 465.6 R<60adad7265>-.74 E(ge)-.15 E(x')-.15 E 3.393 ('a)-.74 G .894(ka `)-3.393 F(`\255e')-.74 E 3.394('o)-.74 G 3.394 (ption. The)-3.394 F .894(\214le must be in re)3.394 F .894(gular e)-.15 F .894(xpression format.)-.15 F -.15(Fo)5.894 G 3.394(re).15 G(xample,) -3.544 E -.74(``)108 477.6 S<8d61>.74 E .956 (w\214nder -e $\(cat \214le1\)')-.15 F 3.456('w)-.74 G .956 (ould report only hits that matched the pattern in `)-3.556 F(`\214le1') -.74 E 3.455('. If)-.74 F .955(\214le1 contained)3.455 F -.74(``)108 489.6 S(CWE-120|CWE-126').74 E 2.5('i)-.74 G 2.5(tw)-2.5 G (ould only report hits matching those CWEs.)-2.6 E 2.58(Al)108 506.4 S .08 (ist of all CWE security elements \(the signatures/patterns that \215a) -2.58 F .081(w\214nder looks for\) can be found by using)-.15 F .449 (the `)108 518.4 R(`\255\255listrules')-.74 E 2.949('o)-.74 G 2.949 (ption. Each)-2.949 F .449(line lists the signature tok)2.949 F .449 (en \(typically a function name\) that may lead to a)-.1 F .916 (hit, the def)108 530.4 R .917(ault risk le)-.1 F -.15(ve)-.25 G .917 (l, and the def).15 F .917(ault w)-.1 F .917 (arning \(which includes the def)-.1 F .917(ault CWE identi\214er\).)-.1 F -.15(Fo)5.917 G 3.417(rm).15 G(ost)-3.417 E .727 (purposes this is also enough if you w)108 542.4 R .727 (ant to see what CWE security elements map to which CWEs, or the)-.1 F (re)108 554.4 Q -.15(ve)-.25 G 3.505(rse. F).15 F 1.005(or e)-.15 F 1.006(xample, to see the most of the signatures \(function names\) that\ map to CWE-327, without)-.15 F .165(seeing the def)108 566.4 R .164 (ault risk le)-.1 F -.15(ve)-.25 G 2.664(lo).15 G 2.664(rd)-2.664 G .164 (etailed w)-2.664 F .164(arning te)-.1 F .164(xt, run `)-.15 F(`\215a) -.74 E .164(w\214nder \255\255listrules | grep CWE-327 | cut -f1')-.15 F ('.)-.74 E -1.1(Yo)108 578.4 S 3.087(uc)1.1 G .587(an also see the tok) -3.087 F .588(ens without a CWE mapping this w)-.1 F .588 (ay by running `)-.1 F(`\215a)-.74 E .588 (w\214nder -D --listrules | grep)-.15 F .676(-v CWE-')108 590.4 R 3.176 ('. Ho)-.74 F(we)-.25 E -.15(ve)-.25 G 1.476 -.4(r, w).15 H .676(hile \ \255\255listrules lists all CWE security elements, it only lists the de\ f).4 F .676(ault mappings)-.1 F .09 (from CWE security elements to CWE identi\214ers.)108 602.4 R .091 (It does not include the re\214nements that \215a)5.091 F .091 (w\214nder applies)-.15 F(\(e.g., by e)108 614.4 Q (xamining function parameters\).)-.15 E 1.135(If you w)108 631.2 R 1.135 (ant a detailed and e)-.1 F 1.135(xact mapping between the CWE security\ elements and CWE identi\214ers, the)-.15 F<8d61>108 643.2 Q 1.178 (w\214nder source code \(included in the distrib)-.15 F 1.179 (ution\) is the best place for that information.)-.2 F 1.179 (This detailed)6.179 F 1.459 (information is primarily of interest to those fe)108 655.2 R 3.959(wp) -.25 G 1.459(eople who are trying to re\214ne the CWE mappings of)-3.959 F<8d61>108 667.2 Q 1.02(w\214nder or re\214ne CWE in general.)-.15 F 1.02(The source code documents the mapping between the security ele-) 6.02 F .992(ments to the respecti)108 679.2 R 1.292 -.15(ve C)-.25 H .992(WE identi\214ers, and is a single Python \214le.).15 F .992(The `) 5.992 F(`c_rules')-.74 E 3.492('d)-.74 G .991(ataset de\214nes most) -3.492 F .359(rules, with reference to a function that may mak)108 691.2 R 2.859(ef)-.1 G .359(urther re\214nements.)-2.859 F -1.1(Yo)5.359 G 2.859(uc)1.1 G .359(an search the dataset for func-)-2.859 F .044 (tion names to see what CWE it generates by def)108 703.2 R .043 (ault; if \214rst parameter is not `)-.1 F(`normal')-.74 E 2.543('t)-.74 G .043(hen that is the name)-2.543 F .64 (of a re\214ning Python method that may select dif)108 715.2 R .64 (ferent CWEs \(depending on additional information\).)-.25 F(Con-)5.64 E -.15(ve)108 727.2 S(rsely).15 E 3.192(,y)-.65 G .692 (ou can search for `)-3.192 F(`CWE-number')-.74 E 3.192('a)-.74 G .691 (nd \214nd what security elements \(signatures or patterns\) refer) -3.192 F(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(12) 202.055 E 0 Cg EP %%Page: 13 13 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E .594(to that CWE identi\214er) 108 84 R 5.594(.F)-.55 G .595 (or most people, this is much more than the)-5.744 F 3.095(yn)-.15 G .595(eed; most people just w)-3.095 F .595(ant to scan)-.1 F (their source code to quickly \214nd problems.)108 96 Q/F1 10.95 /Times-Bold@0 SF(SECURITY)72 136.8 Q F0 .782 (The whole point of this tool is to help \214nd vulnerabilities so the) 108 148.8 R 3.281(yc)-.15 G .781(an be \214x)-3.281 F 3.281(ed. Ho)-.15 F(we)-.25 E -.15(ve)-.25 G 1.581 -.4(r, d).15 H -2.15 -.25(ev e).4 H .781(lopers and).25 F(re)108 160.8 Q(vie)-.25 E .351(wers must kno)-.25 F 2.851(wh)-.25 G .851 -.25(ow t)-2.851 H 2.851(od).25 G -2.15 -.25 (ev e)-2.851 H .351(lop secure softw).25 F .352 (are to use this tool, because otherwise,)-.1 F/F2 10/Times-Italic@0 SF 2.852(af)2.852 G .352(ool with a tool)-2.852 F(is still a fool)108 172.8 Q F0 5(.M)C 2.5(yb)-5 G(ook at https://dwheeler)-2.5 E (.com/secure-programs may help.)-.55 E .214 (This tool should be, at most, a small part of a lar)108 189.6 R .214 (ger softw)-.18 F .214(are de)-.1 F -.15(ve)-.25 G .214 (lopment process designed to eliminate or).15 F .227 (reduce the impact of vulnerabilities.)108 201.6 R(De)5.227 E -.15(ve) -.25 G .227(lopers and re).15 F(vie)-.25 E .227(wers need kno)-.25 F 2.727(wh)-.25 G .727 -.25(ow t)-2.727 H 2.727(od).25 G -2.15 -.25(ev e) -2.727 H .228(lop secure softw).25 F(are,)-.1 E(and the)108 213.6 Q 2.5 (yn)-.15 G(eed to apply this kno)-2.5 E (wledge to reduce the risks of vulnerabilities in the \214rst place.) -.25 E(Dif)108 230.4 Q 1.924 (ferent vulnerability-\214nding tools tend to \214nd dif)-.25 F 1.924 (ferent vulnerabilities.)-.25 F 1.924(Thus, you are best of)6.924 F 4.423(fu)-.25 G(sing)-4.423 E(human re)108 242.4 Q(vie)-.25 E 2.5(wa) -.25 G(nd a v)-2.5 E(ariety of tools.)-.25 E (This tool can help \214nd some vulnerabilities, b)5 E (ut by no means all.)-.2 E -1.1(Yo)108 259.2 S 2.858(us)1.1 G .358 (hould al)-2.858 F -.1(wa)-.1 G .359(ys analyze a).1 F F2(copy)2.859 E F0 .359(of the source program being analyzed, not a directory that can \ be modi-)2.859 F .345(\214ed by a de)108 271.2 R -.15(ve)-.25 G .344 (loper while \215a).15 F .344(w\214nder is performing the analysis.)-.15 F .344(This is)5.344 F F2(especially)2.844 E F0 .344(true if you don') 2.844 F 2.844(tn)-.18 G(ecess-)-2.844 E .806(ily trust a de)108 283.2 R -.15(ve)-.25 G .806(loper of the program being analyzed.).15 F .806 (If an attack)5.806 F .806(er has control o)-.1 F -.15(ve)-.15 G 3.306 (rt).15 G .807(he \214les while you')-3.306 F(re)-.5 E .539 (analyzing them, the attack)108 295.2 R .539(er could mo)-.1 F .838 -.15 (ve \214)-.15 H .538(les around or change their contents to pre).15 F -.15(ve)-.25 G .538(nt the e).15 F .538(xposure of a)-.15 F .077(securi\ ty problem \(or create the impression of a problem where there is none\ \).)108 307.2 R .078(If you')5.078 F .078(re w)-.5 F .078 (orried about mali-)-.1 F 1.018(cious programmers you should do this an) 108 319.2 R(yw)-.15 E(ay)-.1 E 3.518(,b)-.65 G 1.017 (ecause after analysis you')-3.518 F 1.017(ll need to v)-.1 F 1.017 (erify that the code)-.15 F -2.15 -.25(ev e)108 331.2 T .71 (ntually run is the code you analyzed.).25 F .711 (Also, do not use the \255\255allo)5.71 F .711 (wlink option in such cases; attack)-.25 F(ers)-.1 E(could create malic\ ious symbolic links to \214les outside of their source code area \(such\ as /etc/passwd\).)108 343.2 Q .726 (Source code management systems \(lik)108 360 R 3.226(eG)-.1 G .725 (itHub, SourceF)-3.226 F(or)-.15 E .725(ge, and Sa)-.18 F -.25(va)-.2 G .725(nnah\) de\214nitely f).25 F .725(all into this cate-)-.1 F .11 (gory; if you')108 372 R .11 (re maintaining one of those systems, \214rst cop)-.5 F 2.61(yo)-.1 G 2.61(re)-2.61 G .11(xtract the \214les into a separate directory \(that) -2.76 F(can')108 384 Q 2.5(tb)-.18 G 2.5(ec)-2.5 G(ontrolled by attack) -2.5 E(ers\) before running \215a)-.1 E(w\214nder or an)-.15 E 2.5(yo) -.15 G(ther code analysis tool.)-2.5 E 1.276(Note that \215a)108 400.8 R 1.276(w\214nder only opens re)-.15 F 1.276(gular \214les, directories, \ and \(if requested\) symbolic links; it will ne)-.15 F -.15(ve)-.25 G(r) .15 E 1.607(open other kinds of \214les, e)108 412.8 R -.15(ve)-.25 G 4.107(ni).15 G 4.107(fas)-4.107 G 1.607(ymbolic link is made to them.) -4.107 F 1.608(This counters attack)6.607 F 1.608(ers who insert)-.1 F .363(unusual \214le types into the source code.)108 424.8 R(Ho)5.363 E (we)-.25 E -.15(ve)-.25 G 1.163 -.4(r, t).15 H .363(his only w).4 F .363 (orks if the \214lesystem being analyzed can')-.1 F 2.862(tb)-.18 G(e) -2.862 E .479(modi\214ed by an attack)108 436.8 R .479 (er during the analysis, as recommended abo)-.1 F -.15(ve)-.15 G 5.479 (.T).15 G .48(his protection also doesn')-5.479 F 2.98(tw)-.18 G .48 (ork on)-3.08 F(Cygwin platforms, unfortunately)108 448.8 Q(.)-.65 E .789(Cygwin systems \(Unix emulation on top of W)108 465.6 R(indo)-.4 E .789(ws\) ha)-.25 F 1.089 -.15(ve a)-.2 H 3.289(na).15 G .789 (dditional problem if \215a)-3.289 F .788(w\214nder is used to)-.15 F 1.053(analyze programs that the analyst cannot trust.)108 477.6 R 1.053 (The problem is due to a design \215a)6.053 F 3.554(wi)-.15 G 3.554(nW) -3.554 G(indo)-3.954 E 1.054(ws \(that it)-.25 F .999 (inherits from MS-DOS\).)108 489.6 R .999(On W)5.999 F(indo)-.4 E .998 (ws and MS-DOS, certain \214lenames \(e.g., `)-.25 F(`com1')-.74 E .998 ('\) are automatically)-.74 F .686(treated by the operating system as t\ he names of peripherals, and this is true e)108 501.6 R -.15(ve)-.25 G 3.186(nw).15 G .686(hen a full pathname is)-3.186 F(gi)108 513.6 Q -.15 (ve)-.25 G 2.975(n. Y).15 F .475(es, W)-1 F(indo)-.4 E .475 (ws and MS-DOS really are designed this badly)-.25 F 5.475(.F)-.65 G(la) -5.475 E .474(w\214nder deals with this by checking)-.15 F .867(what a \ \214lesystem object is, and then only opening directories and re)108 525.6 R .867(gular \214les \(and symlinks if enabled\).)-.15 F (Unfortunately)108 537.6 Q 2.52(,t)-.65 G .02(his doesn')-2.52 F 2.52 (tw)-.18 G .02(ork on Cygwin; on at least some v)-2.62 F .019 (ersions of Cygwin on some v)-.15 F .019(ersions of W)-.15 F(in-)-.4 E (do)108 549.6 Q .259(ws, merely trying to determine if a \214le is a de) -.25 F .259(vice type can cause the program to hang.)-.25 F 2.759(Aw) 5.259 G .259(orkaround is)-2.859 F 1.649(to delete or rename an)108 561.6 R 4.149<798c>-.15 G 1.649(lenames that are interpreted as de) -4.149 F 1.648(vice names before performing the analysis.)-.25 F 4.705 (These so-called `)108 573.6 R(`reserv)-.74 E 4.705(ed names')-.15 F 7.205('a)-.74 G 4.705(re CON, PRN, A)-7.205 F 4.706 (UX, CLOCK$, NUL, COM1-COM9, and)-.55 F 1.798 (LPT1-LPT9, optionally follo)108 585.6 R 1.798(wed by an e)-.25 F 1.798 (xtension \(e.g., `)-.15 F(`com1.txt')-.74 E 1.798('\), in an)-.74 F 4.298(yd)-.15 G(irectory)-4.298 E 4.298(,a)-.65 G 1.798(nd in an)-4.298 F 4.297(yc)-.15 G(ase)-4.297 E(\(W)108 597.6 Q(indo)-.4 E (ws is case-insensiti)-.25 E -.15(ve)-.25 G(\).).15 E(Do)108 614.4 Q F2 (not)2.808 E F0 .308(load or dif)2.808 F 2.808(fh)-.25 G .308 (itlists from untrusted sources.)-2.808 F(The)5.308 E 2.808(ya)-.15 G .308(re implemented using the Python pickle module,)-2.808 F 1.919 (and the pickle module is not intended to be secure ag)108 626.4 R 1.918 (ainst erroneous or maliciously constructed data.)-.05 F .218(Stored hi\ tlists are intended for later use by the same user who created the hitl\ ist; in that conte)108 638.4 R .219(xt this restric-)-.15 F (tion is not a problem.)108 650.4 Q F1 -.11(BU)72 679.2 S(GS).11 E F0 (Fla)108 691.2 Q .399(w\214nder is based on simple te)-.15 F .399(xt pa\ ttern matching, which is part of its fundamental design and not easily) -.15 F 3.282(changed. This)108 703.2 R .782(design approach leads to a \ number of fundamental limitations, e.g., a higher f)3.282 F .782 (alse positi)-.1 F -.15(ve)-.25 G .055 (rate, and is the underlying cause of most of the b)108 715.2 R .055 (ugs listed here.)-.2 F .055(On the positi)5.055 F .354 -.15(ve s)-.25 H .054(ide, \215a).15 F .054(w\214nder doesn')-.15 F 2.554(tg)-.18 G(et) -2.554 E .169(confused by man)108 727.2 R 2.669(yc)-.15 G .169 (omplicated preprocessor sequences that other tools sometimes chok) -2.669 F 2.67(eo)-.1 G .17(n; \215a)-2.67 F .17(w\214nder can)-.15 F (Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(13)202.055 E 0 Cg EP %%Page: 14 14 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E (often handle code that cannot link, and sometimes cannot e)108 84 Q -.15(ve)-.25 G 2.5(nc).15 G(ompile or b)-2.5 E(uild.)-.2 E(Fla)108 100.8 Q .861(w\214nder is currently limited to C/C++.)-.15 F .86 (In addition, when analyzing C++ it focuses primarily on the C)5.861 F .49(subset of C++.)108 112.8 R -.15(Fo)5.49 G 2.99(re).15 G .49 (xample, \215a)-3.14 F .49(w\214nder does not report on e)-.15 F .49 (xpressions lik)-.15 F 2.99(ec)-.1 G .49(in >> charb)-2.99 F .49 (uf, where charb)-.2 F(uf)-.2 E .276(is a char array)108 124.8 R 5.276 (.T)-.65 G .276(hat is because \215a)-5.276 F .276(w\214nder doesn')-.15 F 2.776(th)-.18 G -2.25 -.2(av e)-2.776 H .275 (type information, and ">>" is safe with man)2.976 F 2.775(yo)-.15 G (ther)-2.775 E .447(types; reporting on all ">>" w)108 136.8 R .447 (ould lead to too man)-.1 F 2.947(yf)-.15 G .447(alse positi)-3.047 F -.15(ve)-.25 G 2.947(s. That).15 F .447(said, it')2.947 F 2.948(sd)-.55 G .448(esigned so that adding)-2.948 F (support for other languages should be easy where its te)108 148.8 Q (xt-based approach can usefully apply)-.15 E(.)-.65 E(Fla)108 165.6 Q .813(w\214nder can be fooled by user)-.15 F .812(-de\214ned functions o\ r method names that happen to be the same as those)-.2 F .185 (de\214ned as `)108 177.6 R(`hits')-.74 E 2.685('i)-.74 G 2.685(ni) -2.685 G .186(ts database, and will often trigger on de\214nitions \(as\ well as uses\) of functions with the)-2.685 F .998(same name.)108 189.6 R .998(This is typically not a problem for C code.)5.998 F .997 (In C code, a function with the same name as a)5.998 F .495 (common library routine name often indicates that the de)108 201.6 R -.15(ve)-.25 G .495(loper is simply re).15 F .496 (writing a common library rou-)-.25 F .072(tine with the same interf)108 213.6 R .071(ace, say for portability')-.1 F 2.571(ss)-.55 G(ak)-2.571 E 2.571(e. C)-.1 F .071(programs tend to a)2.571 F -.2(vo)-.2 G .071 (id reusing the same name for).2 F 2.857(ad)108 225.6 S(if)-2.857 E .357 (ferent purpose \(since in C function names are global by def)-.25 F 2.857(ault\). There)-.1 F .357(are reasonable odds that these)2.857 F (re)108 237.6 Q .406(written routines will be vulnerable to the same ki\ nds of misuse, and thus, reusing these rules is a reason-)-.25 F .186 (able approach.)108 249.6 R(Ho)5.186 E(we)-.25 E -.15(ve)-.25 G .986 -.4 (r, t).15 H .186 (his can be a much more serious problem in C++ code which hea).4 F .187 (vily uses classes)-.2 F 1.355 (and namespaces, since the same method name may ha)108 261.6 R 1.654 -.15(ve m)-.2 H(an).15 E 3.854(yd)-.15 G(if)-3.854 E 1.354 (ferent meanings.)-.25 F 1.354(The \255\255f)6.354 F(alsepositi)-.1 E -.15(ve)-.25 G 1.189(option can help some)108 273.6 R 1.189 (what in this case.)-.25 F 1.189 (If this is a serious problem, feel free to modify the program, or)6.189 F(process the \215a)108 285.6 Q (w\214nder output through other tools to remo)-.15 E .3 -.15(ve t)-.15 H (he f).15 E(alse positi)-.1 E -.15(ve)-.25 G(s.).15 E .025(Preprocessor\ commands embedded in the middle of a parameter list of a call can caus\ e problems in parsing,)108 302.4 R 2.382(in particular)108 314.4 R 4.882 (,i)-.4 G 4.882(fas)-4.882 G 2.382(tring is opened and then closed mult\ iple times using an #ifdef .. #else construct,)-4.882 F<8d61>108 326.4 Q .073(w\214nder gets confused.)-.15 F .073 (Such constructs are bad style, and will confuse man)5.073 F 2.573(yo) -.15 G .073(ther tools too.)-2.573 F .073(If you must)5.073 F (analyze such \214les, re)108 338.4 Q(write those lines.)-.25 E (Thankfully)5 E 2.5(,t)-.65 G(hese are quite rare.)-2.5 E(Fla)108 355.2 Q 2.656(w\214nder reports vulnerabilities re)-.15 F -.05(ga)-.15 G 2.656 (rdless of the parameters of "#if" or "#ifdef".).05 F 5.157(Ac)7.656 G 2.657(onstruct "#if)-5.157 F -1.35(VA)108 367.2 S .722 (LUE" will often ha)1.35 F 1.022 -.15(ve V)-.2 H .722 (ALUE of 0 in some cases, and non-zero in others.)-1.2 F(Similarly)5.722 E 3.221(,")-.65 G .721(#ifdef V)-3.221 F(ALUE")-1.35 E .605(will ha)108 379.2 R .905 -.15(ve V)-.2 H .606 (ALUE de\214ned in some cases, and not de\214ned in others.)-1.2 F(Fla) 5.606 E .606(w\214nder reports in all cases, which)-.15 F .542 (means that \215a)108 391.2 R .541 (w\214nder has a chance of reporting vulnerabilities in all alternati) -.15 F -.15(ve)-.25 G 3.041(s. This).15 F .541(is not a b)3.041 F .541 (ug, this is)-.2 F(intended beha)108 403.2 Q(vior)-.2 E(.)-.55 E(Fla)108 420 Q .739(w\214nder will report hits e)-.15 F -.15(ve)-.25 G 3.239(ni) .15 G 3.239(ft)-3.239 G(he)-3.239 E 3.239(ya)-.15 G .739 (re between a literal "#if 0" and "#endif".)-3.239 F .739(It w)5.739 F .739(ould be possible to)-.1 F .842(change this particular situation, b) 108 432 R .841 (ut directly using "#if 0" to comment-out code \(other than during deb) -.2 F(ug-)-.2 E .599(ging\) indicates \(1\) the remo)108 444 R -.25(va) -.15 G 3.099(li).25 G 3.099(sv)-3.099 G .6 (ery temporary \(in which case we should still report it\) or \(2\) v) -3.249 F .6(ery poor)-.15 F .173(code practices.)108 456 R .173 (If you w)5.173 F .173(ant to permanently get rid of code, then delete \ it instead of using "#if 0", since you)-.1 F .441(can al)108 468 R -.1 (wa)-.1 G .441(ys see what it w).1 F .442(as using your v)-.1 F .442 (ersion control softw)-.15 F 2.942(are. If)-.1 F .442(you don')2.942 F 2.942(tu)-.18 G .442(se v)-2.942 F .442(ersion control softw)-.15 F (are,)-.1 E(then that')108 480 Q 2.5(st)-.55 G(he b)-2.5 E (ug you need to \214x right no)-.2 E -.65(w.)-.25 G .602(Some comple)108 496.8 R 3.102(xo)-.15 G 3.102(ru)-3.102 G .602 (nusual constructs can mislead \215a)-3.102 F(w\214nder)-.15 E 5.602(.I) -.55 G 3.102(np)-5.602 G(articular)-3.102 E 3.102(,i)-.4 G 3.102(fap) -3.102 G .602(arameter be)-3.102 F .602(gins with get-)-.15 F(te)108 508.8 Q .977(xt\(" and ends with \), \215a)-.15 F .977 (w\214nder will presume that the parameter of gette)-.15 F .977 (xt is a constant.)-.15 F .978(This means it)5.978 F 1.267 (will get confused by patterns lik)108 520.8 R 3.766(eg)-.1 G(ette) -3.766 E 1.266(xt\("hi"\) + function\("bye"\).)-.15 F 1.266 (In practice, this doesn')6.266 F 3.766(ts)-.18 G 1.266(eem to be a) -3.766 F(problem; gette)108 532.8 Q (xt\(\) is usually wrapped around the entire parameter)-.15 E(.)-.55 E 2.201(The routine to detect statically de\214ned character arrays uses \ simple te)108 549.6 R 2.201(xt matching; some complicated)-.15 F -.15 (ex)108 561.6 S(pressions can cause it to trigger or not trigger une).15 E(xpectedly)-.15 E(.)-.65 E(Fla)108 578.4 Q .222 (w\214nder looks for speci\214c patterns kno)-.15 F .221 (wn to be common mistak)-.25 F 2.721(es. Fla)-.1 F .221 (w\214nder \(or an)-.15 F 2.721(yt)-.15 G .221(ool lik)-2.721 F 2.721 (ei)-.1 G .221(t\) is not)-2.721 F 2.572(ag)108 590.4 S .072 (ood tool for \214nding intentionally malicious code \(e.g., T)-2.572 F .072(rojan horses\); malicious programmers can easily)-.35 F (insert code that w)108 602.4 Q (ould not be detected by this kind of tool.)-.1 E(Fla)108 619.2 Q .355 (w\214nder looks for speci\214c patterns kno)-.15 F .355 (wn to be common mistak)-.25 F .355(es in application code.)-.1 F .355 (Thus, it is lik)5.355 F(ely)-.1 E .673(to be less ef)108 631.2 R(fecti) -.25 E .973 -.15(ve a)-.25 H .673(nalyzing programs that aren').15 F 3.174(ta)-.18 G .674(pplication-layer code \(e.g., k)-3.174 F .674 (ernel code or self-hosting)-.1 F 2.868(code\). The)108 643.2 R .367(te\ chniques may still be useful; feel free to replace the database if your\ situation is signi\214cantly)2.867 F(dif)108 655.2 Q (ferent from normal.)-.25 E(Fla)108 672 Q(w\214nder')-.15 E 3.07(sd)-.55 G(ef)-3.07 E .571(ault output format \(\214lename:linenumber)-.1 F 3.071 (,f)-.4 G(ollo)-3.071 E .571(wed optionally by a :columnnumber\) can be) -.25 F 1.775(misunderstood if an)108 684 R 4.275(ys)-.15 G 1.775 (ource \214les ha)-4.275 F 2.075 -.15(ve ve)-.2 H 1.775 (ry weird \214lenames.).15 F 1.775(Filenames embedding a ne)6.775 F (wline/linefeed)-.25 E .708(character will cause odd breaks, and \214le\ names including colon \(:\) are lik)108 696 R .708 (ely to be misunderstood.)-.1 F .709(This is)5.709 F .176 (especially important if \215a)108 708 R(w\214nder')-.15 E 2.676(so)-.55 G .176(utput is being used by other tools, such as \214lters or te) -2.676 F .175(xt editors.)-.15 F .175(If you)5.175 F .448 (are using \215a)108 720 R(w\214nder')-.15 E 2.948(so)-.55 G .449(utput\ in other tools, consider using its CSV format instead \(which can hand\ le this\).)-2.948 F(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(14)202.055 E 0 Cg EP %%Page: 15 15 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF(FLA)72 48 Q 134.71(WFINDER\(1\) Fla)-.9 F 134.71 (w\214nder FLA)-.15 F(WFINDER\(1\))-.9 E 1.014(If you')108 84 R 1.014 (re looking at ne)-.5 F 3.514(wc)-.25 G 1.014(ode, e)-3.514 F 1.014 (xamine the \214les for such characters.)-.15 F(It')6.013 E 3.513(si) -.55 G 1.013(ncredibly unwise to ha)-3.513 F 1.313 -.15(ve s)-.2 H(uch) .15 E .841(\214lenames an)108 96 R(yw)-.15 E .841(ay; man)-.1 F 3.342 (yt)-.15 G .842(ools can')-3.342 F 3.342(th)-.18 G .842 (andle such \214lenames at all.)-3.342 F(Ne)5.842 E .842 (wline and linefeed are often used as)-.25 F .858 (internal data delimeters.)108 108 R .857(The colon is often used as sp\ ecial characters in \214lesystems: MacOS uses it as a)5.857 F 1.135 (directory separator)108 120 R 3.635(,W)-.4 G(indo)-4.035 E 1.135 (ws/MS-DOS uses it to identify dri)-.25 F 1.435 -.15(ve l)-.25 H 1.135 (etters, W).15 F(indo)-.4 E 1.135(ws/MS-DOS inconsistently)-.25 F .542 (uses it to identify special de)108 132 R .541(vices lik)-.25 F 3.041 (eC)-.1 G .541(ON:, and applications on man)-3.041 F 3.041(yp)-.15 G .541(latforms use the colon to identify)-3.041 F 2.926 (URIs/URLs. Filenames)108 144 R .427(including spaces and/or tabs don') 2.927 F 2.927(tc)-.18 G .427(ause problems for \215a)-2.927 F(w\214nder) -.15 E 2.927(,t)-.4 G .427(hough note that)-2.927 F (other tools might ha)108 156 Q .3 -.15(ve p)-.2 H(roblems with them.) .15 E(Fla)108 172.8 Q(w\214nder is not internationalized, so it current\ ly does not support localization.)-.15 E .133(In general, \215a)108 189.6 R .133(w\214nder attempts to err on the side of caution; it tends\ to report hits, so that the)-.15 F 2.632(yc)-.15 G .132(an be e)-2.632 F(xam-)-.15 E .397(ined further)108 201.6 R 2.897(,i)-.4 G .397 (nstead of silently ignoring them.)-2.897 F .397(Thus, \215a)5.397 F .397(w\214nder prefers to ha)-.15 F .698 -.15(ve f)-.2 H .398 (alse positi).05 F -.15(ve)-.25 G 2.898(s\().15 G .398(reports that) -2.898 F .318(turn out to not be problems\) rather than f)108 213.6 R .317(alse ne)-.1 F -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G 2.817(s\().15 G -.1(fa)-2.817 G .317(ilures to report security vulnerabilities\).).1 F .317(But this)5.317 F(is a generality; \215a)108 225.6 Q (w\214nder uses simplistic heuristics and simply can')-.15 E 2.5(tg)-.18 G(et e)-2.5 E -.15(ve)-.25 G(rything "right".).15 E .061 (Security vulnerabilities might not be identi\214ed as such by \215a)108 242.4 R(w\214nder)-.15 E 2.561(,a)-.4 G .062(nd con)-2.561 F -.15(ve)-.4 G(rsely).15 E 2.562(,s)-.65 G .062(ome hits aren')-2.562 F 2.562(tr)-.18 G(eally)-2.562 E 1.507(security vulnerabilities.)108 254.4 R 1.506(This\ is true for all static security scanners, and is especially true for t\ ools lik)6.507 F(e)-.1 E<8d61>108 266.4 Q .043 (w\214nder that use a simple le)-.15 F .043(xical analysis and pattern \ analysis to identify potential vulnerabilities.)-.15 F .044(Still, it) 5.044 F 1.112(can serv)108 278.4 R 3.612(ea)-.15 G 3.611(sau)-3.612 G 1.111(seful aid for humans, helping to identify useful places to e) -3.611 F 1.111(xamine further)-.15 F 3.611(,a)-.4 G 1.111(nd that') -3.611 F 3.611(st)-.55 G(he)-3.611 E(point of this simple tool.)108 290.4 Q/F1 10.95/Times-Bold@0 SF(SEE ALSO)72 319.2 Q F0 1.344 (See the \215a)108 331.2 R 1.344(w\214nder website at https://dwheeler) -.15 F(.com/\215a)-.55 E(w\214nder)-.15 E 6.344(.Y)-.55 G 1.344 (ou should also see the)-7.444 F/F2 10/Times-Italic@0 SF(Secur)4.175 E 3.845(eP)-.37 G -1.7 -.45(ro g)-3.845 H -.15(ra).45 G(m-).15 E(ming HO) 108 343.2 Q(WT)-.5 E(O)-.18 E F0(at)2.77 E F2(https://dwheeler)2.5 E (.com/secur)-1.11 E(e-pr)-.37 E -.1(og)-.45 G -.15(ra).1 G(ms).15 E F0 (.).27 E F1 -.548(AU)72 372 S(THOR).548 E F0(Da)108 384 Q (vid A. Wheeler \(dwheeler@dwheeler)-.2 E(.com\).)-.55 E(Fla)72 768 Q 166.375(w\214nder 3)-.15 F(Jun 2021)2.5 E(15)202.055 E 0 Cg EP %%Trailer end %%EOF flawfinder-2.0.19/pylintrc000644 000765 000024 00000036235 13774402305 016473 0ustar00dwheelerstaff000000 000000 [MASTER] # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code extension-pkg-whitelist= # Add files or directories to the blacklist. They should be base names, not # paths. ignore=CVS # Add files or directories matching the regex patterns to the blacklist. The # regex matches against base names, not paths. ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= # Use multiple processes to speed up Pylint. jobs=1 # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins= # Pickle collected data for later comparisons. persistent=yes # Specify a configuration file. #rcfile= # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED confidence= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once).You can also use "--disable=all" to # disable everything first and then reenable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" # Flawfinder specifics: This disables "invalid-name", because that checker # has a serious bug: it can't handle global variables and thinks they are # constants (so it raises a hailstorm of incorrect reports). # We *use* global-statement, so don't warn about it. # TODO: perhaps stop disabling some, e.g., # missing-docstring, too-many-statements, # too-many-branches,too-many-locals,too-many-nested-blocks disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,invalid-name,missing-docstring,global-statement,too-many-statements,too-many-branches,too-many-locals,too-many-instance-attributes,too-many-nested-blocks # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. enable= [REPORTS] # Python expression which should return a note less than 10 (10 is the highest # note). You have access to the variables errors warning, statement which # respectively contain the number of errors / warnings messages and the total # number of statements analyzed. This is used by the global evaluation report # (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details #msg-template= # Set the output format. Available formats are text, parseable, colorized, json # and msvs (visual studio).You can also give a reporter class, eg # mypackage.mymodule.MyReporterClass. output-format=text # Tells whether to display a full report or only the messages reports=no # Activate the evaluation score. score=yes [REFACTORING] # Maximum number of nested blocks for function / method body max-nested-blocks=5 [BASIC] # Naming hint for argument names argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Regular expression matching correct argument names argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Naming hint for attribute names attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Regular expression matching correct attribute names attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,baz,toto,tutu,tata # Naming hint for class attribute names class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ # Regular expression matching correct class attribute names class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ # Naming hint for class names class-name-hint=[A-Z_][a-zA-Z0-9]+$ # Regular expression matching correct class names class-rgx=[A-Z_][a-zA-Z0-9]+$ # Naming hint for constant names const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ # Regular expression matching correct constant names const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=-1 # Naming hint for function names function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Regular expression matching correct function names function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Good variable names which should always be accepted, separated by a comma good-names=i,j,k,ex,Run,_ # Include a hint for the correct naming format with invalid-name include-naming-hint=no # Naming hint for inline iteration names inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ # Regular expression matching correct inline iteration names inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ # Naming hint for method names method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Regular expression matching correct method names method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Naming hint for module names module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Regular expression matching correct module names module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=^_ # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. property-classes=abc.abstractproperty # Naming hint for variable names variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ # Regular expression matching correct variable names variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ [FORMAT] # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). indent-string=' ' # Maximum number of characters on a single line. # TODO: Flawfinder specific - eventually we'll bring this down to 80 max-line-length=500 # Maximum number of lines in a module # Flawfinder specific - we want this to be a single file max-module-lines=5000 # List of optional constructs for which whitespace checking is disabled. `dict- # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. # `trailing-comma` allows a space between comma and closing bracket: (a, ). # `empty-line` allows space-only lines. no-space-check=trailing-comma,dict-separator # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=no [LOGGING] # Logging modules to check that the string format arguments are in logging # function parameter format logging-modules=logging [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. # notes=FIXME,XXX,TODO # Flawfinder specifics: We already note them, no need to report notes= [SIMILARITIES] # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no # Minimum lines number of a similarity. min-similarity-lines=4 [SPELLING] # Spelling dictionary name. Available dictionaries: none. To make it working # install python-enchant package. spelling-dict= # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to indicated private dictionary in # --spelling-private-dict-file option instead of raising a message. spelling-store-unknown-words=no [TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. contextmanager-decorators=contextlib.contextmanager # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). ignore-mixin-members=yes # This flag controls whether pylint should warn about no-member and similar # checks whenever an opaque object is returned when inferring. The inference # can return multiple potential results while evaluating a Python object, but # some branches might not be evaluated, which results in partial inference. In # that case, it might be useful to still emit no-member and other checks for # the rest of the inferred objects. ignore-on-opaque-inference=yes # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=optparse.Values,thread._local,_thread._local # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching. ignored-modules= # Show a hint with possible names when a member name was not found. The aspect # of finding the hint is based on edit distance. missing-member-hint=yes # The minimum edit distance a name should have in order to be considered a # similar match for a missing member name. missing-member-hint-distance=1 # The total number of similar names that should be taken in consideration when # showing a hint for a missing member. missing-member-max-choices=1 [VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=yes # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_,_cb # A regular expression matching the name of dummy variables (i.e. expectedly # not used). dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ # Argument names that match this expression will be ignored. Default to name # with leading underscore ignored-argument-names=_.*|^ignored_|^unused_ # Tells whether we should check for unused import in __init__ files. init-import=no # List of qualified module names which can have objects that can redefine # builtins. redefining-builtins-modules=six.moves,future.builtins [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__,__new__,setUp # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict,_fields,_replace,_source,_make # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=mcs [DESIGN] # Maximum number of arguments for function / method max-args=5 # Maximum number of attributes for a class (see R0902). max-attributes=7 # Maximum number of boolean expressions in a if statement max-bool-expr=5 # Maximum number of branch for function / method body max-branches=12 # Maximum number of locals for function / method body max-locals=15 # Maximum number of parents for a class (see R0901). max-parents=7 # Maximum number of public methods for a class (see R0904). max-public-methods=20 # Maximum number of return / yield for function / method body max-returns=6 # Maximum number of statements in function / method body max-statements=50 # Minimum number of public methods for a class (see R0903). min-public-methods=2 [IMPORTS] # Allow wildcard imports from modules that define __all__. allow-wildcard-with-all=no # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no # Deprecated modules which should not be used, separated by a comma deprecated-modules=regsub,TERMIOS,Bastion,rexec # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled) ext-import-graph= # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled) import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= # Force import order to recognize a module as part of the standard # compatibility libraries. known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "Exception" overgeneral-exceptions=Exception flawfinder-2.0.19/setup.cfg000644 000765 000024 00000000321 13774402305 016510 0ustar00dwheelerstaff000000 000000 [metadata] description-file = README.md [bdist_wheel] universal=1 [bdist_rpm] release = 1 doc_files = ChangeLog README.md COPYING flawfinder.ps flawfinder.pdf flawfinder-2.0.19/flawfinder.1.gz000644 000765 000024 00000046736 13777165617 017554 0ustar00dwheelerstaff000000 000000 ‹Êýù_µ}ûsÇ•îïýWL½EÀ@‘²c[¬Í]š¢"Þ•D.AEvE©p ˆ‰€df@Š®ÔýÛïùΣ»gÊÞÇ­JÅ"0èéÇés¾ó>øØs㽤6HÎÊÍc•ß-›äøÙ³£Ññ³£ï“—é}>ONÇɇe–­²*éÏä_ÿfÿÏÊõƒð@7˼N6UyW¥ë„þ¹¨²,©ËEóVÙIòXn“YZ$U6Ïë¦Ê§Û&Kò&I‹ùaY%ërž/y úp[ÌéÍ2Kš¬Z×I¹à?þôî}ò§¬Èªt•\m§«|–¼ÉgYQgIJïÆ'õ2›'S?y…YLtÉ«’FN›¼,N’,§ï«ä>«jú;9¶—èˆÃ¤¬dƒÒ“¯’rƒhÆÉ*mÂoÇüÜÞMk'yÁã/Ë -kI£ÒBòÕ*™fɶÎÛÕÇ §“7¯/ßß$§ï~N>œ^_Ÿ¾»ùù„žn–%}›Ýg2V¾Þ¬ršW¥EóHkà!Þž_Ÿ½¦ßœþxñæâægZJòêâæÝùd’¼º¼NN“«Ó뛋³÷oN¯“«÷×W—“óq’L2L,ã¾°Õ >.ÚÍyÖ¤ùªŽ–ÿ3rMS\Í“ezŸÑaϲüž&˜&3¢±_?G%]•Å/–žûy’䋤(›aòPåDž—Í<¯Z_¥=‹ñýÇ›´™-ÿõãâb‘¯²"]g×<é«IçÓ}S{M;‚{™×›UúÏ/Ǭkë‚~K.~Äçë¼XÑE]ÑK¯é ?é ñå%öakYéªÎ6e7tmxÌW;K)hTâÖ® ž(ô‰¿è‹«ì.û¬o½:½¹9¿~½›—Øúfßz/· ÎâUY­Ó&^í¬,šìsÃ/žµ¦>+WÛu!qÖþ¦¾oýMw3- ¢S<ú²õÕ²Y¯øã×­óõšÄ]8ún”·¾ªiº«ŒÎ\6cÒú²\çM“¯³Ö‡ÿØæ™,à?ZŸgUUV#foÎÿ|þ¦MtûÓ;l] ´<ö›¾*Ó9}Šuë_ñÖÚ÷5±Ã/}OÒo±ïûöÑc.ôïèÚ& ]0xý¬*ˆÄqÞ¦¬“¿~Í÷úåùäìúâêæâò_]¹ÀNˆ;¤ÕlIW²YVåön™œž}ýu뫲ü„eçwO±•±»)“j[Dlc˜ÔPɈ9bV)o¤M4§÷Ó°‰È.ÉÒÙ2Z† &MÌ@ ÊBFæk78!ê$IBœ§v,qÓx;ú7Üåz;Þ=„¤Ú¿¢³x©œ}NégsZÛrK‰ä£™“Dú;ý¶~r…L<•x²›»yF²áa¢yHnoÇüü„æSÑN‡‡C‡ÙGoáyê$ykôm:=zÓÎYŽã£Ÿ—´‘Dj$TAèUFW£Rp¼F[NW,i§Ûœ„:ã ÃtCW—À0@uaæ‚LXrçÉ9’¸MÖ~ýÅ‚‡æûÿ@˜ƒó1Òßβˆ°oo!dé8ûþ¸ö…1ÓBbÓ¼1]±z€]­t%U^:áÉà_D§ 8OÊÌz Ë–WàB7úHÂÜ ÀS¾Îé"Ðý­ÿ±ÅO¦U:û”á÷ÅÜݧ|éU¹N‘H!TKÜr%# q.ß“;ì+‚·ÐÀÑkæÙ&+æ50™œg)¨t±-f‚¾eõÃûtµÍ É»MJ€Žh£òØÞ~¤·ŸˆšˆgHDSÔ È8šö‡×NHdF\@¦óŠ¥½Øû`] Zg? 3^²«ä¾ Æ™‚ôcÁæÉ™"SGƒŽ8,¹u{>%¡©t D~—5,ûºë5­y•ÓvÓžâ:çôŠª`à”®ò_²¹SH[x2üʆwº»^Ú©˘³½(Å„ùš7ݤ¬Êv~{"ð™4.¢ÍÚ1OÚ®§4uÚsFBNy±;CÝõx‡Øç‚»k°7Ъœ`nýo7}YÕßn΢îÈÛ|V•`tøo Ü|…ß~iêUëÈ‹EI\!Ë^$˦ټ8<|xxW›|Lë<ü¿›í<{,ÓªÉgD!‡Ä7˜ñYÄK™•ø*QŒ@)ÚOì«ÞL™n-_Ûα{8Ä;ŸK¦Ð ö’· o íë*Kéö ®„éÂ1«1¸¨|ÆÑõÃÐr±ÂÐKRÓ[$YC+€¤ûŽÝk0·¬žU9S “¡*oªá݉¸39“Yú©À=:'Ê } ¿IúgÎI;˜ƒmÏ­ú5ë tgéB $/]ʺílËÄ9Í袴%ǽ^䳜·‹ÆÑ ‰›æt3÷L’—ÖûËÛÉhš$pÿÚKÀg@|ÆTä§LÌDäYÏrÃXeZ õTwšqJ2ëz^Œ×öT²Ã¬mëC½¶‡Óéñ÷ßóí7ã´Þ|v‹˜ø‰±Mróuþå" Þ•¬¥W|tÄ>¥ÆáØ›tÖlygÒ€¢î·+hÄÓœ¸ðã0aY_øaö?†± ұ뚸èš/Ñ)~C;9Œ‰UE5ýš3ÔI1™WÙº¼§?ÜÞwåf§ÆÝHç% /Z§N²LréfÓ¾(ô VËGƒK¼Ú0 N•)¼nFL⤥ƒ|#i‚·E ý.áO ªÎøt”Ͱ}¢'Ý:ýDÜjkè†oÕ*»#Ë7<]Ø*§`KHg³lQÌBr[êZãOšG¥ç|YÐ2èö@\lçyöå\CÑ×iõ©¨iÖBÐíéaÕ€EÌR¬¶ÞÐA”Ûž‚¥Y]Ê:(¤]¹Iq¥yÁ'ÊÔI³fdÎ3Hù½~ ¾ËahFÛ͆x!Ý¡ÃnЉm2¹Å#¡|¬P¹£™ÐTÂC 8~A?]4 ‚£E€¾À(éV?ËV 3‰m€ö°LüZÐŒ½b½­æ—…GÓÍQT+¡yÕ¤¥^\%ûÓ­;úú«=_'_ ´++ÞGð*¾c„¢k"žadÁÜÀˆÛd^ô˜…¹ÞÅÍä›3¯Oo&/zºD>Ë'7’ˆi’ƒ’r`vRÿëœa7©ÞrÁ=Teq7Œ%ˆ3 ÛDˆ “‡eN?gbª;—‘·Å³M“^â JƒÓ{PñG!Š):ØG×g†H˜c±eœxVw^².ý¿;š§–zBø"mÒi h&п¾½e³QÖœð‚õÏ ¥ê}‚B¹•®Œ§«³‚D 3ÍÓjÆ,f+B5îKZÝŨ zCÆjY€õtÛé´ÖÄq䇠ÉiÙ«‰‰3¯ë­i¬84RéÂcÏègž_T}È膤xwx+“IÓä}‘­òOÂ5?Ðøp{žyjKtzDÏ3YoÛ'”¢&('GeÕ4Pyo¤oóÊͳEº]51!ÑÀzØß´¼§Û"bë kª„Õ/Öìw,D^нD6%4 ¦ÜB‰´·ÚH$}kHú–NÓ$ #'yÛ|[Ép€2´[:]“EP›Ínß"=µËrä‚Ö&I¡œÎ¡½cäŽg«ìB"¤y1Þe÷Lˆ.úQd<ˆÜ²û  ª'Ñ{Zt,ŸRÚ~††´ hìȰ´{÷EÄ„%¿\ S™€?Ë5£¯yÊf_Ör… fŒsb½ ¬>Õàëó?ÖÕ Mc}ÊŠü–Ë®OŠìfƒ§Z;Àq}šÇàM*Dd’&¬6/€1 ×g˃‰1Ü®,˜P{š% šuN¿ÂoÀ»yZàçÆE¤K姗טæUDá›åXÅè(¼I¤ ÒÔM¾îû}ÁׇS‹, Þ@DÜ’”óÙìÀc\¬»ZlD³U )±xÒÔƒe°öÜ2€HÚE·ÐŽ«rE#•CÞdý'ý˜ÿj74ð­Ô‰!ÑN)ÜüŠÄOu‘Lh`8¦(™aÛ†­¬vF8×™½…{ÑdÍh.jeçb8Ks–²:ùí½#W Êé~fzê® ê‘ª«‚êèI€÷iÆ–³‹ÁC«â…È1gà‰"ÔÉ~Æ–µ)‹´ ñǹë{­rú¨º›Ì*60–]*g=TP°¹t$Â[ô$ÖÉI+£Çs&¼g²å|.Ëä ±Ü¯ËÍ’X «hs%O¦&"—-À VÒšVÊ“ðîNsr›ˆö>T&>p8šft ÓÕcë’°Ï*U‡®VÈ„ Lû𨿢£îÇŠ…~ÎeôÂOA7f1 ¤(\ ¿d Û5'}>†|á Áêf.Õ@Y„Ò=8&cŒˆt–¹6"ó–\šœùbíÆÏ‘»K˜*Ãm‹mè‘»E¸bžÛd…ÿÏïó¹|Ö¢s¼ýct{åÒóÑy!Òi[(‚„ó"o©îµüÊrL੊Þ º¼kD ¼VíÔtºÁ0>Ùè­Y€Ç­çk¢…È Þ°ÜWÍÚÇBÉÏœJA+Êæ'1´í>iËNN#Š÷Ÿ¨.¯ŒýRâ‡\ãðŠïb±U¿è˜g;FÔ§m²Buëôëxô”½”Í·1cÛá˜= ˆ€  Þ3¡?Çl2Ï‹-ÌcöX}ýX7°í!äjͱ{æM›§ZÿBdÃÇQì_`·+wæb ܧz3zÇãÈ­«7ÄA%,Šž«4(®Oßß½«lŠ’¨Z–èf¦³zH¬oå¼NÜzÀ.F¨æ€fˆ5PÔ%ž›Ès/=˜¸ÑqDbëÇz6O *q¥[ºuÌÓ¢U÷‰¨3z5‹á÷<¨™æ—dö¤:çМ9xÿ‚0Ú*O+¡c|=vÌÑûñúâüUróþæòúâôMϹ×D“AŽ«÷”¹/qö ¥¨·žXÆñ,‘Çߣ´Ý ǘ¬ƒ™DÍçÇ_~yt}92 «w ýôÏ#"`P_0nÓnë‹O^"HšóÏlÒ¦,`Òm놦DšsV0kT2íŒ1§2s“f ¨LúCrqÀ–6 X¿4/Ó"c›Ü5Â| òÞÐ}üpWŠÏ„½ó ,0Òb§j1Ô°|Ûw&æê>Sv®¯`ew@]¼;uäÔ—±v,–ž«y‘D à ºUˆLpæ}Ó=‰®A…1€Â.îQ ‚6À~AɉÈæ9A±æù‡æ0?e«r#Þùâ>§•3Sàà5¿16d3¹ë^Í]-À\¡¼|µo4À"¸;Kvp”N¢0“×7oߘjàüäüY‘ƒí—}81¼ÂóM‹;6jZh­:¯¾žñsÈBQh|É!Îç:=ö¦úù›sœíêwļ7LDMö1å«ô‚ ÊyœA ƒæ5z>ÿ‘Œ¿ÔÔ]£ÿ6ÚÙ±ßl² &ê³ÃÆ«ÇûB`„ሠ÷±‰Wæì ˜ÒµLšªôÕ4íÏÉ]]N.~JúpS'ß ‘ò<9Ÿ‹æäÏáöö}#AGge«(Þvp°ëdÐ Ô^aät›^ÎþÑ<­—~Ÿ!q±h\ â°òñÇÅõÀíjxô==#.–×3Tâ(oÓb›®èwîöVeXrZÝñi%Y{kò¼ã6`ɤ<Ñ-ã(äÛ[ÿ'ì™:Þ€K^@ÝX¤³ŒwáMX$iow*‹•¸TÎ!–ooG#@ƒe+f—>cШÝéjå7Ç‚¶ØM—Í#–úwtåæ I:[ f+=q"?àç3’€íø%Øyú Þçä}OŒÌ÷n’ôZÙA¤‘Žo®’£c7þñÂçá3ý`É!o2ÏÑÿ†8ן“R:sZ ()/îKèøõØM Ën|’>>´9W4¼O>âßz‡Ôˆf¨ ³úqðYÞÔã)û ÷÷0$#öÙá[œHš*¿#äG°¯bî(®Í>ãx‰d7^"X¹í;sâöSe5üÃy;“-ˆ­Ëg8tØËaÂN§£:ƒ#ÙÛàd®)ƒ«|-–-­±bG|d¹r¤kdç6¬vsܲLÚyÓ€÷Z±Î«F²€xØ­zè$„\DHbVhLªØ(èÎMÅG²ùB¹ác¶/¬[fê[Òm X3%;ò£ññ ã,D„wŒ-C€,Üe(H§µ*lóy¶ÿ è~$ásÔž$nß¾»úìH<¢¬ª e×Ôs£w±Ãóã”PwζÀØ5þÀèQXà4»Ë5O©7îEý¼´øW©cD*G°;Û.¨Ó-õ37´H\÷äÈQ2Þ=<¾Ë›C븾/H@^Õš0lçA(4› gO‹ün«fÿèˆ1•ÄäŽô“Xw!ó†O«Ær$9˜w’À(ß×(Œ¶Ã‚?7Í–é}^VbŒØÝ}ð7Ma´[$/ò¿Ac˜?s¥¹§­oÏ£nÆœµ’H¡V’ž¤ÑÔjiÙ+ìv>0N˜¶Èvg–âHñk†ä/›Q2ØZTe±ÛÒ,Ê»‚­£q&šBw§„azbêq"ZRÒ1ÙÂ|:Ú°•–üÐ,oþÚëDîÔQEãçÈjÞë)\Œ 8ÇóÅzgQ> ÇèÖ2èèWyeé!òc4P7ªæ9NýmPU­e(‘-µ î(­®Òô@¨AfØõȉ[_ò—D6AÓ±iÒ£_V¸‰.z ؃æ"ôR…4ñ%zLsæ~ÌØËãw•¿óÉl9²O-l-önüM2á‹CéAYu(1³%%è§0Œ‘Bóy¨¾`õ¸Fú?&÷õ89  @}—à$‰DÓú 4|I;§¤%èÅS–Ò$×§ôqpââímRª‰Š<ˆ÷0olß.}B’dRÌf[¶#‰Äc‹–iÜçoÈ _²òvEA°^UYˉÉX®qQwƒËÇ`)Œy‘¼,£øF@‡vj§ÕÎÍxf4ôF¿n´!…Àu€ÛÄ™yžFpïœúvŒqäj% ¡|­šî1O7-eÿ»ÞV–H ,-ÙO}È8—?c{´?°–›1U-­Ô‰Íàû®*¨>9ÝÄ‚¾JÃCŸsÄVÂö,N8ÈS±Kàæ!è+b̤4ZØçº u*0_—ãU09ý²/×aÅDd&É_§¿ò™^‰“(êâðNÁ†^½`{ëERóBôK^E' ¾œ²ÏA¢_¡)Õ¶—VœDä¥@à1Šãž©|Þ­ Á ü,F뤗üÔs“¬y"†â'Í'%S 0C‘R¡ $­7éßÞâF98pF/>Z§ŸýÐô¹$T˜~ƒh‹qg·ZU)âM{E:ŒI“v„:ìŸâèÇ”Ú.Rì$½‘мwQ¼SÛ‡ƒ0‹'„/ü".ü^¿7Ôø$ýg³U*¨IÂÆ–ô× ¨ÅryTÒŸg-X(RÌÁÒ¤åñ™'=1‹ô$|„½‚N –ÁUpø¶Á QC3?“©g&ýX/Ž|FT´Ãœ=æ¤Í—e9G.ü:¯ùZ†XœÃ‰&mj4ü°»«ôíïŶæh§4 g.ò>ß8D©—œ 8^šÍ»È30è@Õ…$$šÏÀû’%/f˜hLm'šB#“ÇÚÁJÞ7ѾS\ôd³SõÄÙSöDYŒ$ƒu]âœ-À- 'Kï@Г„í#MªHtÄŽæ #rw|¨š'fzS¹±GÇÏzC'% übýé gYç*½‹.FÖvG¯Ûà [Õ\víZ¹%:È3a†q†/Í^Ö2”Z )ñ1ÓòätÉQr´ô7'e Ò(Õÿ7˜»„9°{ÞÉÚsð™†2 &Ñýf*Q_™kÿöhàï\9"Ì›âS´þ¾]oÓ~Å Å{ÄUÁ,¥ŸC±,í]L¥Þ.X蜰n¨uP\P ®Ã›¤u ¢Ïfr(úñªq¦*¯Šš…ùÑž÷CÀ Þ8®.h¥ˆ€Ð¢ãQcWwjõ½û“Cƒ–…DÎ3äˆÙIÿlòçâʰ÷r§ä&ÏY eT+@…e Å{*þ¢Ì—gd¬ßéjª&À¤BšJ,ž%¾p$y…Ô¹>œö§‚Ò,G¸@±Í'Ý6%gÓ±6-v¯:*,àW9=I&%7Á#°5d«ÅˆÊŠP T€±ë½¢ëÔ³ý á*=øüçqÄŠë1aú/•ÜûªÁvJ £=ù Â?áŠþ³Ñ·C‰m±`<¦A-þ'–ÏØJˆ±À—Þ;šª4Q 9&{:=ª°]žfoægŸ·Œˆ‰É”hê¾åÍÓï&[¨fƒÿi­Ÿ¡*aÞ„7Ò²Ý0æ”j¡÷[ÎñÜ5ÖúἎ6X`&g+ÉàÞm¾|þÑnNw¼XÍØTMG 3û†¾ ¿ž¼>û¨ò>šØ l•¤†eä13¬Ò|%»”ÓÄa°É‰)Ñü€Exâ%Ø3ƒÁO¼©HØæ|Ë>†K„™tõHl¬x.¬†§š×ÝÙ²n€¤\ìARì›/æƒî衾Y4üÄ©^#SÃB~8¦ïXö 7Ñc¹tÄ—¤•¥\®êî<¬”ZÏ]r¤V¾î˜ä÷ VB2†—ˆ^ñôFá|FC«Hà¢c°ø™{æ7SAÓ4ˆ:ìNšÉ#&·ÿè²Ì¶­T–¤/rU¼A½fx½%‚ àUXeí)ÐÿîJ™dw"qm9.,×s×Y³­ IRa[yŸÁ@c¼$jt¡YyŠÈ[ràŒ´•«¼ñ /|®ÔaÑ]m0vö€s²Ñ--”¡=”ÕŠiªøBöØrëh;|A ’Ê‘©Rkš*'ãò†«V+ ªžÿ#ê˜Ô‚´—éXŒ0´ÖËFø ø]˜ªm À¹12ŸÛSK¥­ü¼‡çu¸f+ÒWµ+¨(KNä^8Ž×æ¶ÈcþÓðM|怕Œñ;0Wãmd¤Ü÷Mðñé“`aZÁQsG±Å[!u–Ñ£B›‹ÍY£ð‹KHŒòBâH³Tïñšéq}>i_cçÅÚÔó¥ÉÜç\­$ŒàË«û0xÈZ`ÙúÄN ãqÊÔdˆ1jªG5Ö¤÷eÎêË)B 6M©¹Àá ÈóÜ1¬ä gôí,‡8ŠÇÉ\åE¸âò0íýðh<ƒŒÃCÛf1úþ€™ÅL¥)ýK  <û¼àêcÆä’o¾}pÃt•ÏK»j8>(Q]j|•±àMX€b‚”B«÷Rrò%¿§K»r¡{±L7\†¡á¬¶¡â{úžï¤†dÒj/E´ýþ(é[üȃê¿­43-„‹Y1-¿;jBCàßä¡“ó «Æ&¨úZÉåžÿ¥¦ ¿9ûÛé›7|Bëô‘8}pvóóÕy”ª/±ÏAW²ºË ;áži ÌIãù5.`CúhLk *&ÀëlÁÐå,ÌT ¯ºÆ&4°KÛxº$ü¸A3}´Ì8Õ¹}”|ðõ\ý|óúòMýû}6L8¶ÃuI–¨?—lôÕÑCã1¢‹ü9wÏ1QÁ)pÅpx‹(ä!¯‡®U=Äb[Ç6NÎ9E9•}ŒSÿñÍéëaò«Ëÿ׳1žzQ?w«áõÔp¬‡áÓcž„’D[¾Ï%éI™…Ìô²âoï'yñÛôÜJžØ\b :Ÿ!þ(¨†ñ;‰âr|-8Ù5¡KÙZž)€ƒó¨¤öÖ,¹Zkmttüí±iHÆìE»¦‹À+¹–þ^eîbr9úþûoÑ]~·ÁèhM»ð5¦VÌxä¥b¼öÐ7ZÚ,Ýî±ä‰*Öš74sœ0µbV€׺#5j¶*DÀá×äO'g>A¹ Z¤ë–Û k£“’AOy’¬¢x’¸. Áq3vxZX‘)¶m®ô¨ŒÅj–ÿ Ío^HAõ¥›*ÖŠHÁ°v/$ŠS3×ùŸŽ$ÙV ö§Âpíe¥á±¶—1Кa ^ŽßôœÞ Åöíì¾9&ÑèâšíÑk<»þÏ!q¬YêO5jr“oâo苞¹Ö$ÏŸ½„Ј˵í‹/ãÙ†ü„º}Y\I‘d>]go‡ÒM”ð›‹xóy 68¨9³ìÀÊzs°ñgM¶ô'KòÿºÍ[Hó86‹`;a¶=!äã=¬ÿ†ia¶ÊÒê…»¹hþœ£t޶¨”˜ëÕ*Ö{DänµlùCœYQKªh'ÃÅ^ØŒÎʃà¥,Ïs5Ï2Þ$£„\RÂ2?Š¿¯6½‹·T‡ççÍV¥ökB\ÍÁuëiÑu¸(¤Ò•TŒ?’ñý¾Ø”4åëü§Ó·WoÎ'R)r;ãsÝ´Bc)%ÑAYU(¸ýó¬­Û(jú×Â`#±³ošjX9™n‘;%õÜþ[Y{jo'ÄÕŽgç×c ‚±Y9l÷¹äÊfëtæÓt&O¯%Ž ˆ­³Éá¶®ëjv¸BÙƒÑóñÑz>j7•X¹vÉ/Mòð±{FÐØ¯ÕžfI?nÆAÀ‹C(Tñ…ÖµÔuäÔî†ð!Ob'‚6¾Ž£‘X µr†»q'Œœ—!Â¥µ)­8®o’ñoÚ‘–n;’öœ¸8’¤[€A äßHZôF¬Á¨¬e´ã"­ƒ§—¢¹¨ëGšÅ¯.…ŸúMSÆ5&|T&N!cWßÛ7iPªÃ¾,w—±Œþ†¸©1•¸Ø¾°´¸ ño[_‹xå7É}c¢h_ß”É~‰kšŒQA\gééy£kRDV{釘õCñ…-§:38žMþü›Â0|?Í—·Ð5zÅ–luÕ‰‹‚5\(‡O,ku±oñÉÓú—Ý# »¯KòÅp5ˆÕ©³òõû]Èí,dƒ*¼^Ebk±T]š»¡nŸåw‚Rl|5§9†«NŠiH´/—Øž-K$Ðä‘6k%šÏÐuƇfIC t·ê·}Â'pvÊk†L0š¾í NÄuòôyLÎöžÈ0‰¹òÞIúEiç€mâchY-»åÓ˜¸*„ø°µp¶Uï ÷†S]­îŒ+(‘²Àù‰;$ûÛ–oñ¾3YÜM(ó¶\n0ò?ÊZ8Ü ”JÇ[¾Q»V#ìåÁJrÇUKˆBÓä9Ò&î$vo’Þ§E‘.Nâg$ú5TCUÜoÙªØ Æ²Ç̃¾ÿe¶ük{‹Æ3~ùxù+‚Ò’=°ôvxï‘Ðê-òªS˜££å,ÅŒ$:F«ƒšØ‹Ù:æüôjcûÿÐuæK®ìôèB(5\QX|ÈâÛ?×øZ˜f×. ~{[dûÊ§Î§ÙøjlêÐÔµEé5⺃0nùF»…Ô%f"Ôè|`†N[èZ4cùãW…_«Øm77,Ê ‹“‹ØÕ9Jꦎ,{Êç¦IÀ7ŒÉñ¬>.®ƒ£µ³ ÛµˆÞÊÿÐK€|ãL·°œ¾”~g_X ¶ß‰AÇ2t|Îûz4€ýÆÇý‘ГZ7p,*ˆƒvõ9èÑí}"µeG±Uy½Vâ Ú<Ã⨽ŸÛAmRÂe¨ãðQ³ä‹mJCk]ÜŽ¨]/k@!“Š0bòÙ£º±åÂ’~ãš¶q¥F‘&Çôh],É:àGÑà2R,­úÍãÆzºâ<µ;ýÌÊ+ª™Ç/d¸ÏµÂ~ëhÒÒùu9é>ûæœÄMWïä*ë™e3¬- ý#Ù-p“ôð}åÇØÙ(&5šÛåü7X™±0r¨¤{gÅÒè‘–éÆî„•î«— W^C×{ñ»ðÐÈdÚ[~o( .d¡{ñy]™™-Â/B–x|Ð¥ÆãDzK 18"¯W\¤Ðïqb¤iÖÙv^¶„-Fo‘,M‚ ñwZ2ª0¬QÇöR¾4A~wÒ¬…þ¸h22?¸ÛŒí–Z¢ÙtZûèA‰“8y?š0*uuZ‡g¹M|Iæ½ÔšçšT\éj\0VŽeöÇ‚«~DF¹”ÓùòÎ{ŽãaÐMTÊN®èùCÁ Â™ ôå»ö—η#Bôn¢#T=…k)Lå³l+éÊ8 NcO3Qˆ4µR&‰cAÖæXÒq„¹¢gÆúëÏ’­ô:¸XìñlçQo n=bBŽÑ€N¾oŸiÛ®+ÇF9gEY%÷ìZ=¼áAžÄ‚Ë.ý쫆¶‹peö>Ízáê¤2©VÝ¥tJs ›>w&<Ê–„‘úL\¾0ìÁ ÉœœèÔÏÌåÚ95–«¦h7¡„¶«Þ/!Ù:ÖëŠÇäç§é?df¹6HM¦3aÑÆ ú‘—¢†AÚÖÀ¸IîZ«[4Ö­À19w…çÐïÇS’SŽ“ˆÁµ,·`x×S°vçœ?¸ñv ©½½a<>' »ähˆø‡¹ ”úB9à üÅ+Ô ª“xH„•¤Éˆ{¥ƒ?Ø¢G]Õ™3ÁÇuNÆ;á:fòˆ7šóº»1Q¬;HpkVjJè,ÂLj Å}»tÜP3 }>¶uô¬ŸY£;ga¾k¼Ëmw9@ñEúݺ̗ËõŒòíè3?Ñs^ê„§@.í’cú»± ïÅ0ÙßñøúÜšß6ºZ«R®“1ú”=a%§À•ì…š­Þ&žMð,dÇÐÓqAýÆGªoµ&F–œOÎðø€[Y‰Ý•åÈTÖ »/ãlÀäúüæýõ;Á2® Óuë.ô œCueÇŠ*äâÃó§",×QŠRóXS£ƒIª„t+}ÛØ I>&›lh6È›Åà@ç4L­¢Â1íÌqó…³úç{1Áö$¶¨¹ß)-j¬û:ÃQ¶‚…ëâÚÃ*ë ¹Sšy[Cs«Íáó«ßAÞ¬_¾/…¯É¾Øoîc5xƒÁÓê"a!`6bü“’÷+¡æÇ@}QIü8‰æá¶ê½Ä x´÷ .ÛÓNÒÈ qãX¡LãViˆS”¶ÑåûxëúgR¡†þi? HâÔy³'¥I™ŒoJθ©# Æîl´ÕÑ“¾Ö¿¡Of{ÞCÔ¯½!>ò„'ÏEªOÅmÛ:!bè_$½KUIAsö­‚ ¯¢—¯ ‹Ð _áöÙÂø½¹TòÀÆ®CB½à^ È¡x ú!wFFZ‡®_g2btW6¥¤‚Œ~µÒ|•SÒ`o xf£cØšÒw%j-×õClŒÝûš8"ß˧—ÊPušõ¯%b ØÍ_‡†Ì>‰¥Ûÿ{(e]„÷ʃ>üŠy§¦tRÎkP)àA°WœóïÄŠžâu\~'5„EèðœÞm—¦ê´^®ˆU¢ÖMѶ£Ž;ÒhÔ ó"¸~_F®ßóÈõ›ô/^ž×ƒž×òûÌ× >–¶èðy²JIÔfÒܬ¶wUïøÙåÛ·—ï’ç§ÿþîœfrþîýÛóëSTI•>ÏÞ:ô«¡7p{›ÊÂWŠ Q¡‰½zÚ7H£¬|—…ÎlqÜïŒKÆäá)´.@+$'n¥,~ô¡0!®£I yüHÈ”ÎY›U™7|˜Ov/™/9a°º—Z.¾c»E¡2®–‹’Ô]‹9,êàÀõ­&öì!¯ó¦ÊÆeuwÈêé?Ø1 ö•ÂæÌRŽ|Ý;ÐNIÞVyUÔ‡ýŸê·ÌJV¸#ý¯µïôW#¥ÏYãÄ/‹‡ : Ò dZkMæ ºŽØe(Ù¨ ÂåFš?‡{Šcò±ÝÞ*³#UüÑG4sGiLù‹Ɔ g‡ÆÜ··g«´®‰Éý(¿½$Ô‚.‡E#’GUo¶­¬ÅÄ“Š¿ª3…ÿRÍF„/{m¼76ÔÝ"®õHƒuN_Ñwá[–œCÿöâæú\c_¹^»Å['üde 8ÒUFªÒbÂj<Šâì‚Á“X§Ò¦S"Žp/HƒZ­2T ;I섉÷ÆKku¨dï«SH#”WêË‚úÁ—¹tTÆi6ZÒtÙšF­ej;óe û™Á›D‚ì™Ç(ŽÇ€f.Öø¬E:ÿŒà'&k˜¶uTêTŒøøîC3¸÷üÔaLƬ…4æsK’‰Ûâiå{û=€£K/` œ‡e)½à,ç-‹‹$Ñ['§ï& z{+÷øÙÑQòϡ玿=Dn*7H6Ø×+“Bit>oTeåf¥­ D×=à“Ê•ø¢…¶(æ›èÏô>ÆÒû¤%ã<YùLŒ¨H"(6Ž?|å,a$YûÒ¡ ›0W™·r‹F 4nC'ah¿ÂVA~Ù¬%ø†·˜Ó0~C:¶r¥mñ†öZ}a7*‰-¦þ±åÜ.;k%®4` ‡™tчü‡M³‡å)—þ¯Íã¸ÛpîÒ”+.~A`èw½H•–=®½jaÅ0•ÞÌçãDTãüÊ鵡¾™1 éåå+…°zR{Å+vôÃïÃ…j«VíÝÏkh@j;¥Iÿb2úßLÖ>R˜ºøÕÏÿp|(ÿýîw;¯Öh]1-TŸîŒNô‹#›e‚k>¤È¸6‹`°··ºéó£œøßI.(§´áE›xDÆk}NÏ ]뇿ÛCB°}‰Ìtô/<ÂÅŠ:°˜°~)öWÚÆ‚¼Ùôg«xo‰‰y½‚N‰òDõ²¢ ì_Ö[1Ï¥<éS‰p eqC{>iû:Ϲ2È–F÷ùÅF®ÁB+žÐEÚ-©¬ÙŒp{ÈK\7ßòlü"¯´EÚÿÙÒM:~ÎÅó¿„Ü_Sœõ­ÊuZò-j ÀÝ…bÆë;ÇI°½•ÐT0qðÿÏz˜š fFÐÁ‚к>Ô²Uú«æ VkZšGάÒÍ4ë\Iÿ½dS\…‚âÉK_Pü•Fü „Y(K°`î4íZ‚x¬ [›/û-bGþ†+«!ÅUØ X˜Ì%$*´ÛâÜZu·º Ÿú[ÉP3‰$3]I§Fák{J¾’¹ŸÛ̪ÙÅëÊpøE|ƒÕÚ ÿÜÛÒøÖsúj[SYÖÌ+ŽÃ6²çËÂ%¿vûcqg ¾GÏžý/iDÛy¸ÈîÒ}wˆ0SxbݱTéF¼_K¿8ÿLTS}ˆ$ÞÞã”\!3}EãÕíß=?þŽæ%ø"M~¬Ðu/ºFÛÅä¬zÜ43Ü,iN­BFçÝ„×9cÏW˜†È§É2S$ROOÎSÈ䱘-«²0’¤¿FB! (ŠýA?ÿî;쎶µ»ÉPkDa¿ö“„žü꾌ž:Kúî9®¥¥J'W€‚Raë´Ç[+¾¦ÊYûÕuúþÛ0ÜÓ·‡QÂ×jo÷ÄøVªj.‚o—€Ð2×xø-7àøÙ¡¾·³kß?£]»ÎVyÊqAäaEa.$Ùƒ“þ&Æã_[¨wwæûãxg´62úôê"RÖ)Y C«Œ¸ ðÈW­ #ãi@|-=°ÖôÒRÚ³2-9 °õ Ä¦û#œÚDÕѬ†$—nôÙ-,;Œ#t-sÙÐIzj\+v'èUcÕɳo !ôÛÛ¢ÿTÑ ô.2ç;¬8hnžlK_Q¿"öÏa^})ÇŸn[ðsZSL=¡™Xƒ/¥Ìµl–ÖHؤ¿k·Ôòw%Lkñi¤;ŠQ›mM:Áƒ»]-s‚sÙnëß(I³}Âé§Ôáîãå:Ûi ±§~°åâÄvp+’ù£,ù—þ,•Ê Gz…€ô8&D‰K¹b‰ 3¼“sgüZéÿm!Y|LÂÁ¡5NÞ³SÀ˜_!Q V½øÔ«0ÝîUB5îþ)E4Z6šªŠjiʬյ»-Ê1ø]Ñös~ ‡(Š¿®õÚ„{wÅqµi»¼‘võ‚¢`Î%ñw¶š@Åmv5Ôx·“—7˜½?~¦­Hyçmáf[ªÎ‚)ƒuGSñÚ^[OÜ~­_­œ2 ñ2©1‚;!ר[²ÚšDòTÔŽ,é·+ˆû½â÷¨Èú€$-•²ߨshj©m×5vÚ©[ïO:ù§xªõuô' ôd´` oùÔm1Ò®Í˱´¥Bš+%ª\й„/“ÑîÛG÷<¼Ó‘‰Ñ¹=Y!Á'/—CákhÕöÊ, ŽÅÖþ#–mur.\ä«c™y\ŠÜÅþP鱡…h/¤Ð%Û!|xÏð÷DF驇¨9ÛäiÖYSãÍP\‚D¯·¹‘mO»æÝ@c „1к¤Õ‹Ñ£âÕ.•9FU 9ZÎÂZ…þ9¢Ï·*híwÐØ°`6ŒŒŸÇöúÜF 48´©ljÒÓvûl¼à­&]r*‰ÅEµI …®Ó*“†¾„˜˜«$$e"öZÕĶøèaêG :*2' ň³Æ_jŽ« iU}ÒÚ“û^ª3 å_ÙÇø×„áPX+«#`s¯.XÏßqÙ[;è xµßÐXÝ×ñ‡xK1Þ/Õþ=ÄP8ö\¡$Ç̉MøóŽÙ¨,ÆÅU'4Ò£q0P!œùç¡r")‚Hcv#lÜ˧v˜Õ‡ß°Ã¾¦XÐ88½M¶£¾Óê>6#XQï™PÈ”¬LÈÖ½Üß„}¤µæ-üåYÌR¼¿o{Œ¬–tÌB§\,¬.·k¶ÿqL¿ØEA–5ï"éÇá(Ù“æ œýÈ÷‰/…]eêS cÑÀJ jAÕ@Sz)Q%bbйހ]«¤o'YsÈŽ™4 tµ%Ÿ*Êže¯E.¯­¡uÞ)Ø|Ñ4³P7óC¡æÐåU¢9»tå„Kxç¯äœ^,â.¤’ý¢Š?LªQå ™üNïTîO&%cmq7qı½c >Cñü äTqÁiNsS4§€0>Ȟ綾ÜVˆ±š™ê}SÑñó¾^c;Öª(‹ÌîÇÊªâæ‡Ü*•˜A>ãÀEÝ©5îåc +á•-rÆÙ$CÏ{Î:aŸ¨­±xŒ¤Áñy¥Y¤5ßšbžÉ-ñ‡sJ8}hÅU-p¿Õ*×—÷-Ä}È~ݶº]a‘O5˜µÖ]B5y·PÃõZpF=hðþZn=[ þ”7¯·Óaœ`?ìdØk|| ®SX‹(ë§qoX“ªn}ƒ¼Š¨ó)Ú¦cVè¸0ãÒ«±3ÕŸéÛ­–jÓ‘ 7Û6y`¹Y{걪;Iclxc'«lÜÞ¦´ÀŸqø¾˜GxºÃvÓOè×}Ú 8*¯+怅‹m蜤(àu–/¡£ï=¬ìÈ ìÄÇ¡ö®ÖNà+†èN(ãn]Ò‹Cµwn›!aÅÖ¹6ªUVûF ³%Ò½ö¾hG©Hè¼rŠíFá!¶Ì9Tl塜~Å2ɲiÜÕ~¼‡B”o·Ð=gGvÂéEÀy% é“þ)g\á<2ͪU9vûa°–g£’ÅTq‰{Ó¯j)½1#²ÿã¹Pòt»jR‹þ)ìHYýuï¶’nÅéAVÄ&@m ÷Ç?râ{.4ü`ð4ÃÊ“d§&~¤N:óRÑ!Ë/wúì†Ø4Ç•†½ä·ò=ÚuS‹˜YÈë-#ª&­uÖÑ@zðä^û«¦ª\êÕª퉉bÇ^©ºøÐÈb³BÿeN¥c›kŒNJè+nj۟ŠaÞFI‘®¿%|šíh/Ùú¨c·¶íÃþFÉ7­v§ ¼2 ­cékÄð0è´bpÇ R"3T3 Š?³¬ààgÙµ¦ÆH³&U–Û¶ •‹¬Ö«Á=Xv’¼¶èÑ*{PÑ™º'mÏaÈ"iý nʼnFÃb5Cîaú iÀIëj:ã¦ô #â81²«©ëÓi4¯÷5‚¾[•Ót™ù%²[3—¤]G ”óyíÛÊq)–}ÒU†^Æfb[™ (Óôêã:¯·µ7NÂÚ- Co¥B?tø ؅誀¾ra°±×Ye¶Ñ` °1Ç­wXèQfÁ=$²é‚ V†PåsɯŸK߇©mX¾5Ak7L <ú°v yßyÎM u9 Î’›ÌEb~¹¨;ð,×c{âÑap¨Ô¦ý¸¸ÞÊ•I£ËIJ¾–:«ì3®·W;Á÷$‡ïÆåû/ö0ÞÀĹ¼ˆÚ±îPuùsÓ·ÒCsý|ÐJt`—ž‡Qÿ„0"m²¤ª¦È=Ëø^É5‹tW{óAoP4œŸÐ2ï ’¯=Úé÷¦YO’ÏB:¦/:õO¬Wâ:ñ+DÅÜC%i[j’¾%M^E‹{ß»@µ}͸$¾2…2¬ 6v±RoÊü‰òÃH_Õ­NB…ó0¼JÄ´+n úQcÇU‡ †X]¿ËqýEºDBÚ*8£'Űˆ‹ìYä]‰ |ÇõzÔI̼ÒÌ`.¸ž„çˆñë¦*ÿäTVÐNžðÂ…ÚeN Aù©Yrr$fJ†G^bõ#ÿOí S9 Lkÿˆ®"NnÉ\ yk¨vaq¶‰tö¶å>ÕÆaàÑ*}TŸ‘Ù ?Ñܲ•/û®išå+ÉhðjKE…¸Yo´%UUùÂý‚A‹åú+,þÈ\È䲸f£díBÙ¢Þ¤¹…’c\c³1ißvÅ<ú_­*-Œ¬ýÍꦴöM/ªÀ•Ò9B…±mñþ¯`t’]]I¢•–öT‰ªôÖ †ÝRzô¤]æ:³¢$ûfÉ2£áð/ip¤f>a@ \†‘kž&=ÞZ;zòÄ<”t>\T®78 ñã˜(¥aGˆf•ŽnÚ™ZÚ60ײ4W°šÂÃíŸ1ò ¿B|iÇ-G?t¡r$ß⸖*hHZZ(LÝ) €óyÂ!„%ÜèeéíNÂèH‚x}i1íM’æâƒã`@š?,iêa¶á>ªu·¹¨™ OåVþDÕªv€¬¡o‚ì„ëMÎÏ“Ó7“Ëž›d;uɲi óÌS±§±ŠÕŠ+ ™n|A/å•ÂY¬êõå‡z)ÝšñÅuÒû-¡­½D'}úþæõåµ{™ÞÓ–Ž“ò›¤o¿þ·xº0ÿã~!—ÈØflawfinder-2.0.19/flawfinder.1000644 000765 000024 00000157650 14056170364 017115 0ustar00dwheelerstaff000000 000000 '\" .\" (C) Copyright 2001-2018 David A. Wheeler (dwheeler@dwheeler.com) .\" .\" This program is free software; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by .\" the Free Software Foundation; either version 2 of the License, or .\" (at your option) any later version. .\" .\" This program 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 General Public License for more details. .\" .\" You should have received a copy of the GNU General Public License .\" along with this program; if not, write to the Free Software .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA .\" .\" .\" .\" Man page created 17 May 2001 by David A. Wheeler (dwheeler@dwheeler.com) .\" .TH FLAWFINDER 1 "3 Jun 2021" "Flawfinder" "Flawfinder" .SH NAME flawfinder \- lexically find potential security flaws ("hits") in source code .SH SYNOPSIS .B flawfinder .\" Documentation: .RB [ \-\-help | \-h ] .RB [ \-\-version ] .RB [ \-\-listrules ] .br .\" Selecting Input Data: .RB [ \-\-allowlink ] .RB [ \-\-followdotdir ] .RB [ \-\-nolink ] .br .RB [ \-\-patch=\fIfilename\fR | \-P\ \fIfilename\fR ] .br .\" Selecting Hits to Display: .RB [ \-\-inputs | \-I ] [ \fB\-\-minlevel=\fR\fIX\fR | \fB\-m\fR\ \fIX\fR ] .RB [ \-\-falsepositive | \-F ] .br .RB [ \-\-neverignore | \-n ] .br [\fB\-\-regex=\fR\fIPATTERN\fR | \fB\-e\fR \fIPATTERN\fR] .br .\" Selecting Output Format: .RB [ \-\-context | \-c ] .RB [ \-\-columns | \-C ] .RB [ \-\-csv ] .RB [ \-\-dataonly | \-D ] .RB [ \-\-html | \-H ] .RB [ \-\-immediate | -i ] .RB [ \-\-sarif ] .RB [ \-\-singleline | \-S ] .RB [ \-\-omittime ] .RB [ \-\-quiet | \-Q ] .RB [ \-\-error-level=\fRLEVEL\fR ] .br .\" Managing hit list. [\fB\-\-loadhitlist=\fR\fIF\fR] [\fB\-\-savehitlist=\fR\fIF\fR] [\fB\-\-diffhitlist=\fR\fIF\fR] .br .RB [ \-\- ] .I [ source code file or source root directory ]+ .SH DESCRIPTION .PP Flawfinder searches through C/C++ source code looking for potential security flaws. To run flawfinder, simply give flawfinder a list of directories or files. For each directory given, all files that have C/C++ filename extensions in that directory (and its subdirectories, recursively) will be examined. Thus, for most projects, simply give flawfinder the name of the source code's topmost directory (use ``.'' for the current directory), and flawfinder will examine all of the project's C/C++ source code. Flawfinder does \fInot\fR require that you be able to build your software, so it can be used even with incomplete source code. If you only want to have \fIchanges\fR reviewed, save a unified diff of those changes (created by GNU "diff -u" or "svn diff" or "git diff") in a patch file and use the \-\-patch (\-P) option. .PP Flawfinder will produce a list of ``hits'' (potential security flaws, also called findings), sorted by risk; the riskiest hits are shown first. The risk level is shown inside square brackets and varies from 0, very little risk, to 5, great risk. This risk level depends not only on the function, but on the values of the parameters of the function. For example, constant strings are often less risky than fully variable strings in many contexts, and in those contexts the hit will have a lower risk level. Flawfinder knows about gettext (a common library for internationalized programs) and will treat constant strings passed through gettext as though they were constant strings; this reduces the number of false hits in internationalized programs. Flawfinder will do the same sort of thing with _T() and _TEXT(), common Microsoft macros for handling internationalized programs. .\" For more info, see: http://www.rpi.edu/~pudeyo/articles/unicode.html Flawfinder correctly ignores text inside comments and strings. Normally flawfinder shows all hits with a risk level of at least 1, but you can use the \-\-minlevel option to show only hits with higher risk levels if you wish. Hit descriptions also note the relevant Common Weakness Enumeration (CWE) identifier(s) in parentheses, as discussed below. Flawfinder is officially CWE-Compatible. Hit descriptions with "[MS-banned]" indicate functions that are in the banned list of functions released by Microsoft; see http://msdn.microsoft.com/en-us/library/bb288454.aspx for more information about banned functions. .PP Not every hit (aka finding) is actually a security vulnerability, and not every security vulnerability is necessarily found. Nevertheless, flawfinder can be an aid in finding and removing security vulnerabilities. A common way to use flawfinder is to first apply flawfinder to a set of source code and examine the highest-risk items. Then, use \-\-inputs to examine the input locations, and check to make sure that only legal and safe input values are accepted from untrusted users. .PP Once you've audited a program, you can mark source code lines that are actually fine but cause spurious warnings so that flawfinder will stop complaining about them. To mark a line so that these warnings are suppressed, put a specially-formatted comment either on the same line (after the source code) or all by itself in the previous line. The comment must have one of the two following formats: .IP \(bu // Flawfinder: ignore .IP \(bu /* Flawfinder: ignore */ .PP For compatibility's sake, you can replace "Flawfinder:" with "ITS4:" or "RATS:" in these specially-formatted comments. Since it's possible that such lines are wrong, you can use the \-\-neverignore option, which causes flawfinder to never ignore any line no matter what the comment directives say (more confusingly, \-\-neverignore ignores the ignores). .PP Flawfinder uses an internal database called the ``ruleset''; the ruleset identifies functions that are common causes of security flaws. The standard ruleset includes a large number of different potential problems, including both general issues that can impact any C/C++ program, as well as a number of specific Unix-like and Windows functions that are especially problematic. The \-\-listrules option reports the list of current rules and their default risk levels. As noted above, every potential security flaw found in a given source code file (matching an entry in the ruleset) is called a ``hit,'' and the set of hits found during any particular run of the program is called the ``hitlist.'' Hitlists can be saved (using \-\-savehitlist), reloaded back for redisplay (using \-\-loadhitlist), and you can show only the hits that are different from another run (using \-\-diffhitlist). .PP Flawfinder is a simple tool, leading to some fundamental pros and cons. Flawfinder works by doing simple lexical tokenization (skipping comments and correctly tokenizing strings), looking for token matches to the database (particularly to find function calls). Flawfinder is thus similar to RATS and ITS4, which also use simple lexical tokenization. Flawfinder then examines the text of the function parameters to estimate risk. Unlike tools such as splint, gcc's warning flags, and clang, flawfinder does \fInot\fR use or have access to information about control flow, data flow, or data types when searching for potential vulnerabilities or estimating the level of risk. Thus, flawfinder will necessarily produce many false positives for vulnerabilities and fail to report many vulnerabilities. On the other hand, flawfinder can find vulnerabilities in programs that cannot be built or cannot be linked. It can often work with programs that cannot even be compiled (at least by the reviewer's tools). Flawfinder also doesn't get as confused by macro definitions and other oddities that more sophisticated tools have trouble with. Flawfinder can also be useful as a simple introduction to static analysis tools in general, since it is easy to start using and easy to understand. .PP Any filename given on the command line will be examined (even if it doesn't have a usual C/C++ filename extension); thus you can force flawfinder to examine any specific files you desire. While searching directories recursively, flawfinder only opens and examines regular files that have C/C++ filename extensions. Flawfinder presumes that files are C/C++ files if they have the extensions ".c", ".h", ".ec", ".ecp", ".pgc", ".C", ".cpp", ".CPP", ".cxx", ".c++", ".cc", ".CC", ".pcc", ".hpp", or ".H". The filename ``\-'' means the standard input. To prevent security problems, special files (such as device special files and named pipes) are always skipped, and by default symbolic links are skipped (the \-\-allowlink option follows symbolic links). .PP After the list of hits is a brief summary of the results (use -D to remove this information). It will show the number of hits, lines analyzed (as reported by wc \-l), and the physical source lines of code (SLOC) analyzed. A physical SLOC is a non-blank, non-comment line. It will then show the number of hits at each level; note that there will never be a hit at a level lower than minlevel (1 by default). Thus, "[0] 0 [1] 9" means that at level 0 there were 0 hits reported, and at level 1 there were 9 hits reported. It will next show the number of hits at a given level or larger (so level 3+ has the sum of the number of hits at level 3, 4, and 5). Thus, an entry of "[0+] 37" shows that at level 0 or higher there were 37 hits (the 0+ entry will always be the same as the "hits" number above). Hits per KSLOC is next shown; this is each of the "level or higher" values multiplied by 1000 and divided by the physical SLOC. If symlinks were skipped, the count of those is reported. If hits were suppressed (using the "ignore" directive in source code comments as described above), the number suppressed is reported. The minimum risk level to be included in the report is displayed; by default this is 1 (use \-\-minlevel to change this). The summary ends with important reminders: Not every hit is necessarily a security vulnerability, and there may be other security vulnerabilities not reported by the tool. .PP Flawfinder can easily integrate into a continuous integration system. You might want to check out the \-\-error\-level option to help do that, e.g., using \-\-error\-level=4 will cause an error to be returned if flawfinder finds a vulnerability of level 4 or higher. .PP Flawfinder is released under the GNU GPL license version 2 or later (GPLv2+). .PP Flawfinder works similarly to another program, ITS4, which is not fully open source software (as defined in the Open Source Definition) nor free software (as defined by the Free Software Foundation). The author of Flawfinder has never seen ITS4's source code. Flawfinder is similar in many ways to RATS, if you are familiar with RATS. .SH "BRIEF TUTORIAL" Here's a brief example of how flawfinder might be used. Imagine that you have the C/C++ source code for some program named xyzzy (which you may or may not have written), and you're searching for security vulnerabilities (so you can fix them before customers encounter the vulnerabilities). For this tutorial, I'll assume that you're using a Unix-like system, such as Linux, OpenBSD, or MacOS X. .PP If the source code is in a subdirectory named xyzzy, you would probably start by opening a text window and using flawfinder's default settings, to analyze the program and report a prioritized list of potential security vulnerabilities (the ``less'' just makes sure the results stay on the screen): .RS flawfinder xyzzy | less .RE .PP At this point, you will see a large number of entries. Each entry has a filename, a colon, a line number, a risk level in brackets (where 5 is the most risky), a category, the name of the function, and a description of why flawfinder thinks the line is a vulnerability. Flawfinder normally sorts by risk level, showing the riskiest items first; if you have limited time, it's probably best to start working on the riskiest items and continue until you run out of time. If you want to limit the display to risks with only a certain risk level or higher, use the \-\-minlevel option. If you're getting an extraordinary number of false positives because variable names look like dangerous function names, use the \-F option to remove reports about them. If you don't understand the error message, please see documents such as the .UR "https://dwheeler.com/secure-programs" .I "Secure Programming HOWTO" .UE at https://dwheeler.com/secure-programs which provides more information on writing secure programs. .PP Once you identify the problem and understand it, you can fix it. Occasionally you may want to re-do the analysis, both because the line numbers will change \fIand\fP to make sure that the new code doesn't introduce yet a different vulnerability. .PP If you've determined that some line isn't really a problem, and you're sure of it, you can insert just before or on the offending line a comment like .RS /* Flawfinder: ignore */ .RE to keep them from showing up in the output. .PP Once you've done that, you should go back and search for the program's inputs, to make sure that the program strongly filters any of its untrusted inputs. Flawfinder can identify many program inputs by using the \-\-inputs option, like this: .RS flawfinder \-\-inputs xyzzy .RE .PP Flawfinder can integrate well with text editors and integrated development environments; see the examples for more information. .PP Flawfinder includes many other options, including ones to create HTML versions of the output (useful for prettier displays) and OASIS Static Analysis Results Interchange Format (SARIF) output. The next section describes those options in more detail. .SH OPTIONS Flawfinder has a number of options, which can be grouped into options that control its own documentation, select input data, select which hits to display, select the output format, and perform hitlist management. The commonly-used flawfinder options support the standard option syntax defined in the POSIX (Issue 7, 2013 Edition) section ``Utility Conventions''. Flawfinder also supports the GNU long options (double-dash options of form \-\-\fIoption\fR) as defined in the \fIGNU C Library Reference Manual\fR ``Program Argument Syntax Conventions'' and \fIGNU Coding Standards\fR ``Standards for Command Line Interfaces''. Long option arguments can be provided as ``--name=value'' or ``-name value''. All options can be accessed using the more readable GNU long option conventions; some less commonly used options can \fIonly\fR be accessed using long option conventions. .SS "Documentation" .TP 12 .BI \-\-help .TP .BI \-h .\" Leave -? undocumented... it also invokes help. Show usage (help) information. .TP .BI \-\-version Shows (just) the version number and exits. .TP 12 .BI \-\-listrules List the terms (tokens) that trigger further examination, their default risk level, and the default warning (including the CWE identifier(s), if applicable), all tab-separated. The terms are primarily names of potentially-dangerous functions. Note that the reported risk level and warning for some specific code may be different than the default, depending on how the term is used. Combine with \-D if you do not want the usual header. Flawfinder version 1.29 changed the separator from spaces to tabs, and added the default warning field. .SS "Selecting Input Data" .TP 12 .BI \-\-allowlink Allow the use of symbolic links; normally symbolic links are skipped. Don't use this option if you're analyzing code by others; attackers could do many things to cause problems for an analysis with this option enabled. For example, an attacker could insert symbolic links to files such as /etc/passwd (leaking information about the file) or create a circular loop, which would cause flawfinder to run ``forever''. Another problem with enabling this option is that if the same file is referenced multiple times using symbolic links, it will be analyzed multiple times (and thus reported multiple times). Note that flawfinder already includes some protection against symbolic links to special file types such as device file types (e.g., /dev/zero or C:\\mystuff\\com1). Note that for flawfinder version 1.01 and before, this was the default. .TP .BI \-\-followdotdir Enter directories whose names begin with ".". Normally such directories are ignored, since they normally include version control private data (such as .git/ or .svn/), build metadata (such as .makepp), configuration information, and so on. .TP .BI \-\-nolink Ignored. Historically this disabled following symbolic links; this behavior is now the default. .TP 12 \fB\-\-patch=\fR\fIpatchfile\fR .TP \fB\-P\fR \fIpatchfile\fR Examine the selected files or directories, but only report hits in lines that are added or modified as described in the given patch file. The patch file must be in a recognized unified diff format (e.g., the output of GNU "diff -u old new", "svn diff", or "git diff [commit]"). Flawfinder assumes that the patch has already been applied to the files. The patch file can also include changes to irrelevant files (they will simply be ignored). The line numbers given in the patch file are used to determine which lines were changed, so if you have modified the files since the patch file was created, regenerate the patch file first. Beware that the file names of the new files given in the patch file must match exactly, including upper/lower case, path prefix, and directory separator (\\ vs. /). Only unified diff format is accepted (GNU diff, svn diff, and git diff output is okay); if you have a different format, again regenerate it first. Only hits that occur on resultant changed lines, or immediately above and below them, are reported. This option implies \-\-neverignore. \fBWarning\fR: Do \fInot\fR pass a patch file without the \fB\-P\fR, because flawfinder will then try to treat the file as a source file. This will often work, but the line numbers will be relative to the beginning of the patch file, not the positions in the source code. Note that you \fBmust\fR also provide the actual files to analyze, and not just the patch file; when using \fB\-P\fR files are only reported if they are both listed in the patch and also listed (directly or indirectly) in the list of files to analyze. .SS "Selecting Hits to Display" .TP .BI "\-\-inputs" .TP .BI \-I Show only functions that obtain data from outside the program; this also sets minlevel to 0. .TP \fB\-\-minlevel=\fIX\fR .TP .BI -m " X" Set minimum risk level to X for inclusion in hitlist. This can be from 0 (``no risk'') to 5 (``maximum risk''); the default is 1. .TP .BI "\-\-falsepositive" .TP .BI \-F Do not include hits that are likely to be false positives. Currently, this means that function names are ignored if they're not followed by "(", and that declarations of character arrays aren't noted. Thus, if you have use a variable named "access" everywhere, this will eliminate references to this ordinary variable. This isn't the default, because this also increases the likelihood of missing important hits; in particular, function names in #define clauses and calls through function pointers will be missed. .TP .BI \-\-neverignore .TP .BI -n Never ignore security issues, even if they have an ``ignore'' directive in a comment. .TP \fB\-\-regexp=\fR\fIPATTERN\fR .TP \fB-e\fR \fIPATTERN\fR Only report hits with text that matches the regular expression pattern PATTERN. For example, to only report hits containing the text "CWE-120", use ``\-\-regex CWE-120''. These option flag names are the same as grep. .SS "Selecting Output Format" .TP 12 .BI \-\-columns .TP .BI \-C Show the column number (as well as the file name and line number) of each hit; this is shown after the line number by adding a colon and the column number in the line (the first character in a line is column number 1). This is useful for editors that can jump to specific columns, or for integrating with other tools (such as those to further filter out false positives). .TP .BI \-\-context .TP .BI \-c Show context, i.e., the line having the "hit"/potential flaw. By default the line is shown immediately after the warning. .TP .BI \-\-csv Generate output in comma-separated-value (CSV) format. This is the recommended format for sending to other tools for processing. It will always generate a header row, followed by 0 or more data rows (one data row for each hit). Selecting this option automatically enables \-\-quiet and \-\-dataonly. The headers are mostly self-explanatory. "File" is the filename, "Line" is the line number, "Column" is the column (starting from 1), "Level" is the risk level (0-5, 5 is riskiest), "Category" is the general flawfinder category, "Name" is the name of the triggering rule, "Warning" is text explaining why it is a hit (finding), "Suggestion" is text suggesting how it might be fixed, "Note" is other explanatory notes, "CWEs" is the list of one or more CWEs, "Context" is the source code line triggering the hit, and "Fingerprint" is the SHA-256 hash of the context once its leading and trailing whitespace have been removed (the fingerprint may help detect and eliminate later duplications). If you use Python3, the hash is of the context when encoded as UTF-8. .TP .BI "\-\-dataonly" .TP .BI \-D Don't display the header and footer. Use this along with \-\-quiet to see just the data itself. .TP .BI \-\-html .TP .BI \-H Format the output as HTML instead of as simple text. .TP .BI "\-\-immediate" .TP .BI -i Immediately display hits (don't just wait until the end). .TP .BI \-\-sarif Produce output in the OASIS Static Analysis Results Interchange Format (SARIF) format (a JSON-based format). The goals of the SARIF format, as explained in version 2.1.0 (27 March 2020) of its specification, include being able to "comprehensively capture the range of data produced by commonly used static analysis tools." SARIF output identifies the tool name as "Flawfinder". The flawfinder levels 0 through 5 are mapped to SARIF rank (by dividing by 5), SARIF level, and the default viewer action as follows: Flawfinder 0: SARIF rank 0.0, SARIF level note, Does not display by default Flawfinder 1: SARIF rank 0.2, SARIF level note, Does not display by default Flawfinder 2: SARIF rank 0.4, SARIF level note, Does not display by default Flawfinder 3: SARIF rank 0.6, SARIF level warning, Displays by default, does not break build / other processes Flawfinder 4: SARIF rank 0.8, SARIF level error, Displays by default, breaks build/ other processes Flawfinder 5: SARIF rank 1.0, SARIF level error, Displays by default, breaks build/ other processes A big thanks to Yong Yan implementing SARIF output generation for flawfinder! For more about the SARIF format, see: https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif .TP .BI "\-\-singleline" .TP .BI -S Display as single line of text output for each hit. Useful for interacting with compilation tools. .TP .BI "\-\-omittime" Omit timing information. This is useful for regression tests of flawfinder itself, so that the output doesn't vary depending on how long the analysis takes. .TP .BI "\-\-quiet" .TP .BI \-Q Don't display status information (i.e., which files are being examined) while the analysis is going on. .TP .BI "\-\-error-level=LEVEL" Return a nonzero (false) error code if there is at least one hit of LEVEL or higher. If a diffhitlist is provided, hits noted in it are ignored. This option can be useful within a continuous integration script, especially if you mark known-okay lines as "flawfinder: ignore". Usually you want level to be fairly high, such as 4 or 5. By default, flawfinder returns 0 (true) on a successful run. .SS "Hitlist Management" .\" This isn't sorted as usual, because logically saving comes .\" before loading and differencing. .TP 12 \fB\-\-savehitlist=\fR\fIF\fR Save all resulting hits (the "hitlist") to F. .TP \fB\-\-loadhitlist=\fR\fIF\fR Load the hitlist from F instead of analyzing source programs. Warning: Do \fInot\fR load hitlists from untrusted sources (for security reasons). These are internally implemented using Python's "pickle" facility, which trusts the input. Note that stored hitlists often cannot be read when using an older version of Python, in particular, if savehitlist was used but flawfinder was run using Python 3, the hitlist can't be loaded by running flawfinder with Python 2. .TP \fB\-\-diffhitlist=\fR\fIF\fR Show only hits (loaded or analyzed) not in F. F was presumably created previously using \-\-savehitlist. Warning: Do \fInot\fR diff hitlists from untrusted sources (for security reasons). If the \-\-loadhitlist option is not provided, this will show the hits in the analyzed source code files that were not previously stored in F. If used along with \-\-loadhitlist, this will show the hits in the loaded hitlist not in F. The difference algorithm is conservative; hits are only considered the ``same'' if they have the same filename, line number, column position, function name, and risk level. .SS "Character Encoding Errors" Flawfinder uses the character encoding rules set by Python. Sometimes source code does not perfectly follow some encoding rules. If you run flawfinder with Python 2 these non-conformities often do not impact processing in practice. However, if you run flawfinder with Python 3, this can be a problem. Python 3 developers wants the world to always use encodings perfectly correctly, everywhere, and in general wants everyone to only use UTF-8. UTF-8 is a great encoding, and it is very popular, but the world often doesn't care what the Python 3 developers want. When running flawfinder using Python 3, the program will crash hard if \fIany\fR source file has \fIany\fR non-conforming text. It will do this even if the non-conforming text is in comments or strings (where it often doesn't matter). Python 3 fails to provide useful built-ins to deal with the messiness of the real world, so it's non-trivial to deal with this problem without depending on external libraries (which we're trying to avoid). A symptom of this problem is if you run flawfinder and you see an error message like this: \fIError: encoding error in ,1.c\fR \fI'utf-8' codec can't decode byte 0xff in position 45: invalid start byte\fR What you are seeing is the result of an internal UnicodeDecodeError. If this happens to you, there are several options: Option #1 (special case): if your system normally uses an encoding other than UTF-8, is properly set up to use that encoding (using LC_ALL and maybe LC_CTYPE), and the input files are in that non-UTF-8 encoding, it may be that Python3 is (incorrectly) ignoring your configuration. In that case, simply tell Python3 to use your configuration by setting the environment variable PYTHONUTF8=0, e.g., run flawfinder as: "PYTHONUTF8=0 python3 flawfinder ...". Option #2 (special case): If you know what the encoding of the files is, you can force use of that encoding. E.g., if the encoding is BLAH, run flawfinder as: "PYTHONUTF8=0 LC_ALL=C.BLAH python3 flawfinder ...". You can replace "C" after LC_ALL= with your real language locale (e.g., "en_US"). Option #3: If you don't know what the encoding is, or the encoding is inconsistent (e.g., the common case of UTF-8 files with some characters encoded using Windows-1252 instead), then you can force the system to use the ISO-8859-1 (Latin-1) encoding in which all bytes are allowed. If the inconsistencies are only in comments and strings, and the underlying character set is "close enough" to ASCII, this can get you going in a hurry. You can do this by running: "PYTHONUTF8=0 LC_ALL=C.ISO-8859-1 python3 flawfinder ...". In some cases you may not need the "PYTHONUTF8=0". You may be able to replace "C" after LC_ALL= with your real language locale (e.g., "en_US"). Option #4: Convert the encoding of the files to be analyzed so that it's a single encoding - it's highly recommended to convert to UTF-8. For example, the system program "iconv" or the Python program cvt2utf can be used to convert encodings. (You can install cvt2utf with "pip install cvtutf"). This works well if some files have one encoding, and some have another, but they are consistent within a single file. If the files have encoding errors, you'll have to fix them. Option #5: Run flawfinder using Python 2 instead of Python 3. E.g., "python2 flawfinder ...". To be clear: I strongly recommend using the UTF-8 encoding for all source code, and use continuous integration tests to ensure that the source code is always valid UTF-8. If you do that, many problems disappear. But in the real world this is not always the situation. Hopefully this information will help you deal with real-world encoding problems. .SH EXAMPLES Here are various examples of how to invoke flawfinder. The first examples show various simple command-line options. Flawfinder is designed to work well with text editors and integrated development environments, so the next sections show how to integrate flawfinder into vim and emacs. .SS "Simple command-line options" .TP 12 .B "flawfinder /usr/src/linux-3.16" Examine all the C/C++ files in the directory /usr/src/linux-3.16 and all its subdirectories (recursively), reporting on all hits found. By default flawfinder will skip symbolic links and directories with names that start with a period. .TP .B "flawfinder \-\-error-level=4 ." Examine all the C/C++ files in the current directory and its subdirectories (recursively); return an error code if there are vulnerabilities level 4 and up (the two highest risk levels). This is a plausible way to use flawfinder in a continuous integration system. .TP .B "flawfinder \-\-minlevel=4 ." Examine all the C/C++ files in the current directory and its subdirectories (recursively); only report vulnerabilities level 4 and up (the two highest risk levels). .TP .B "flawfinder \-\-inputs mydir" Examine all the C/C++ files in mydir and its subdirectories (recursively), and report functions that take inputs (so that you can ensure that they filter the inputs appropriately). .TP .B "flawfinder \-\-neverignore mydir" Examine all the C/C++ files in the directory mydir and its subdirectories, including even the hits marked for ignoring in the code comments. .TP .B "flawfinder \-\-csv ." Examine the current directory down (recursively), and report all hits in CSV format. This is the recommended form if you want to further process flawfinder output using other tools (such as data correlation tools). .TP .B "flawfinder \-QD mydir" Examine mydir and report only the actual results (removing the header and footer of the output). This form may be useful if the output will be piped into other tools for further analysis, though CSV format is probably the better choice in that case. The \-C (\-\-columns) and \-S (\-\-singleline) options can also be useful if you're piping the data into other tools. .TP .B "flawfinder \-QDSC mydir" Examine mydir, reporting only the actual results (no header or footer). Each hit is reported on one line, and column numbers are reported. This can be a useful command if you are feeding flawfinder output to other tools. .TP .B "flawfinder \-\-quiet \-\-html \-\-context mydir > results.html" Examine all the C/C++ files in the directory mydir and its subdirectories, and produce an HTML formatted version of the results. Source code management systems (such as SourceForge and Savannah) might use a command like this. .TP .B "flawfinder \-\-quiet \-\-savehitlist saved.hits *.[ch]" Examine all .c and .h files in the current directory. Don't report on the status of processing, and save the resulting hitlist (the set of all hits) in the file saved.hits. .TP .B "flawfinder \-\-diffhitlist saved.hits *.[ch]" Examine all .c and .h files in the current directory, and show any hits that weren't already in the file saved.hits. This can be used to show only the ``new'' vulnerabilities in a modified program, if saved.hits was created from the older version of the program being analyzed. .TP 12 .B "flawfinder \-\-patch recent.patch ." Examine the current directory recursively, but only report lines that were changed or added in the already-applied patchfile named \fIrecent.patch\fR. .TP \fBflawfinder \-\-regex "CWE-120|CWE-126" src/\fR Examine directory \fIsrc\fR recursively, but only report hits where CWE-120 or CWE-126 apply. .SS "Invoking from vim" .PP The text editor vim includes a "quickfix" mechanism that works well with flawfinder, so that you can easily view the warning messages and jump to the relevant source code. .PP First, you need to invoke flawfinder to create a list of hits, and there are two ways to do this. The first way is to start flawfinder first, and then (using its output) invoke vim. The second way is to start (or continue to run) vim, and then invoke flawfinder (typically from inside vim). .PP For the first way, run flawfinder and store its output in some FLAWFILE (say "flawfile"), then invoke vim using its -q option, like this: "vim -q flawfile". The second way (starting flawfinder after starting vim) can be done a legion of ways. One is to invoke flawfinder using a shell command, ":!flawfinder-command > FLAWFILE", then follow that with the command ":cf FLAWFILE". Another way is to store the flawfinder command in your makefile (as, say, a pseudocommand like "flaw"), and then run ":make flaw". .PP In all these cases you need a command for flawfinder to run. A plausible command, which places each hit in its own line (-S) and removes headers and footers that would confuse it, is: .PP .B "flawfinder \-SQD ." .PP You can now use various editing commands to view the results. The command ":cn" displays the next hit; ":cN" displays the previous hit, and ":cr" rewinds back to the first hit. ":copen" will open a window to show the current list of hits, called the "quickfix window"; ":cclose" will close the quickfix window. If the buffer in the used window has changed, and the error is in another file, jumping to the error will fail. You have to make sure the window contains a buffer which can be abandoned before trying to jump to a new file, say by saving the file; this prevents accidental data loss. .SS "Invoking from emacs" The text editor / operating system emacs includes "grep mode" and "compile mode" mechanisms that work well with flawfinder, making it easy to view warning messages, jump to the relevant source code, and fix any problems you find. .PP First, you need to invoke flawfinder to create a list of warning messages. You can use "grep mode" or "compile mode" to create this list. Often "grep mode" is more convenient; it leaves compile mode untouched so you can easily recompile once you've changed something. However, if you want to jump to the exact column position of a hit, compile mode may be more convenient because emacs can use the column output of flawfinder to directly jump to the right location without any special configuration. .PP To use grep mode, enter the command "M-x grep" and then enter the needed flawfinder command. To use compile mode, enter the command "M-x compile" and enter the needed flawfinder command. This is a meta-key command, so you'll need to use the meta key for your keyboard (this is usually the ESC key). As with all emacs commands, you'll need to press RETURN after typing "grep" or "compile". So on many systems, the grep mode is invoked by typing ESC x g r e p RETURN. .PP You then need to enter a command, removing whatever was there before if necessary. A plausible command is: .PP .B "flawfinder \-SQDC ." .PP This command makes every hit report a single line, which is much easier for tools to handle. The quiet and dataonly options remove the other status information not needed for use inside emacs. The trailing period means that the current directory and all descendents are searched for C/C++ code, and analyzed for flaws. .PP Once you've invoked flawfinder, you can use emacs to jump around in its results. The command C-x \` (Control-x backtick) visits the source code location for the next warning message. C-u C-x \` (control-u control-x backtick) restarts from the beginning. You can visit the source for any particular error message by moving to that hit message in the *compilation* buffer or *grep* buffer and typing the return key. (Technical note: in the compilation buffer, this invokes compile-goto-error.) You can also click the Mouse-2 button on the error message (you don't need to switch to the *compilation* buffer first). .PP If you want to use grep mode to jump to specific columns of a hit, you'll need to specially configure emacs to do this. To do this, modify the emacs variable "grep-regexp-alist". This variable tells Emacs how to parse output of a "grep" command, similar to the variable "compilation-error-regexp-alist" which lists various formats of compilation error messages. .SS "Invoking from Integrated Development Environments (IDEs)" .PP For (other) IDEs, consult your IDE's set of plug-ins. .SH COMMON WEAKNESS ENUMERATION (CWE) .PP The Common Weakness Enumeration (CWE) is ``a formal list or dictionary of common software weaknesses that can occur in software's architecture, design, code or implementation that can lead to exploitable security vulnerabilities... created to serve as a common language for describing software security weaknesses'' (https://cwe.mitre.org/about/faq.html). For more information on CWEs, see https://cwe.mitre.org. .PP Flawfinder supports the CWE and is officially CWE-Compatible. Hit descriptions typically include a relevant Common Weakness Enumeration (CWE) identifier in parentheses where there is known to be a relevant CWE. For example, many of the buffer-related hits mention CWE-120, the CWE identifier for ``buffer copy without checking size of input'' (aka ``Classic Buffer Overflow''). In a few cases more than one CWE identifier may be listed. The HTML report also includes hypertext links to the CWE definitions hosted at MITRE. In this way, flawfinder is designed to meet the CWE-Output requirement. .PP In some cases there are CWE mapping and usage challenges; here is how flawfinder handles them. If the same entry maps to multiple CWEs simultaneously, all the CWE mappings are listed as separated by commas. This often occurs with CWE-20, Improper Input Validation; thus the report "CWE-676, CWE-120" maps to two CWEs. In addition, flawfinder provides additional information for those who are are interested in the CWE/SANS top 25 list 2011 (https://cwe.mitre.org/top25/) when mappings are not directly to them. Many people will want to search for specific CWEs in this top 25 list, such as CWE-120 (classic buffer overflow). The challenge is that some flawfinder hits map to a more general CWE that would include a top 25 item, while in some other cases hits map to a more specific vulnerability that is only a subset of a top 25 item. To resolve this, in some cases flawfinder will list a sequence of CWEs in the format "more-general/more-specific", where the CWE actually being mapped is followed by a "!". This is always done whenever a flaw is not mapped directly to a top 25 CWE, but the mapping is related to such a CWE. So "CWE-119!/CWE-120" means that the vulnerability is mapped to CWE-119 and that CWE-120 is a subset of CWE-119. In contrast, "CWE-362/CWE-367!" means that the hit is mapped to CWE-367, a subset of CWE-362. Note that this is a subtle syntax change from flawfinder version 1.31; in flawfinder version 1.31, the form "more-general:more-specific" meant what is now listed as "more-general!/more-specific", while "more-general/more-specific" meant "more-general/more-specific!". Tools can handle both the version 1.31 and the current format, if they wish, by noting that the older format did not use "!" at all (and thus this is easy to distinguish). These mapping mechanisms simplify searching for certain CWEs. .PP CWE version 2.7 (released June 23, 2014) was used for the mapping. The current CWE mappings select the most specific CWE the tool can determine. In theory, most CWE security elements (signatures/patterns that the tool searches for) could theoretically be mapped to CWE-676 (Use of Potentially Dangerous Function), but such a mapping would not be useful. Thus, more specific mappings were preferred where one could be found. Flawfinder is a lexical analysis tool; as a result, it is impractical for it to be more specific than the mappings currently implemented. This also means that it is unlikely to need much updating for map currency; it simply doesn't have enough information to refine to a detailed CWE level that CWE changes would typically affect. The list of CWE identifiers was generated automatically using "make show-cwes", so there is confidence that this list is correct. Please report CWE mapping problems as bugs if you find any. .PP Flawfinder may fail to find a vulnerability, even if flawfinder covers one of these CWE weaknesses. That said, flawfinder does find vulnerabilities listed by the CWEs it covers, and it will not report lines without those vulnerabilities in many cases. Thus, as required for any tool intending to be CWE compatible, flawfinder has a rate of false positives less than 100% and a rate of false negatives less than 100%. Flawfinder almost always reports whenever it finds a match to a CWE security element (a signature/pattern as defined in its database), though certain obscure constructs can cause it to fail (see BUGS below). .PP Flawfinder can report on the following CWEs (these are the CWEs that flawfinder covers; ``*'' marks those in the CWE/SANS top 25 list): .IP \(bu 2 CWE-20: Improper Input Validation .IP \(bu 2 CWE-22: Improper Limitation of a Pathname to a Restricted Directory (``Path Traversal'') .IP \(bu CWE-78: Improper Neutralization of Special Elements used in an OS Command (``OS Command Injection'')* .IP \(bu CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer (a parent of CWE-120*, so this is shown as CWE-119!/CWE-120) .IP \(bu CWE-120: Buffer Copy without Checking Size of Input (``Classic Buffer Overflow'')* .IP \(bu CWE-126: Buffer Over-read .IP \(bu CWE-134: Uncontrolled Format String* .IP \(bu CWE-190: Integer Overflow or Wraparound* .IP \(bu CWE-250: Execution with Unnecessary Privileges .IP \(bu CWE-327: Use of a Broken or Risky Cryptographic Algorithm* .IP \(bu CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization (``Race Condition'') .IP \(bu CWE-377: Insecure Temporary File .IP \(bu CWE-676: Use of Potentially Dangerous Function* .IP \(bu CWE-732: Incorrect Permission Assignment for Critical Resource* .IP \(bu CWE-785: Use of Path Manipulation Function without Maximum-sized Buffer (child of CWE-120*, so this is shown as CWE-120/CWE-785) .IP \(bu CWE-807: Reliance on Untrusted Inputs in a Security Decision* .IP \(bu CWE-829: Inclusion of Functionality from Untrusted Control Sphere* .PP You can select a specific subset of CWEs to report by using the ``\-\-regex'' (-e) option. This option accepts a regular expression, so you can select multiple CWEs, e.g., ``\-\-regex "CWE-120|CWE-126"''. If you select multiple CWEs with ``|'' on a command line you will typically need to quote the parameters (since an unquoted ``|'' is the pipe symbol). Flawfinder is designed to meet the CWE-Searchable requirement. .PP If your goal is to report a subset of CWEs that are listed in a file, that can be achieved on a Unix-like system using the ``\-\-regex'' aka ``\-e'' option. The file must be in regular expression format. For example, ``flawfinder -e $(cat file1)'' would report only hits that matched the pattern in ``file1''. If file1 contained ``CWE-120|CWE-126'' it would only report hits matching those CWEs. .PP A list of all CWE security elements (the signatures/patterns that flawfinder looks for) can be found by using the ``\-\-listrules'' option. Each line lists the signature token (typically a function name) that may lead to a hit, the default risk level, and the default warning (which includes the default CWE identifier). For most purposes this is also enough if you want to see what CWE security elements map to which CWEs, or the reverse. For example, to see the most of the signatures (function names) that map to CWE-327, without seeing the default risk level or detailed warning text, run ``flawfinder \-\-listrules | grep CWE-327 | cut -f1''. You can also see the tokens without a CWE mapping this way by running ``flawfinder -D --listrules | grep -v CWE-''. However, while \-\-listrules lists all CWE security elements, it only lists the default mappings from CWE security elements to CWE identifiers. It does not include the refinements that flawfinder applies (e.g., by examining function parameters). .PP If you want a detailed and exact mapping between the CWE security elements and CWE identifiers, the flawfinder source code (included in the distribution) is the best place for that information. This detailed information is primarily of interest to those few people who are trying to refine the CWE mappings of flawfinder or refine CWE in general. The source code documents the mapping between the security elements to the respective CWE identifiers, and is a single Python file. The ``c_rules'' dataset defines most rules, with reference to a function that may make further refinements. You can search the dataset for function names to see what CWE it generates by default; if first parameter is not ``normal'' then that is the name of a refining Python method that may select different CWEs (depending on additional information). Conversely, you can search for ``CWE-number'' and find what security elements (signatures or patterns) refer to that CWE identifier. For most people, this is much more than they need; most people just want to scan their source code to quickly find problems. .SH SECURITY .PP The whole point of this tool is to help find vulnerabilities so they can be fixed. However, developers and reviewers must know how to develop secure software to use this tool, because otherwise, \fIa fool with a tool is still a fool\fR. My book at https://dwheeler.com/secure-programs may help. .PP This tool should be, at most, a small part of a larger software development process designed to eliminate or reduce the impact of vulnerabilities. Developers and reviewers need know how to develop secure software, and they need to apply this knowledge to reduce the risks of vulnerabilities in the first place. .PP Different vulnerability-finding tools tend to find different vulnerabilities. Thus, you are best off using human review and a variety of tools. This tool can help find some vulnerabilities, but by no means all. .PP You should always analyze a \fIcopy\fP of the source program being analyzed, not a directory that can be modified by a developer while flawfinder is performing the analysis. This is \fIespecially\fP true if you don't necessily trust a developer of the program being analyzed. If an attacker has control over the files while you're analyzing them, the attacker could move files around or change their contents to prevent the exposure of a security problem (or create the impression of a problem where there is none). If you're worried about malicious programmers you should do this anyway, because after analysis you'll need to verify that the code eventually run is the code you analyzed. Also, do not use the \-\-allowlink option in such cases; attackers could create malicious symbolic links to files outside of their source code area (such as /etc/passwd). .PP Source code management systems (like GitHub, SourceForge, and Savannah) definitely fall into this category; if you're maintaining one of those systems, first copy or extract the files into a separate directory (that can't be controlled by attackers) before running flawfinder or any other code analysis tool. .PP Note that flawfinder only opens regular files, directories, and (if requested) symbolic links; it will never open other kinds of files, even if a symbolic link is made to them. This counters attackers who insert unusual file types into the source code. However, this only works if the filesystem being analyzed can't be modified by an attacker during the analysis, as recommended above. This protection also doesn't work on Cygwin platforms, unfortunately. .PP Cygwin systems (Unix emulation on top of Windows) have an additional problem if flawfinder is used to analyze programs that the analyst cannot trust. The problem is due to a design flaw in Windows (that it inherits from MS-DOS). On Windows and MS-DOS, certain filenames (e.g., ``com1'') are automatically treated by the operating system as the names of peripherals, and this is true even when a full pathname is given. Yes, Windows and MS-DOS really are designed this badly. Flawfinder deals with this by checking what a filesystem object is, and then only opening directories and regular files (and symlinks if enabled). Unfortunately, this doesn't work on Cygwin; on at least some versions of Cygwin on some versions of Windows, merely trying to determine if a file is a device type can cause the program to hang. A workaround is to delete or rename any filenames that are interpreted as device names before performing the analysis. These so-called ``reserved names'' are CON, PRN, AUX, CLOCK$, NUL, COM1-COM9, and LPT1-LPT9, optionally followed by an extension (e.g., ``com1.txt''), in any directory, and in any case (Windows is case-insensitive). .\" See 'Writing Secure Code' by Howard and LeBlanc, pg. 223 .PP Do \fInot\fR load or diff hitlists from untrusted sources. They are implemented using the Python pickle module, and the pickle module is not intended to be secure against erroneous or maliciously constructed data. Stored hitlists are intended for later use by the same user who created the hitlist; in that context this restriction is not a problem. .SH BUGS .PP Flawfinder is based on simple text pattern matching, which is part of its fundamental design and not easily changed. This design approach leads to a number of fundamental limitations, e.g., a higher false positive rate, and is the underlying cause of most of the bugs listed here. On the positive side, flawfinder doesn't get confused by many complicated preprocessor sequences that other tools sometimes choke on; flawfinder can often handle code that cannot link, and sometimes cannot even compile or build. .PP Flawfinder is currently limited to C/C++. In addition, when analyzing C++ it focuses primarily on the C subset of C++. For example, flawfinder does not report on expressions like cin >> charbuf, where charbuf is a char array. That is because flawfinder doesn't have type information, and ">>" is safe with many other types; reporting on all ">>" would lead to too many false positives. That said, it's designed so that adding support for other languages should be easy where its text-based approach can usefully apply. .PP Flawfinder can be fooled by user-defined functions or method names that happen to be the same as those defined as ``hits'' in its database, and will often trigger on definitions (as well as uses) of functions with the same name. This is typically not a problem for C code. In C code, a function with the same name as a common library routine name often indicates that the developer is simply rewriting a common library routine with the same interface, say for portability's sake. C programs tend to avoid reusing the same name for a different purpose (since in C function names are global by default). There are reasonable odds that these rewritten routines will be vulnerable to the same kinds of misuse, and thus, reusing these rules is a reasonable approach. However, this can be a much more serious problem in C++ code which heavily uses classes and namespaces, since the same method name may have many different meanings. The \-\-falsepositive option can help somewhat in this case. If this is a serious problem, feel free to modify the program, or process the flawfinder output through other tools to remove the false positives. .PP Preprocessor commands embedded in the middle of a parameter list of a call can cause problems in parsing, in particular, if a string is opened and then closed multiple times using an #ifdef .. #else construct, flawfinder gets confused. Such constructs are bad style, and will confuse many other tools too. If you must analyze such files, rewrite those lines. Thankfully, these are quite rare. .PP Flawfinder reports vulnerabilities regardless of the parameters of "#if" or "#ifdef". A construct "#if VALUE" will often have VALUE of 0 in some cases, and non-zero in others. Similarly, "#ifdef VALUE" will have VALUE defined in some cases, and not defined in others. Flawfinder reports in all cases, which means that flawfinder has a chance of reporting vulnerabilities in all alternatives. This is not a bug, this is intended behavior. .PP Flawfinder will report hits even if they are between a literal "#if 0" and "#endif". It would be possible to change this particular situation, but directly using "#if 0" to comment-out code (other than during debugging) indicates (1) the removal is very temporary (in which case we should still report it) or (2) very poor code practices. If you want to permanently get rid of code, then delete it instead of using "#if 0", since you can always see what it was using your version control software. If you don't use version control software, then that's the bug you need to fix right now. .PP Some complex or unusual constructs can mislead flawfinder. In particular, if a parameter begins with gettext(" and ends with ), flawfinder will presume that the parameter of gettext is a constant. This means it will get confused by patterns like gettext("hi") + function("bye"). In practice, this doesn't seem to be a problem; gettext() is usually wrapped around the entire parameter. .PP The routine to detect statically defined character arrays uses simple text matching; some complicated expressions can cause it to trigger or not trigger unexpectedly. .PP Flawfinder looks for specific patterns known to be common mistakes. Flawfinder (or any tool like it) is not a good tool for finding intentionally malicious code (e.g., Trojan horses); malicious programmers can easily insert code that would not be detected by this kind of tool. .PP Flawfinder looks for specific patterns known to be common mistakes in application code. Thus, it is likely to be less effective analyzing programs that aren't application-layer code (e.g., kernel code or self-hosting code). The techniques may still be useful; feel free to replace the database if your situation is significantly different from normal. .PP Flawfinder's default output format (filename:linenumber, followed optionally by a :columnnumber) can be misunderstood if any source files have very weird filenames. Filenames embedding a newline/linefeed character will cause odd breaks, and filenames including colon (:) are likely to be misunderstood. This is especially important if flawfinder's output is being used by other tools, such as filters or text editors. If you are using flawfinder's output in other tools, consider using its CSV format instead (which can handle this). If you're looking at new code, examine the files for such characters. It's incredibly unwise to have such filenames anyway; many tools can't handle such filenames at all. Newline and linefeed are often used as internal data delimeters. The colon is often used as special characters in filesystems: MacOS uses it as a directory separator, Windows/MS-DOS uses it to identify drive letters, Windows/MS-DOS inconsistently uses it to identify special devices like CON:, and applications on many platforms use the colon to identify URIs/URLs. Filenames including spaces and/or tabs don't cause problems for flawfinder, though note that other tools might have problems with them. .PP Flawfinder is not internationalized, so it currently does not support localization. .PP In general, flawfinder attempts to err on the side of caution; it tends to report hits, so that they can be examined further, instead of silently ignoring them. Thus, flawfinder prefers to have false positives (reports that turn out to not be problems) rather than false negatives (failures to report security vulnerabilities). But this is a generality; flawfinder uses simplistic heuristics and simply can't get everything "right". .PP Security vulnerabilities might not be identified as such by flawfinder, and conversely, some hits aren't really security vulnerabilities. This is true for all static security scanners, and is especially true for tools like flawfinder that use a simple lexical analysis and pattern analysis to identify potential vulnerabilities. Still, it can serve as a useful aid for humans, helping to identify useful places to examine further, and that's the point of this simple tool. .SH "SEE ALSO" See the flawfinder website at https://dwheeler.com/flawfinder. You should also see the .I "Secure Programming HOWTO" at .IR "https://dwheeler.com/secure-programs" . .SH AUTHOR David A. Wheeler (dwheeler@dwheeler.com). flawfinder-2.0.19/announcement000644 000765 000024 00000002524 13774402305 017313 0ustar00dwheelerstaff000000 000000 I've just released "flawfinder", a program that can scan source code and identify out potential security flaws, ranking them by likely severity. Unlike ITS4, flawfinder is completely open source / free software (it's released under the GPL license). Flawfinder will miss some security problems, and point out issues that aren't really security problems, but nevertheless I think it can help track down security problems in code so that the code can be fixed. You can download flawfinder from: http://www.dwheeler.com/flawfinder Flawfinder is in its very early stages - I'm labelling it version "0.12". It works reliably, but its ruleset is currently small and rudimentary. It can already find some security problems now, but expanding its ruleset will give it much more power. Also, it currently can only examine C/C++ code. After I wrote flawfinder - and just before I released it - I found out that Secure Software Solutions was also writing a program (RATS) to perform this same task, also to be released under the GPL. We agreed to release our programs simultaneously, and to mention each other's programs in our announcements. Now that we've released our programs, we plan to coordinate so that there will be a single open source / free software source code scanner that will be a ``best of breed.'' --- David A. Wheeler dwheeler@dwheeler.com flawfinder-2.0.19/entrypoint.sh000755 000765 000024 00000000331 14066722205 017441 0ustar00dwheelerstaff000000 000000 #!/bin/sh -l # $1 whitespace-separated arguments. Some filenames may need to be escaped. # $2 output filename output="${2:-flawfinder-output.txt}" flawfinder $1 > "$output" result="$?" cat "$output" exit "$result" flawfinder-2.0.19/action.yml000644 000765 000024 00000000630 14074640414 016671 0ustar00dwheelerstaff000000 000000 name: 'flawfinder_scan' description: 'Execute Flawfinder to scan source code for vulnerabilities' inputs: arguments: description: 'Command arguments to be sent to Flawfinder' required: true default: '' output: description: 'Output file name' required: true default: '' runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.arguments }} - ${{ inputs.output }} flawfinder-2.0.19/test/correct-results-008.txt000644 000765 000024 00000001312 14112766111 022050 0ustar00dwheelerstaff000000 000000 Flawfinder version 2.0.19, (C) 2001-2019 David A. Wheeler. Showing hits not in test-saved-hitlist-008.txt Number of rules (primarily dangerous function names) in C/C++ ruleset: 222 ANALYSIS SUMMARY: No hits found. Lines analyzed = 125 Physical Source Lines of Code (SLOC) = 86 Hits@level = [0] 0 [1] 0 [2] 0 [3] 0 [4] 0 [5] 0 Hits@level+ = [0+] 0 [1+] 0 [2+] 0 [3+] 0 [4+] 0 [5+] 0 Hits/KSLOC@level+ = [0+] 0 [1+] 0 [2+] 0 [3+] 0 [4+] 0 [5+] 0 Suppressed hits = 2 (use --neverignore to show them) Minimum risk level = 1 There may be other security vulnerabilities; review your code! See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. flawfinder-2.0.19/test/test-boost-system.hpp000644 000765 000024 00000000154 13774407616 022022 0ustar00dwheelerstaff000000 000000 // Ensure reference to boost::system is ignored void HandleWrite(const boost::system::error_code &error); flawfinder-2.0.19/test/test-patched.c000644 000765 000024 00000006542 13774402305 020412 0ustar00dwheelerstaff000000 000000 /* Test flawfinder. This program won't compile or run; that's not necessary for this to be a useful test. */ #include #define hello(x) goodbye(x) #define WOKKA "stuff" main() { printf("hello\n"); } int bad(char *a, char *b) { strcpy(b, a); } /* This is a strcpy test. */ int demo(char *a, char *b) { strcpy(a, "\n"); // Did this work? strcpy(a, gettext("Hello there")); // Did this work? strcpy(b, a); sprintf(s, "\n"); sprintf(s, "hello"); sprintf(s, "hello %s", bug); sprintf(s, gettext("hello %s"), bug); sprintf(s, unknown, bug); printf(bf, x); scanf("%d", &x); scanf("%s", s); scanf("%10s", s); scanf("%s", s); gets(f); // Flawfinder: ignore printf("\\"); /* Flawfinder: ignore */ gets(f); gets(f); /* These are okay, but flawfinder version < 0.20 incorrectly used the first parameter as the parameter for the format string */ syslog(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno)) syslog(LOG_CRIT,"malloc() failed"); /* But this one SHOULD trigger a warning. */ syslog(LOG_ERR, attacker_string); } demo2() { char d[20]; char s[20]; int n; _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */ memcpy(d,s); CopyMemory(d,s); lstrcat(d,s); strncpy(d,s); _tcsncpy(d,s); strncat(d,s,10); strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */ _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */ n = strlen(d); /* This is wrong, and should be flagged as risky: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)); /* This is also wrong, and should be flagged as risky: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName); /* This is much better: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0])); /* This is much better: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0])); /* This is an example of bad code - the third paramer is NULL, so it creates a NULL ACL. Note that Flawfinder can't detect when a SECURITY_DESCRIPTOR structure is manually created with a NULL value as the ACL; doing so would require a tool that handles C/C++ and knows about types more that flawfinder currently does. Anyway, this needs to be detected: */ SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE); /* This one is a bad idea - first param shouldn't be NULL */ CreateProcess(NULL, "C:\\Program Files\\GoodGuy\\GoodGuy.exe -x", ""); /* Test interaction of quote characters */ printf("%c\n", 'x'); printf("%c\n", '"'); printf("%c\n", '\"'); printf("%c\n", '\''); printf("%c\n", '\177'); printf("%c\n", '\xfe'); printf("%c\n", '\xd'); printf("%c\n", '\n'); printf("%c\n", '\\'); printf("%c\n", "'"); } int getopt_example(int argc,char *argv[]) { while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) { } } int testfile() { FILE *f; f = fopen("/etc/passwd", "r"); fclose(f); } /* Regression test: handle \\\n after end of string */ #define assert(x) {\ if (!(x)) {\ fprintf(stderr,"Assertion failed.\n"\ "File: %s\nLine: %d\n"\ "Assertion: %s\n\n"\ ,__FILE__,__LINE__,#x);\ exit(1);\ };\ } int accesstest() { int access = 0; /* Not a function call. Should be caught by the false positive test, and NOT labelled as a problem. */ } flawfinder-2.0.19/test/test-results-008.txt000644 000765 000024 00000001312 14112766125 021373 0ustar00dwheelerstaff000000 000000 Flawfinder version 2.0.19, (C) 2001-2019 David A. Wheeler. Showing hits not in test-saved-hitlist-008.txt Number of rules (primarily dangerous function names) in C/C++ ruleset: 222 ANALYSIS SUMMARY: No hits found. Lines analyzed = 125 Physical Source Lines of Code (SLOC) = 86 Hits@level = [0] 0 [1] 0 [2] 0 [3] 0 [4] 0 [5] 0 Hits@level+ = [0+] 0 [1+] 0 [2+] 0 [3+] 0 [4+] 0 [5+] 0 Hits/KSLOC@level+ = [0+] 0 [1+] 0 [2+] 0 [3+] 0 [4+] 0 [5+] 0 Suppressed hits = 2 (use --neverignore to show them) Minimum risk level = 1 There may be other security vulnerabilities; review your code! See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. flawfinder-2.0.19/test/test-cpp-digit-separator.c000644 000765 000024 00000000034 13774402723 022652 0ustar00dwheelerstaff000000 000000 int main() { return 0'000; }flawfinder-2.0.19/test/._test-results.csv000644 000765 000024 00000000351 14112766123 021257 0ustar00dwheelerstaff000000 000000 Mac OS X  2·éATTRéÀ)Àcom.apple.lastuseddate#PSÐcom.apple.quarantine¥cE`›â´:q/0082;604563a6;Numbers;flawfinder-2.0.19/test/PaxHeader/test-results.csv000644 000765 000024 00000000033 14112766123 023010 xustar00dwheelerstaff000000 000000 27 mtime=1630268499.902645 flawfinder-2.0.19/test/test-results.csv000644 000765 000024 00000035150 14112766123 021047 0ustar00dwheelerstaff000000 000000 File,Line,Column,DefaultLevel,Level,Category,Name,Warning,Suggestion,Note,CWEs,Context,Fingerprint,ToolVersion,RuleId,HelpUri test.c,32,2,5,5,buffer,gets,"Does not check for buffer overflows (CWE-120, CWE-20).",Use fgets() instead.,,"CWE-120, CWE-20", gets(f);,6a5bb383fb44030b0d9428b17359e94ba3979bc1ce702be450427f85592c649a,2.0.19,FF1014,https://cwe.mitre.org/data/definitions/120.html test.c,60,3,1,5,buffer,strncat,"Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120).","Consider strcat_s, strlcat, snprintf, or automatically resizing strings.","Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.",CWE-120," strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */",cbd19c308547e79af13436d8f7dbcf6c62e49e4f62ba9aee38fbef29e0772f74,2.0.19,FF1010,https://cwe.mitre.org/data/definitions/120.html test.c,61,3,1,5,buffer,_tcsncat,"Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120).","Consider strcat_s, strlcat, or automatically resizing strings.","Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.",CWE-120," _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */",c3f6ba2c710efc878e66df4578894fd408452cb7cdec7ae6f492a3b1796f8c42,2.0.19,FF1011,https://cwe.mitre.org/data/definitions/120.html test.c,64,3,2,5,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is high, it appears that the size is given as bytes, but the function requires size as characters.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));",4f5b73ff337a54d6e1d9a369659ca0ddb4f80e6b7e38a17e5b112f6d3e266e69,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html test.c,66,3,2,5,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is high, it appears that the size is given as bytes, but the function requires size as characters.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);",9ecdc1e903acc16a646bf7909a630ae22a7593b70952c39ce6bd9c5a23fad0fd,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html test.c,77,3,5,5,misc,SetSecurityDescriptorDacl,"Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb,2.0.19,FF1060,https://cwe.mitre.org/data/definitions/732.html test.c,77,3,5,5,misc,SetSecurityDescriptorDacl,"Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb,2.0.19,FF1060,https://cwe.mitre.org/data/definitions/732.html test.c,17,2,4,4,buffer,strcpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,"Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).",,CWE-120," strcpy(b, a);",c01c8472bb53022e912da4da2faebc67d537855da324020c44bfd5e608a79b77,2.0.19,FF1001,https://cwe.mitre.org/data/definitions/120.html test.c,20,2,4,4,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",,CWE-120," sprintf(s, ""hello %s"", bug);",814237858ab012010f3355a49480dd6fa0a2cb8cf8356a98ac1c17c9febf6521,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,21,2,4,4,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",,CWE-120," sprintf(s, gettext(""hello %s""), bug);",b793f18f143fb2297c49e0639384ad73db86eb01a44377aa4d5d09b44b03d747,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,22,2,4,4,format,sprintf,Potential format string problem (CWE-134).,Make format string constant.,,CWE-134," sprintf(s, unknown, bug);",16ebc2ff96ee4bab2695783709e97b597ca9c8b8cc149e33aed859f0fafd3431,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/134.html test.c,23,2,4,4,format,printf,"If format strings can be influenced by an attacker, they can be exploited (CWE-134).",Use a constant for the format specification.,,CWE-134," printf(bf, x);",46f42896019245d2dffc4caf4fe018b073ce2a58203676eaa28b6374558a5b5d,2.0.19,FF1016,https://cwe.mitre.org/data/definitions/134.html test.c,25,2,4,4,buffer,scanf,"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).","Specify a limit to %s, or use a different input function.",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f,2.0.19,FF1020,https://cwe.mitre.org/data/definitions/120.html test.c,27,2,4,4,buffer,scanf,"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).","Specify a limit to %s, or use a different input function.",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f,2.0.19,FF1020,https://cwe.mitre.org/data/definitions/120.html test.c,38,2,4,4,format,syslog,"If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134).",Use a constant format string for syslog.,,CWE-134," syslog(LOG_ERR, attacker_string);",22e98963d5af7b197a090bd522d2d39b8d8ee7bdf08453fd2008939c92cd9677,2.0.19,FF1018,https://cwe.mitre.org/data/definitions/134.html test.c,49,3,4,4,buffer,_mbscpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,Consider using a function version that stops copying at the end of the buffer.,,CWE-120," _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */",e00a4a1a0a3603db98a23fcff3c9cdfd9012f5a81826814d9508e0f22089b993,2.0.19,FF1003,https://cwe.mitre.org/data/definitions/120.html test.c,56,3,4,4,buffer,lstrcat,Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120).,,,CWE-120," lstrcat(d,s);",364b4c512862fdccbca27d2fa7737995b5d24b637a760976c940ae636218d340,2.0.19,FF1006,https://cwe.mitre.org/data/definitions/120.html test.c,79,3,3,3,shell,CreateProcess,This causes a new process to execute and is difficult to use safely (CWE-78).,"Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf,2.0.19,FF1046,https://cwe.mitre.org/data/definitions/78.html test.c,79,3,3,3,shell,CreateProcess,This causes a new process to execute and is difficult to use safely (CWE-78).,"Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf,2.0.19,FF1046,https://cwe.mitre.org/data/definitions/78.html test.c,81,10,3,3,misc,LoadLibraryEx,"Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20).",Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders.,,"CWE-829, CWE-20"," (void) LoadLibraryEx(L""user32.dll"", nullptr, LOAD_LIBRARY_AS_DATAFILE);",b1f99ecaa31e682487d795afbf03282fd56ad9f2aa630d0196219b277d2a68c9,2.0.19,FF1059,https://cwe.mitre.org/data/definitions/829.html test.c,99,20,3,3,buffer,getopt_long,"Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20).","Check implementation on installation, or limit the size of all string inputs.",,"CWE-120, CWE-20"," while ((optc = getopt_long (argc, argv, ""a"",longopts, NULL )) != EOF) {",5bedf6e5bccf596008ef191ec4c5d4cc51a32cff0c05ef62d5f10fab93d0cc24,2.0.19,FF1027,https://cwe.mitre.org/data/definitions/120.html test.c,16,2,4,2,buffer,strcpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,"Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).",Risk is low because the source is a constant string.,CWE-120," strcpy(a, gettext(""Hello there"")); // Did this work?",d64070fb93ff0bb797fb926f4dddc7212d42f77e288d5ceb0cd30ed2979fa28d,2.0.19,FF1001,https://cwe.mitre.org/data/definitions/120.html test.c,19,2,4,2,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",Risk is low because the source has a constant maximum length.,CWE-120," sprintf(s, ""hello"");",907b46be1c3ea7b38f90a4d1b0f43b7751cd8cbe38fae840930ff006b702157d,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,45,3,2,2,buffer,char,"Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120).","Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.",,CWE-119!/CWE-120, char d[20];,36c87517700337a59cc3ad3218cfdde56cad37d69cdeccee5a55ab232d5c7946,2.0.19,FF1013,https://cwe.mitre.org/data/definitions/119.html test.c,46,3,2,2,buffer,char,"Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120).","Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.",,CWE-119!/CWE-120, char s[20];,213de8e8815fc84c423b55fd845fea541f25744718e486234364bb457863b597,2.0.19,FF1013,https://cwe.mitre.org/data/definitions/119.html test.c,50,3,2,2,buffer,memcpy,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," memcpy(d,s); // fail - no size",e667b352fb0748c67b607b11577b11bad87545779c39923e61839dd04056055f,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,53,3,2,2,buffer,memcpy,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination",01bcc2c8ba2d928ac3315b4dcc6593042ea05e62888a10a6d2cf16797a65ed32,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,54,3,2,2,buffer,memcpy,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," memcpy(d,s,n); // fail - size unguessable",2517a2fb5981193a6017cca660d16e85aab133706cbec302df97aaa623fc77ef,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,55,3,2,2,buffer,CopyMemory,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," CopyMemory(d,s);",977f8c805ddd76ff32e0f7aea08701ba97d9ce6955136e98b308ed4f70eb2e11,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,105,7,2,2,misc,fopen,"Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362).",,,CWE-362," f = fopen(""/etc/passwd"", ""r""); ",2ec6928c77a8b54caa61d0459f367c4394ee1f5e6f488753f587bfa9c780bad8,2.0.19,FF1040,https://cwe.mitre.org/data/definitions/362.html test.c,15,2,4,1,buffer,strcpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,"Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).",Risk is low because the source is a constant character.,CWE-120," strcpy(a, ""\n""); // Did this work?",0badc5f4c500d17b42794feaca54ee0f49e607a32510af3ed749579001017edb,2.0.19,FF1001,https://cwe.mitre.org/data/definitions/120.html test.c,18,2,4,1,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",Risk is low because the source is a constant character.,CWE-120," sprintf(s, ""\n"");",c65fbd60851f3c8ace22332805966606488c0d242c1823493c582e267609b1a7,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,26,2,4,1,buffer,scanf,It's unclear if the %s limit in the format string is small enough (CWE-120).,"Check that the limit is sufficiently small, or use a different input function.",,CWE-120," scanf(""%10s"", s);",e24c4c801f10acfa93098b2bef58524efe4f88237f2dd8b58be9afa838616afe,2.0.19,FF1020,https://cwe.mitre.org/data/definitions/120.html test.c,57,3,1,1,buffer,strncpy,Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).,,,CWE-120," strncpy(d,s);",8fa14bf72393a00f667ffcc06b7b7e5f0b6d2f16d8d67444db06b0deb35b5f5e,2.0.19,FF1008,https://cwe.mitre.org/data/definitions/120.html test.c,58,3,1,1,buffer,_tcsncpy,Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).,,,CWE-120," _tcsncpy(d,s);",691fabd4ca960a00e4c538eee0187ee0fdf59bd43dd71e792c14175150369b8b,2.0.19,FF1009,https://cwe.mitre.org/data/definitions/120.html test.c,59,3,1,1,buffer,strncat,"Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120).","Consider strcat_s, strlcat, snprintf, or automatically resizing strings.",,CWE-120," strncat(d,s,10);",dd92f996a554bfbc038bea27640ba25dcf298383140a8330dca7cdacf493a701,2.0.19,FF1010,https://cwe.mitre.org/data/definitions/120.html test.c,62,7,1,1,buffer,strlen,Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126).,,,CWE-126, n = strlen(d);,db7201c7df7f543ea76febb060bda167e414e71e3d18095fe1def69f8c47a4f6,2.0.19,FF1022,https://cwe.mitre.org/data/definitions/126.html test.c,68,3,2,1,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is very low, the length appears to be in characters not bytes.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));",1813fc329227b38abae867d8023a9e29c7517d679fe55c86f8300dde681b6470,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html test.c,70,3,2,1,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is very low, the length appears to be in characters not bytes.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));",7c6cdcb10ad3a16b8bfd56e3dac84829f9bc3e39d4dde74a2be9bbe000102fc5,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html flawfinder-2.0.19/test/makefile000644 000765 000024 00000007705 14025737107 017364 0ustar00dwheelerstaff000000 000000 # Flawfinder. # Released under the General Public License (GPL) version 2 or later. # (C) 2001-2017 David A. Wheeler. PYTHON=python PYTHON2=python2 PYTHON3=python3 FLAWFINDER=../flawfinder.py SETUPPY=../setup.py test_001: $(FLAWFINDER) test.c test2.c @echo 'test_001 (text output)' @# Omit time report so that results are always the same textually. @$(PYTHON) $(FLAWFINDER) --omittime test.c test2.c > test-results.txt @echo >> test-results.txt @echo "Testing for no ending newline:" >> test-results.txt @$(PYTHON) $(FLAWFINDER) --omittime no-ending-newline.c | \ grep 'Lines analyzed' >> test-results.txt @diff -u correct-results.txt test-results.txt test_002: $(FLAWFINDER) test.c test2.c @echo 'test_002 (HTML output)' @$(PYTHON) $(FLAWFINDER) --omittime --html --context test.c test2.c > test-results.html @diff -u correct-results.html test-results.html test_003: $(FLAWFINDER) test.c test2.c @echo 'test_003 (CSV output)' @$(PYTHON) $(FLAWFINDER) --csv test.c test2.c > test-results.csv @diff -u correct-results.csv test-results.csv test_004: $(FLAWFINDER) test.c @echo 'test_004 (single-line)' @$(PYTHON) $(FLAWFINDER) -m 5 -S -DC --quiet test.c > \ test-results-004.txt @diff -u correct-results-004.txt test-results-004.txt test_005: $(FLAWFINDER) test-diff-005.patch test-patched.c @echo 'test_005 (diff)' @$(PYTHON) $(FLAWFINDER) -SQDC -P test-diff-005.patch \ test-patched.c > test-results-005.txt @diff -u correct-results-005.txt test-results-005.txt test_006: $(FLAWFINDER) test.c @echo 'test_006 (save/load hitlist)' @$(PYTHON) $(FLAWFINDER) -S -DC --quiet \ --savehitlist test-saved-hitlist-006.txt \ test.c > test-junk-006.txt @$(PYTHON) $(FLAWFINDER) -SQDC -m 5 \ --loadhitlist test-saved-hitlist-006.txt > \ test-results-006.txt @diff -u correct-results-006.txt test-results-006.txt test_007: $(SETUPPY) @echo 'test_007 (setup.py sane)' @test "`$(PYTHON) $(SETUPPY) --name`" = 'flawfinder' @test "`$(PYTHON) $(SETUPPY) --license`" = 'GPL-2.0+' @test "`$(PYTHON) $(SETUPPY) --author`" = 'David A. Wheeler' test_008: $(FLAWFINDER) test.c @echo 'test_008 (diff hitlist)' @$(PYTHON) $(FLAWFINDER) -S -DC --quiet \ --savehitlist test-saved-hitlist-008.txt \ test.c > test-junk-008.txt @$(PYTHON) $(FLAWFINDER) -S -C --quiet --omittime \ --diffhitlist test-saved-hitlist-008.txt test.c > \ test-results-008.txt @diff -u correct-results-008.txt test-results-008.txt test_009: $(FLAWFINDER) test-cpp-digit-separator.cpp @echo 'test_009 (C++ digit separator)' # C++ file should have no problem recognizing ' as digit separator @$(PYTHON) $(FLAWFINDER) test-cpp-digit-separator.cpp > /dev/null # C file should fail with unterminated char literal error @$(PYTHON) $(FLAWFINDER) test-cpp-digit-separator.c 2>&1 \ | grep 'File ended while in string.' \ > /dev/null test_010: $(FLAWFINDER) test-boost-system.hpp @echo 'test_010 (system:: ignored)' @$(PYTHON) $(FLAWFINDER) --error-level 2 test-boost-system.hpp \ > /dev/null # Run all tests on *one* version of Python; # output shows differences from expected results. # If everything works as expected, it just prints test numbers. # Set PYTHON as needed, including to "" test: test_001 test_002 test_003 test_004 test_005 test_006 test_007 test_008 \ test_009 test_010 @echo 'All tests pass!' # Usual check routine. Run all tests using *both* python2 and python3. check: @echo "Testing with $(PYTHON2)" @PYTHON="$(PYTHON2)" $(MAKE) test @echo @echo "Testing with $(PYTHON3)" @PYTHON="$(PYTHON3)" $(MAKE) test # Run "make test-is-correct" if the results are as expected. test-is-correct: test-results.txt cp -p test-results.txt correct-results.txt cp -p test-results.html correct-results.html cp -p test-results.csv correct-results.csv cp -p test-results-004.txt correct-results-004.txt cp -p test-results-005.txt correct-results-005.txt cp -p test-results-006.txt correct-results-006.txt cp -p test-results-008.txt correct-results-008.txt .PHONY: test check test-is-correct flawfinder-2.0.19/test/correct-results.txt000644 000765 000024 00000021370 14112766107 021556 0ustar00dwheelerstaff000000 000000 Flawfinder version 2.0.19, (C) 2001-2019 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 222 Examining test.c Examining test2.c FINAL RESULTS: test.c:32: [5] (buffer) gets: Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:17: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). test.c:20: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:21: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:22: [4] (format) sprintf: Potential format string problem (CWE-134). Make format string constant. test.c:23: [4] (format) printf: If format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant for the format specification. test.c:25: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:27: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:38: [4] (format) syslog: If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant format string for syslog. test.c:49: [4] (buffer) _mbscpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using a function version that stops copying at the end of the buffer. test.c:56: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120). test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:81: [3] (misc) LoadLibraryEx: Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20). Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders. test.c:99: [3] (buffer) getopt_long: Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20). Check implementation on installation, or limit the size of all string inputs. test.c:16: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. test.c:19: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. test.c:45: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:46: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:50: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:53: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:54: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:55: [2] (buffer) CopyMemory: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:105: [2] (misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). test.c:15: [1] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant character. test.c:18: [1] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source is a constant character. test.c:26: [1] (buffer) scanf: It's unclear if the %s limit in the format string is small enough (CWE-120). Check that the limit is sufficiently small, or use a different input function. test.c:57: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:58: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:59: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. test.c:62: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). test.c:68: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. test.c:70: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. ANALYSIS SUMMARY: Hits = 39 Lines analyzed = 126 Physical Source Lines of Code (SLOC) = 86 Hits@level = [0] 16 [1] 9 [2] 9 [3] 4 [4] 10 [5] 7 Hits@level+ = [0+] 55 [1+] 39 [2+] 30 [3+] 21 [4+] 17 [5+] 7 Hits/KSLOC@level+ = [0+] 639.535 [1+] 453.488 [2+] 348.837 [3+] 244.186 [4+] 197.674 [5+] 81.3953 Suppressed hits = 2 (use --neverignore to show them) Minimum risk level = 1 Not every hit is necessarily a security vulnerability. You can inhibit a report by adding a comment in this form: // flawfinder: ignore Make *sure* it's a false positive! You can use the option --neverignore to show these. There may be other security vulnerabilities; review your code! See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. Testing for no ending newline: Lines analyzed = 32 flawfinder-2.0.19/test/test-saved-hitlist-008.txt000644 000765 000024 00000050750 14112766124 022463 0ustar00dwheelerstaff000000 000000 (lp0 ccopy_reg _reconstructor p1 (c__main__ Hit p2 c__builtin__ object p3 Ntp4 Rp5 (dp6 S'category' p7 S'buffer' p8 sS'filename' p9 S'test.c' p10 sS'end' p11 I692 sS'name' p12 S'gets' p13 sS'parameters' p14 (lp15 S'' p16 aS'f' p17 asS'level' p18 I5 sS'url' p19 g16 sS'ruleid' p20 S'FF1014' p21 sS'column' p22 I2 sS'context_text' p23 S' gets(f);' p24 sS'hook' p25 c__main__ normal p26 sS'warning' p27 S'Does not check for buffer overflows (CWE-120, CWE-20)' p28 sS'suggestion' p29 S'Use fgets() instead' p30 sS'input' p31 I1 sS'line' p32 I32 sS'defaultlevel' p33 I5 sS'start' p34 I688 sbag1 (g2 g3 Ntp35 Rp36 (dp37 g7 g8 sg9 g10 sg11 I1462 sg12 S'strncat' p38 sg14 (lp39 g16 aS'd' p40 aS's' p41 aS'sizeof(d)' p42 asg18 I5 sg19 g16 sg20 S'FF1010' p43 sg22 I3 sg23 S' strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */' p44 sS'note' p45 S'Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.' p46 sg25 c__main__ c_strncat p47 sg27 S'Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120)' p48 sg29 S'Consider strcat_s, strlcat, snprintf, or automatically resizing strings' p49 sg32 I60 sg33 I1 sg34 I1455 sbag1 (g2 g3 Ntp50 Rp51 (dp52 g7 g8 sg9 g10 sg11 I1539 sg12 S'_tcsncat' p53 sg14 (lp54 g16 aS'd' p55 aS's' p56 aS'sizeof(d)' p57 asg18 I5 sg19 g16 sg20 S'FF1011' p58 sg22 I3 sg23 S' _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */' p59 sg45 g46 sg25 g47 sg27 g48 sg29 S'Consider strcat_s, strlcat, or automatically resizing strings' p60 sg32 I61 sg33 I1 sg34 I1531 sbag1 (g2 g3 Ntp61 Rp62 (dp63 g7 g8 sg9 g10 sg11 I1680 sg12 S'MultiByteToWideChar' p64 sg14 (lp65 g16 aS'CP_ACP' p66 aS'0' p67 aS'szName' p68 aS'-1' p69 aS'wszUserName' p70 aS'sizeof(wszUserName)' p71 asg18 I5 sg19 g16 sg20 S'FF1023' p72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));' p73 sg45 S'Risk is high, it appears that the size is given as bytes, but the function requires size as characters.' p74 sg25 c__main__ c_multi_byte_to_wide_char p75 sg27 S'Requires maximum length in CHARACTERS, not bytes (CWE-120)' p76 sg29 g16 sg32 I64 sg33 I2 sg34 I1661 sbag1 (g2 g3 Ntp77 Rp78 (dp79 g7 g8 sg9 g10 sg11 I1815 sg12 S'MultiByteToWideChar' p80 sg14 (lp81 g16 aS'CP_ACP' p82 aS'0' p83 aS'szName' p84 aS'-1' p85 aS'wszUserName' p86 aS'sizeof wszUserName' p87 asg18 I5 sg19 g16 sg20 g72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);' p88 sg45 g74 sg25 g75 sg27 g76 sg29 g16 sg32 I66 sg33 I2 sg34 I1796 sbag1 (g2 g3 Ntp89 Rp90 (dp91 g7 S'misc' p92 sg9 g10 sg11 I2533 sg12 S'SetSecurityDescriptorDacl' p93 sg14 (lp94 g16 aS'&sd' p95 aS'TRUE' p96 aS'NULL' p97 aS'FALSE' p98 asg18 I5 sg19 g16 sg20 S'FF1060' p99 sg22 I3 sg34 I2508 sg23 S' SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);' p100 sg25 c__main__ c_hit_if_null p101 sg27 S'Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732)' p102 sg29 g16 sg32 I77 sg33 I5 sS'check_for_null' p103 I3 sbag90 ag1 (g2 g3 Ntp104 Rp105 (dp106 g7 g8 sg9 g10 sg11 I372 sg12 S'strcpy' p107 sg14 (lp108 g16 aS'b' p109 aS'a' p110 asg18 I4 sg19 g16 sg20 S'FF1001' p111 sg22 I2 sg23 S' strcpy(b, a);' p112 sg25 c__main__ c_buffer p113 sg27 S'Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)' p114 sg29 S'Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)' p115 sg32 I17 sg33 I4 sg34 I366 sbag1 (g2 g3 Ntp116 Rp117 (dp118 g7 g8 sg9 g10 sg11 I429 sg12 S'sprintf' p119 sg14 (lp120 g16 aS's' p121 aS'"hello %s"' p122 aS'bug' p123 asg18 I4 sg19 g16 sg20 S'FF1015' p124 sg22 I2 sg23 S' sprintf(s, "hello %s", bug);' p125 sg25 c__main__ c_sprintf p126 sg27 S'Does not check for buffer overflows (CWE-120)' p127 sg29 S'Use sprintf_s, snprintf, or vsnprintf' p128 sg32 I20 sg33 I4 sg34 I422 sbag1 (g2 g3 Ntp129 Rp130 (dp131 g7 g8 sg9 g10 sg11 I459 sg12 S'sprintf' p132 sg14 (lp133 g16 aS's' p134 aS'gettext("hello %s")' p135 aS'bug' p136 asg18 I4 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, gettext("hello %s"), bug);' p137 sg25 g126 sg27 g127 sg29 g128 sg32 I21 sg33 I4 sg34 I452 sbag1 (g2 g3 Ntp138 Rp139 (dp140 g7 S'format' p141 sg9 g10 sg11 I498 sg12 S'sprintf' p142 sg14 (lp143 g16 aS's' p144 aS'unknown' p145 aS'bug' p146 asg18 I4 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, unknown, bug);' p147 sg25 g126 sg27 S'Potential format string problem (CWE-134)' p148 sg29 S'Make format string constant' p149 sg32 I22 sg33 I4 sg34 I491 sbag1 (g2 g3 Ntp150 Rp151 (dp152 g7 g141 sg9 g10 sg11 I524 sg12 S'printf' p153 sg14 (lp154 g16 aS'bf' p155 aS'x' p156 asg18 I4 sg19 g16 sg20 S'FF1016' p157 sg22 I2 sg23 S' printf(bf, x);' p158 sg25 c__main__ c_printf p159 sg27 S'If format strings can be influenced by an attacker, they can be exploited (CWE-134)' p160 sg29 S'Use a constant for the format specification' p161 sg32 I23 sg33 I4 sg34 I518 sbag1 (g2 g3 Ntp162 Rp163 (dp164 g7 g8 sg9 g10 sg11 I557 sg12 S'scanf' p165 sg14 (lp166 g16 aS'"%s"' p167 aS's' p168 asg18 I4 sg19 g16 sg20 S'FF1020' p169 sg22 I2 sg23 S' scanf("%s", s);' p170 sg25 c__main__ c_scanf p171 sg27 S"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20)" p172 sg29 S'Specify a limit to %s, or use a different input function' p173 sg31 I1 sg32 I25 sg33 I4 sg34 I552 sbag1 (g2 g3 Ntp174 Rp175 (dp176 g7 g8 sg9 g10 sg11 I593 sg12 S'scanf' p177 sg14 (lp178 g16 aS'"%s"' p179 ag168 asg18 I4 sg19 g16 sg20 g169 sg22 I2 sg23 S' scanf("%s", s);' p180 sg25 g171 sg27 g172 sg29 g173 sg31 I1 sg32 I27 sg33 I4 sg34 I588 sbag1 (g2 g3 Ntp181 Rp182 (dp183 g7 g141 sg9 g10 sg11 I997 sg12 S'syslog' p184 sg14 (lp185 g16 aS'LOG_ERR' p186 aS'attacker_string' p187 asg18 I4 sg19 g16 sg20 S'FF1018' p188 sg22 I2 sg23 S' syslog(LOG_ERR, attacker_string);' p189 sg25 g159 sS'format_position' p190 I2 sg27 S"If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134)" p191 sg29 S'Use a constant format string for syslog' p192 sg32 I38 sg33 I4 sg34 I991 sbag1 (g2 g3 Ntp193 Rp194 (dp195 g7 g8 sg9 g10 sg11 I1088 sg12 S'_mbscpy' p196 sg14 (lp197 g16 aS'd' p198 aS's' p199 asg18 I4 sg19 g16 sg20 S'FF1003' p200 sg22 I3 sg23 S" _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */" p201 sg25 g113 sg27 g114 sg29 S'Consider using a function version that stops copying at the end of the buffer' p202 sg32 I49 sg33 I4 sg34 I1081 sbag1 (g2 g3 Ntp203 Rp204 (dp205 g7 g8 sg9 g10 sg11 I1394 sg12 S'lstrcat' p206 sg14 (lp207 g16 aS'd' p208 aS's' p209 asg18 I4 sg19 g16 sg20 S'FF1006' p210 sg22 I3 sg23 S' lstrcat(d,s);' p211 sg25 g113 sg27 S'Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120)' p212 sg29 g16 sg32 I56 sg33 I4 sg34 I1387 sbag1 (g2 g3 Ntp213 Rp214 (dp215 g7 S'shell' p216 sg9 g10 sg11 I2634 sg12 S'CreateProcess' p217 sg14 (lp218 g16 aS'NULL' p219 aS'"C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x"' p220 aS'""' p221 asg18 I3 sg19 g16 sg20 S'FF1046' p222 sg22 I3 sg34 I2621 sg23 S' CreateProcess(NULL, "C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x", "");' p223 sg25 g101 sg27 S'This causes a new process to execute and is difficult to use safely (CWE-78)' p224 sg29 S'Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run' p225 sg32 I79 sg33 I3 sg103 I1 sbag214 ag1 (g2 g3 Ntp226 Rp227 (dp228 g7 g92 sg9 g10 sg11 I2759 sg12 S'LoadLibraryEx' p229 sg14 (lp230 g16 aS'L"user32.dll"' p231 aS'nullptr' p232 aS'LOAD_LIBRARY_AS_DATAFILE' p233 asg18 I3 sg19 g16 sg20 S'FF1059' p234 sg22 I10 sg23 S' (void) LoadLibraryEx(L"user32.dll", nullptr, LOAD_LIBRARY_AS_DATAFILE);' p235 sg25 c__main__ load_library_ex p236 sg27 S'Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20)' p237 sg29 S'Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders' p238 sg31 I1 sg32 I81 sg33 I3 sg34 I2746 sbag1 (g2 g3 Ntp239 Rp240 (dp241 g7 g8 sg9 g10 sg11 I3361 sg12 S'getopt_long' p242 sg14 (lp243 g16 aS'argc' p244 aS'argv' p245 aS'"a"' p246 aS'longopts' p247 aS'NULL' p248 asg18 I3 sg19 S'dangers-c' p249 sg20 S'FF1027' p250 sg22 I20 sg23 S' while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) {' p251 sg25 g26 sg27 S'Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20)' p252 sg29 S'Check implementation on installation, or limit the size of all string inputs' p253 sg31 I1 sg32 I99 sg33 I3 sg34 I3350 sbag1 (g2 g3 Ntp254 Rp255 (dp256 g7 g8 sg9 g10 sg11 I318 sg12 S'strcpy' p257 sg14 (lp258 g16 aS'a' p259 aS'gettext("Hello there")' p260 asg18 I2 sg19 g16 sg20 g111 sg22 I2 sg23 S' strcpy(a, gettext("Hello there")); // Did this work?' p261 sg45 S'Risk is low because the source is a constant string.' p262 sg25 g113 sg27 g114 sg29 g115 sg32 I16 sg33 I4 sg34 I312 sbag1 (g2 g3 Ntp263 Rp264 (dp265 g7 g8 sg9 g10 sg11 I407 sg12 S'sprintf' p266 sg14 (lp267 g16 aS's' p268 aS'"hello"' p269 asg18 I2 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, "hello");' p270 sg45 S'Risk is low because the source has a constant maximum length.' p271 sg25 g126 sg27 g127 sg29 g128 sg32 I19 sg33 I4 sg34 I400 sbag1 (g2 g3 Ntp272 Rp273 (dp274 g7 g8 sg9 g10 sg11 I1047 sg12 S'char' p275 sg14 (lp276 sg18 I2 sg19 g16 sS'lookahead' p277 S"char d[20];\n char s[20];\n int n;\n\n _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */\n memcpy(d,s); // fail - no size\n memcpy(d, s, sizeof(d)); // pass\n memcpy(& n, s, sizeof( n )); // pass\n memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination\n memcpy(d,s,n); // fail - size unguessable\n CopyMemory(d,s);\n lstrcat(d,s);\n strncpy(d,s);\n _tcsncpy(d,s);\n strncat(d,s,10);\n strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */\n _tcsncat(d,s" p278 sg20 S'FF1013' p279 sg22 I3 sg23 S' char d[20];' p280 sg25 c__main__ c_static_array p281 sg27 S'Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)' p282 sg29 S'Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length' p283 sg32 I45 sg33 I2 sg34 I1043 sS'extract_lookahead' p284 I1 sbag1 (g2 g3 Ntp285 Rp286 (dp287 g7 g8 sg9 g10 sg11 I1061 sg12 S'char' p288 sg14 (lp289 sg18 I2 sg19 g16 sg277 S"char s[20];\n int n;\n\n _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */\n memcpy(d,s); // fail - no size\n memcpy(d, s, sizeof(d)); // pass\n memcpy(& n, s, sizeof( n )); // pass\n memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination\n memcpy(d,s,n); // fail - size unguessable\n CopyMemory(d,s);\n lstrcat(d,s);\n strncpy(d,s);\n _tcsncpy(d,s);\n strncat(d,s,10);\n strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */\n _tcsncat(d,s,sizeof(d)); /" p290 sg20 g279 sg22 I3 sg23 S' char s[20];' p291 sg25 g281 sg27 g282 sg29 g283 sg32 I46 sg33 I2 sg34 I1057 sg284 I1 sbag1 (g2 g3 Ntp292 Rp293 (dp294 g7 g8 sg9 g10 sg11 I1161 sg12 S'memcpy' p295 sg14 (lp296 g16 aS'd' p297 aS's' p298 asg18 I2 sg19 g16 sg20 S'FF1004' p299 sg22 I3 sg23 S' memcpy(d,s); // fail - no size' p300 sg25 c__main__ c_memcpy p301 sg27 S'Does not check for buffer overflows when copying to destination (CWE-120)' p302 sg29 S'Make sure destination can always hold the source data' p303 sg32 I50 sg33 I2 sg34 I1155 sbag1 (g2 g3 Ntp304 Rp305 (dp306 g7 g8 sg9 g10 sg11 I1268 sg12 S'memcpy' p307 sg14 (lp308 g16 aS'&n' p309 aS's' p310 aS'sizeof(s)' p311 asg18 I2 sg19 g16 sg20 g299 sg22 I3 sg23 S' memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination' p312 sg25 g301 sg27 g302 sg29 g303 sg32 I53 sg33 I2 sg34 I1262 sbag1 (g2 g3 Ntp313 Rp314 (dp315 g7 g8 sg9 g10 sg11 I1330 sg12 S'memcpy' p316 sg14 (lp317 g16 aS'd' p318 aS's' p319 aS'n' p320 asg18 I2 sg19 g16 sg20 g299 sg22 I3 sg23 S' memcpy(d,s,n); // fail - size unguessable' p321 sg25 g301 sg27 g302 sg29 g303 sg32 I54 sg33 I2 sg34 I1324 sbag1 (g2 g3 Ntp322 Rp323 (dp324 g7 g8 sg9 g10 sg11 I1378 sg12 S'CopyMemory' p325 sg14 (lp326 g16 aS'd' p327 aS's' p328 asg18 I2 sg19 g16 sg20 g299 sg22 I3 sg23 S' CopyMemory(d,s);' p329 sg25 g301 sg27 g302 sg29 g303 sg32 I55 sg33 I2 sg34 I1368 sbag1 (g2 g3 Ntp330 Rp331 (dp332 g7 g92 sg9 g10 sg11 I3455 sg12 S'fopen' p333 sg14 (lp334 g16 aS'"/etc/passwd"' p335 aS'"r"' p336 asg18 I2 sg19 g16 sg20 S'FF1040' p337 sg22 I7 sg23 S' f = fopen("/etc/passwd", "r"); ' p338 sg25 g26 sg27 S'Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)' p339 sg29 g16 sg32 I105 sg33 I2 sg34 I3450 sbag1 (g2 g3 Ntp340 Rp341 (dp342 g7 g8 sg9 g10 sg11 I282 sg12 S'strcpy' p343 sg14 (lp344 g16 aS'a' p345 aS'"\\n"' p346 asg18 I1 sg19 g16 sg20 g111 sg22 I2 sg23 S' strcpy(a, "\\n"); // Did this work?' p347 sg45 S'Risk is low because the source is a constant character.' p348 sg25 g113 sg27 g114 sg29 g115 sg32 I15 sg33 I4 sg34 I276 sbag1 (g2 g3 Ntp349 Rp350 (dp351 g7 g8 sg9 g10 sg11 I388 sg12 S'sprintf' p352 sg14 (lp353 g16 aS's' p354 aS'"\\n"' p355 asg18 I1 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, "\\n");' p356 sg45 S'Risk is low because the source is a constant character.' p357 sg25 g126 sg27 g127 sg29 g128 sg32 I18 sg33 I4 sg34 I381 sbag1 (g2 g3 Ntp358 Rp359 (dp360 g7 g8 sg9 g10 sg11 I574 sg12 S'scanf' p361 sg14 (lp362 g16 aS'"%10s"' p363 ag168 asg18 I1 sg19 g16 sg20 g169 sg22 I2 sg23 S' scanf("%10s", s);' p364 sg25 g171 sg27 S"It's unclear if the %s limit in the format string is small enough (CWE-120)" p365 sg29 S'Check that the limit is sufficiently small, or use a different input function' p366 sg31 I1 sg32 I26 sg33 I4 sg34 I569 sbag1 (g2 g3 Ntp367 Rp368 (dp369 g7 g8 sg9 g10 sg11 I1410 sg12 S'strncpy' p370 sg14 (lp371 g16 aS'd' p372 aS's' p373 asg18 I1 sg19 g16 sg20 S'FF1008' p374 sg22 I3 sg23 S' strncpy(d,s);' p375 sg25 g113 sg27 S"Easily used incorrectly; doesn't always \\0-terminate or check for invalid pointers [MS-banned] (CWE-120)" p376 sg29 g16 sg32 I57 sg33 I1 sg34 I1403 sbag1 (g2 g3 Ntp377 Rp378 (dp379 g7 g8 sg9 g10 sg11 I1427 sg12 S'_tcsncpy' p380 sg14 (lp381 g16 aS'd' p382 aS's' p383 asg18 I1 sg19 g16 sg20 S'FF1009' p384 sg22 I3 sg23 S' _tcsncpy(d,s);' p385 sg25 g113 sg27 g376 sg29 g16 sg32 I58 sg33 I1 sg34 I1419 sbag1 (g2 g3 Ntp386 Rp387 (dp388 g7 g8 sg9 g10 sg11 I1443 sg12 S'strncat' p389 sg14 (lp390 g16 aS'd' p391 aS's' p392 aS'10' p393 asg18 I1 sg19 g16 sg20 g43 sg22 I3 sg23 S' strncat(d,s,10);' p394 sg25 g47 sg27 g48 sg29 g49 sg32 I59 sg33 I1 sg34 I1436 sbag1 (g2 g3 Ntp395 Rp396 (dp397 g7 g8 sg9 g10 sg11 I1599 sg12 S'strlen' p398 sg14 (lp399 g16 aS'd' p400 asg18 I1 sg19 g16 sg20 S'FF1022' p401 sg22 I7 sg23 S' n = strlen(d);' p402 sg25 g26 sg27 S'Does not handle strings that are not \\0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126)' p403 sg29 g16 sg32 I62 sg33 I1 sg34 I1593 sbag1 (g2 g3 Ntp404 Rp405 (dp406 g7 g8 sg9 g10 sg11 I1918 sg12 S'MultiByteToWideChar' p407 sg14 (lp408 g16 aS'CP_ACP' p409 aS'0' p410 aS'szName' p411 aS'-1' p412 aS'wszUserName' p413 aS'sizeof(wszUserName)/sizeof(wszUserName[0])' p414 asg18 I1 sg19 g16 sg20 g72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));' p415 sg45 S'Risk is very low, the length appears to be in characters not bytes.' p416 sg25 g75 sg27 g76 sg29 g16 sg32 I68 sg33 I2 sg34 I1899 sbag1 (g2 g3 Ntp417 Rp418 (dp419 g7 g8 sg9 g10 sg11 I2045 sg12 S'MultiByteToWideChar' p420 sg14 (lp421 g16 aS'CP_ACP' p422 aS'0' p423 aS'szName' p424 aS'-1' p425 aS'wszUserName' p426 aS'sizeof wszUserName /sizeof(wszUserName[0])' p427 asg18 I1 sg19 g16 sg20 g72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));' p428 sg45 g416 sg25 g75 sg27 g76 sg29 g16 sg32 I70 sg33 I2 sg34 I2026 sbag1 (g2 g3 Ntp429 Rp430 (dp431 g7 g141 sg9 g10 sg11 I200 sg12 S'printf' p432 sg14 (lp433 g16 aS'"hello\\n"' p434 asg18 I0 sg19 g16 sg20 g157 sg22 I2 sg23 S' printf("hello\\n");' p435 sg45 S'Constant format string, so not considered risky.' p436 sg25 g159 sg27 g160 sg29 g161 sg32 I9 sg33 I4 sg34 I194 sbag1 (g2 g3 Ntp437 Rp438 (dp439 g7 g8 sg9 g10 sg11 I539 sg12 S'scanf' p440 sg14 (lp441 g16 aS'"%d"' p442 aS'&x' p443 asg18 I0 sg19 g16 sg20 g169 sg22 I2 sg23 S' scanf("%d", &x);' p444 sg45 S'No risky scanf format detected.' p445 sg25 g171 sg27 g172 sg29 g173 sg31 I1 sg32 I24 sg33 I4 sg34 I534 sbag1 (g2 g3 Ntp446 Rp447 (dp448 g7 g141 sg9 g10 sg11 I643 sg12 S'printf' p449 sg14 (lp450 g16 aS'"\\\\"' p451 asg18 I0 sg19 g16 sg20 g157 sg22 I2 sg23 S' printf("\\\\");' p452 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I29 sg33 I4 sg34 I637 sbag1 (g2 g3 Ntp453 Rp454 (dp455 g7 g141 sg9 g10 sg11 I837 sg12 S'syslog' p456 sg14 (lp457 g16 aS'LOG_ERR' p458 aS'"cannot open config file (%s): %s"' p459 aS'filename' p460 aS'strerror(errno)' p461 asg18 I0 sg19 g16 sg20 g188 sg22 I2 sg23 S' syslog(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno))' p462 sg45 g436 sg25 g159 sg190 I2 sg27 g191 sg29 g192 sg32 I35 sg33 I4 sg34 I831 sbag1 (g2 g3 Ntp463 Rp464 (dp465 g7 g141 sg9 g10 sg11 I914 sg12 S'syslog' p466 sg14 (lp467 g16 aS'LOG_CRIT' p468 aS'"malloc() failed"' p469 asg18 I0 sg19 g16 sg20 g188 sg22 I2 sg23 S' syslog(LOG_CRIT,"malloc() failed");' p470 sg45 g436 sg25 g159 sg190 I2 sg27 g191 sg29 g192 sg32 I36 sg33 I4 sg34 I908 sbag1 (g2 g3 Ntp471 Rp472 (dp473 g7 g141 sg9 g10 sg11 I3049 sg12 S'printf' p474 sg14 (lp475 g16 aS'"%c\\n"' p476 aS"'x'" p477 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'x\');' p478 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I85 sg33 I4 sg34 I3043 sbag1 (g2 g3 Ntp479 Rp480 (dp481 g7 g141 sg9 g10 sg11 I3072 sg12 S'printf' p482 sg14 (lp483 g16 aS'"%c\\n"' p484 aS'\'"\'' p485 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'"\');' p486 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I86 sg33 I4 sg34 I3066 sbag1 (g2 g3 Ntp487 Rp488 (dp489 g7 g141 sg9 g10 sg11 I3095 sg12 S'printf' p490 sg14 (lp491 g16 aS'"%c\\n"' p492 aS'\'\\"\'' p493 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\"\');' p494 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I87 sg33 I4 sg34 I3089 sbag1 (g2 g3 Ntp495 Rp496 (dp497 g7 g141 sg9 g10 sg11 I3119 sg12 S'printf' p498 sg14 (lp499 g16 aS'"%c\\n"' p500 aS"'\\''" p501 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\\'\');' p502 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I88 sg33 I4 sg34 I3113 sbag1 (g2 g3 Ntp503 Rp504 (dp505 g7 g141 sg9 g10 sg11 I3143 sg12 S'printf' p506 sg14 (lp507 g16 aS'"%c\\n"' p508 aS"'\\177'" p509 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\177\');' p510 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I89 sg33 I4 sg34 I3137 sbag1 (g2 g3 Ntp511 Rp512 (dp513 g7 g141 sg9 g10 sg11 I3169 sg12 S'printf' p514 sg14 (lp515 g16 aS'"%c\\n"' p516 aS"'\\xfe'" p517 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\xfe\');' p518 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I90 sg33 I4 sg34 I3163 sbag1 (g2 g3 Ntp519 Rp520 (dp521 g7 g141 sg9 g10 sg11 I3195 sg12 S'printf' p522 sg14 (lp523 g16 aS'"%c\\n"' p524 aS"'\\xd'" p525 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\xd\');' p526 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I91 sg33 I4 sg34 I3189 sbag1 (g2 g3 Ntp527 Rp528 (dp529 g7 g141 sg9 g10 sg11 I3220 sg12 S'printf' p530 sg14 (lp531 g16 aS'"%c\\n"' p532 aS"'\\n'" p533 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\n\');' p534 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I92 sg33 I4 sg34 I3214 sbag1 (g2 g3 Ntp535 Rp536 (dp537 g7 g141 sg9 g10 sg11 I3244 sg12 S'printf' p538 sg14 (lp539 g16 aS'"%c\\n"' p540 aS"'\\\\'" p541 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\\\\');' p542 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I93 sg33 I4 sg34 I3238 sbag1 (g2 g3 Ntp543 Rp544 (dp545 g7 g141 sg9 g10 sg11 I3268 sg12 S'printf' p546 sg14 (lp547 g16 aS'"%c\\n"' p548 aS'"\'"' p549 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", "\'");' p550 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I94 sg33 I4 sg34 I3262 sbag1 (g2 g3 Ntp551 Rp552 (dp553 g7 g141 sg9 g10 sg11 I3593 sg12 S'fprintf' p554 sg14 (lp555 g16 aS'stderr' p556 aS'"Assertion failed.\\n"\\\n "File: %s\\nLine: %d\\n"\\\n "Assertion: %s\\n\\n"' p557 aS'__FILE__' p558 aS'__LINE__' p559 aS'#x' p560 asg18 I0 sg19 g16 sg20 S'FF1017' p561 sg22 I2 sg23 S' fprintf(stderr,"Assertion failed.\\n"\\' p562 sg45 g436 sg25 g159 sg190 I2 sg27 g160 sg29 g161 sg32 I113 sg33 I4 sg34 I3586 sba.flawfinder-2.0.19/test/test-junk-006.txt000644 000765 000024 00000017241 14112766124 020646 0ustar00dwheelerstaff000000 000000 test.c:32:2: [5] (buffer) gets:Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60:3: [5] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61:3: [5] (buffer) _tcsncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:17:2: [4] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). test.c:20:2: [4] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:21:2: [4] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:22:2: [4] (format) sprintf:Potential format string problem (CWE-134). Make format string constant. test.c:23:2: [4] (format) printf:If format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant for the format specification. test.c:25:2: [4] (buffer) scanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:27:2: [4] (buffer) scanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:38:2: [4] (format) syslog:If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant format string for syslog. test.c:49:3: [4] (buffer) _mbscpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using a function version that stops copying at the end of the buffer. test.c:56:3: [4] (buffer) lstrcat:Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120). test.c:79:3: [3] (shell) CreateProcess:This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:79:3: [3] (shell) CreateProcess:This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:81:10: [3] (misc) LoadLibraryEx:Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20). Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders. test.c:99:20: [3] (buffer) getopt_long:Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20). Check implementation on installation, or limit the size of all string inputs. test.c:16:2: [2] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. test.c:19:2: [2] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. test.c:45:3: [2] (buffer) char:Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:46:3: [2] (buffer) char:Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:50:3: [2] (buffer) memcpy:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:53:3: [2] (buffer) memcpy:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:54:3: [2] (buffer) memcpy:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:55:3: [2] (buffer) CopyMemory:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:105:7: [2] (misc) fopen:Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). test.c:15:2: [1] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant character. test.c:18:2: [1] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source is a constant character. test.c:26:2: [1] (buffer) scanf:It's unclear if the %s limit in the format string is small enough (CWE-120). Check that the limit is sufficiently small, or use a different input function. test.c:57:3: [1] (buffer) strncpy:Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:58:3: [1] (buffer) _tcsncpy:Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:59:3: [1] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. test.c:62:7: [1] (buffer) strlen:Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). test.c:68:3: [1] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. test.c:70:3: [1] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. flawfinder-2.0.19/test/no-ending-newline.c000644 000765 000024 00000000670 13774402305 021336 0ustar00dwheelerstaff000000 000000 // Test file to show bug in 1.27 #include #include #include int main() { FILE *f; char buf[1024], *s; int first; first = 1; while(fgets(buf, sizeof(buf), stdin) != 0) { if(first == 0) { printf("\n"); } s = buf; while(*s != '\0') { if(*s == '\n' || *s == '\r') { *s = '\0'; break; } s++; } printf("%s", buf); first = 0; } } /* end with spaces and no \n or \r */ flawfinder-2.0.19/test/test-junk-008.txt000644 000765 000024 00000017241 14112766124 020650 0ustar00dwheelerstaff000000 000000 test.c:32:2: [5] (buffer) gets:Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60:3: [5] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61:3: [5] (buffer) _tcsncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:17:2: [4] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). test.c:20:2: [4] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:21:2: [4] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:22:2: [4] (format) sprintf:Potential format string problem (CWE-134). Make format string constant. test.c:23:2: [4] (format) printf:If format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant for the format specification. test.c:25:2: [4] (buffer) scanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:27:2: [4] (buffer) scanf:The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:38:2: [4] (format) syslog:If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant format string for syslog. test.c:49:3: [4] (buffer) _mbscpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using a function version that stops copying at the end of the buffer. test.c:56:3: [4] (buffer) lstrcat:Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120). test.c:79:3: [3] (shell) CreateProcess:This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:79:3: [3] (shell) CreateProcess:This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:81:10: [3] (misc) LoadLibraryEx:Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20). Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders. test.c:99:20: [3] (buffer) getopt_long:Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20). Check implementation on installation, or limit the size of all string inputs. test.c:16:2: [2] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. test.c:19:2: [2] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. test.c:45:3: [2] (buffer) char:Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:46:3: [2] (buffer) char:Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:50:3: [2] (buffer) memcpy:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:53:3: [2] (buffer) memcpy:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:54:3: [2] (buffer) memcpy:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:55:3: [2] (buffer) CopyMemory:Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:105:7: [2] (misc) fopen:Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). test.c:15:2: [1] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant character. test.c:18:2: [1] (buffer) sprintf:Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source is a constant character. test.c:26:2: [1] (buffer) scanf:It's unclear if the %s limit in the format string is small enough (CWE-120). Check that the limit is sufficiently small, or use a different input function. test.c:57:3: [1] (buffer) strncpy:Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:58:3: [1] (buffer) _tcsncpy:Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:59:3: [1] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. test.c:62:7: [1] (buffer) strlen:Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). test.c:68:3: [1] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. test.c:70:3: [1] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. flawfinder-2.0.19/test/test-saved-hitlist-006.txt000644 000765 000024 00000050750 14112766124 022461 0ustar00dwheelerstaff000000 000000 (lp0 ccopy_reg _reconstructor p1 (c__main__ Hit p2 c__builtin__ object p3 Ntp4 Rp5 (dp6 S'category' p7 S'buffer' p8 sS'filename' p9 S'test.c' p10 sS'end' p11 I692 sS'name' p12 S'gets' p13 sS'parameters' p14 (lp15 S'' p16 aS'f' p17 asS'level' p18 I5 sS'url' p19 g16 sS'ruleid' p20 S'FF1014' p21 sS'column' p22 I2 sS'context_text' p23 S' gets(f);' p24 sS'hook' p25 c__main__ normal p26 sS'warning' p27 S'Does not check for buffer overflows (CWE-120, CWE-20)' p28 sS'suggestion' p29 S'Use fgets() instead' p30 sS'input' p31 I1 sS'line' p32 I32 sS'defaultlevel' p33 I5 sS'start' p34 I688 sbag1 (g2 g3 Ntp35 Rp36 (dp37 g7 g8 sg9 g10 sg11 I1462 sg12 S'strncat' p38 sg14 (lp39 g16 aS'd' p40 aS's' p41 aS'sizeof(d)' p42 asg18 I5 sg19 g16 sg20 S'FF1010' p43 sg22 I3 sg23 S' strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */' p44 sS'note' p45 S'Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.' p46 sg25 c__main__ c_strncat p47 sg27 S'Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120)' p48 sg29 S'Consider strcat_s, strlcat, snprintf, or automatically resizing strings' p49 sg32 I60 sg33 I1 sg34 I1455 sbag1 (g2 g3 Ntp50 Rp51 (dp52 g7 g8 sg9 g10 sg11 I1539 sg12 S'_tcsncat' p53 sg14 (lp54 g16 aS'd' p55 aS's' p56 aS'sizeof(d)' p57 asg18 I5 sg19 g16 sg20 S'FF1011' p58 sg22 I3 sg23 S' _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */' p59 sg45 g46 sg25 g47 sg27 g48 sg29 S'Consider strcat_s, strlcat, or automatically resizing strings' p60 sg32 I61 sg33 I1 sg34 I1531 sbag1 (g2 g3 Ntp61 Rp62 (dp63 g7 g8 sg9 g10 sg11 I1680 sg12 S'MultiByteToWideChar' p64 sg14 (lp65 g16 aS'CP_ACP' p66 aS'0' p67 aS'szName' p68 aS'-1' p69 aS'wszUserName' p70 aS'sizeof(wszUserName)' p71 asg18 I5 sg19 g16 sg20 S'FF1023' p72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));' p73 sg45 S'Risk is high, it appears that the size is given as bytes, but the function requires size as characters.' p74 sg25 c__main__ c_multi_byte_to_wide_char p75 sg27 S'Requires maximum length in CHARACTERS, not bytes (CWE-120)' p76 sg29 g16 sg32 I64 sg33 I2 sg34 I1661 sbag1 (g2 g3 Ntp77 Rp78 (dp79 g7 g8 sg9 g10 sg11 I1815 sg12 S'MultiByteToWideChar' p80 sg14 (lp81 g16 aS'CP_ACP' p82 aS'0' p83 aS'szName' p84 aS'-1' p85 aS'wszUserName' p86 aS'sizeof wszUserName' p87 asg18 I5 sg19 g16 sg20 g72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);' p88 sg45 g74 sg25 g75 sg27 g76 sg29 g16 sg32 I66 sg33 I2 sg34 I1796 sbag1 (g2 g3 Ntp89 Rp90 (dp91 g7 S'misc' p92 sg9 g10 sg11 I2533 sg12 S'SetSecurityDescriptorDacl' p93 sg14 (lp94 g16 aS'&sd' p95 aS'TRUE' p96 aS'NULL' p97 aS'FALSE' p98 asg18 I5 sg19 g16 sg20 S'FF1060' p99 sg22 I3 sg34 I2508 sg23 S' SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);' p100 sg25 c__main__ c_hit_if_null p101 sg27 S'Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732)' p102 sg29 g16 sg32 I77 sg33 I5 sS'check_for_null' p103 I3 sbag90 ag1 (g2 g3 Ntp104 Rp105 (dp106 g7 g8 sg9 g10 sg11 I372 sg12 S'strcpy' p107 sg14 (lp108 g16 aS'b' p109 aS'a' p110 asg18 I4 sg19 g16 sg20 S'FF1001' p111 sg22 I2 sg23 S' strcpy(b, a);' p112 sg25 c__main__ c_buffer p113 sg27 S'Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)' p114 sg29 S'Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)' p115 sg32 I17 sg33 I4 sg34 I366 sbag1 (g2 g3 Ntp116 Rp117 (dp118 g7 g8 sg9 g10 sg11 I429 sg12 S'sprintf' p119 sg14 (lp120 g16 aS's' p121 aS'"hello %s"' p122 aS'bug' p123 asg18 I4 sg19 g16 sg20 S'FF1015' p124 sg22 I2 sg23 S' sprintf(s, "hello %s", bug);' p125 sg25 c__main__ c_sprintf p126 sg27 S'Does not check for buffer overflows (CWE-120)' p127 sg29 S'Use sprintf_s, snprintf, or vsnprintf' p128 sg32 I20 sg33 I4 sg34 I422 sbag1 (g2 g3 Ntp129 Rp130 (dp131 g7 g8 sg9 g10 sg11 I459 sg12 S'sprintf' p132 sg14 (lp133 g16 aS's' p134 aS'gettext("hello %s")' p135 aS'bug' p136 asg18 I4 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, gettext("hello %s"), bug);' p137 sg25 g126 sg27 g127 sg29 g128 sg32 I21 sg33 I4 sg34 I452 sbag1 (g2 g3 Ntp138 Rp139 (dp140 g7 S'format' p141 sg9 g10 sg11 I498 sg12 S'sprintf' p142 sg14 (lp143 g16 aS's' p144 aS'unknown' p145 aS'bug' p146 asg18 I4 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, unknown, bug);' p147 sg25 g126 sg27 S'Potential format string problem (CWE-134)' p148 sg29 S'Make format string constant' p149 sg32 I22 sg33 I4 sg34 I491 sbag1 (g2 g3 Ntp150 Rp151 (dp152 g7 g141 sg9 g10 sg11 I524 sg12 S'printf' p153 sg14 (lp154 g16 aS'bf' p155 aS'x' p156 asg18 I4 sg19 g16 sg20 S'FF1016' p157 sg22 I2 sg23 S' printf(bf, x);' p158 sg25 c__main__ c_printf p159 sg27 S'If format strings can be influenced by an attacker, they can be exploited (CWE-134)' p160 sg29 S'Use a constant for the format specification' p161 sg32 I23 sg33 I4 sg34 I518 sbag1 (g2 g3 Ntp162 Rp163 (dp164 g7 g8 sg9 g10 sg11 I557 sg12 S'scanf' p165 sg14 (lp166 g16 aS'"%s"' p167 aS's' p168 asg18 I4 sg19 g16 sg20 S'FF1020' p169 sg22 I2 sg23 S' scanf("%s", s);' p170 sg25 c__main__ c_scanf p171 sg27 S"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20)" p172 sg29 S'Specify a limit to %s, or use a different input function' p173 sg31 I1 sg32 I25 sg33 I4 sg34 I552 sbag1 (g2 g3 Ntp174 Rp175 (dp176 g7 g8 sg9 g10 sg11 I593 sg12 S'scanf' p177 sg14 (lp178 g16 aS'"%s"' p179 ag168 asg18 I4 sg19 g16 sg20 g169 sg22 I2 sg23 S' scanf("%s", s);' p180 sg25 g171 sg27 g172 sg29 g173 sg31 I1 sg32 I27 sg33 I4 sg34 I588 sbag1 (g2 g3 Ntp181 Rp182 (dp183 g7 g141 sg9 g10 sg11 I997 sg12 S'syslog' p184 sg14 (lp185 g16 aS'LOG_ERR' p186 aS'attacker_string' p187 asg18 I4 sg19 g16 sg20 S'FF1018' p188 sg22 I2 sg23 S' syslog(LOG_ERR, attacker_string);' p189 sg25 g159 sS'format_position' p190 I2 sg27 S"If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134)" p191 sg29 S'Use a constant format string for syslog' p192 sg32 I38 sg33 I4 sg34 I991 sbag1 (g2 g3 Ntp193 Rp194 (dp195 g7 g8 sg9 g10 sg11 I1088 sg12 S'_mbscpy' p196 sg14 (lp197 g16 aS'd' p198 aS's' p199 asg18 I4 sg19 g16 sg20 S'FF1003' p200 sg22 I3 sg23 S" _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */" p201 sg25 g113 sg27 g114 sg29 S'Consider using a function version that stops copying at the end of the buffer' p202 sg32 I49 sg33 I4 sg34 I1081 sbag1 (g2 g3 Ntp203 Rp204 (dp205 g7 g8 sg9 g10 sg11 I1394 sg12 S'lstrcat' p206 sg14 (lp207 g16 aS'd' p208 aS's' p209 asg18 I4 sg19 g16 sg20 S'FF1006' p210 sg22 I3 sg23 S' lstrcat(d,s);' p211 sg25 g113 sg27 S'Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120)' p212 sg29 g16 sg32 I56 sg33 I4 sg34 I1387 sbag1 (g2 g3 Ntp213 Rp214 (dp215 g7 S'shell' p216 sg9 g10 sg11 I2634 sg12 S'CreateProcess' p217 sg14 (lp218 g16 aS'NULL' p219 aS'"C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x"' p220 aS'""' p221 asg18 I3 sg19 g16 sg20 S'FF1046' p222 sg22 I3 sg34 I2621 sg23 S' CreateProcess(NULL, "C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x", "");' p223 sg25 g101 sg27 S'This causes a new process to execute and is difficult to use safely (CWE-78)' p224 sg29 S'Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run' p225 sg32 I79 sg33 I3 sg103 I1 sbag214 ag1 (g2 g3 Ntp226 Rp227 (dp228 g7 g92 sg9 g10 sg11 I2759 sg12 S'LoadLibraryEx' p229 sg14 (lp230 g16 aS'L"user32.dll"' p231 aS'nullptr' p232 aS'LOAD_LIBRARY_AS_DATAFILE' p233 asg18 I3 sg19 g16 sg20 S'FF1059' p234 sg22 I10 sg23 S' (void) LoadLibraryEx(L"user32.dll", nullptr, LOAD_LIBRARY_AS_DATAFILE);' p235 sg25 c__main__ load_library_ex p236 sg27 S'Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20)' p237 sg29 S'Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders' p238 sg31 I1 sg32 I81 sg33 I3 sg34 I2746 sbag1 (g2 g3 Ntp239 Rp240 (dp241 g7 g8 sg9 g10 sg11 I3361 sg12 S'getopt_long' p242 sg14 (lp243 g16 aS'argc' p244 aS'argv' p245 aS'"a"' p246 aS'longopts' p247 aS'NULL' p248 asg18 I3 sg19 S'dangers-c' p249 sg20 S'FF1027' p250 sg22 I20 sg23 S' while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) {' p251 sg25 g26 sg27 S'Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20)' p252 sg29 S'Check implementation on installation, or limit the size of all string inputs' p253 sg31 I1 sg32 I99 sg33 I3 sg34 I3350 sbag1 (g2 g3 Ntp254 Rp255 (dp256 g7 g8 sg9 g10 sg11 I318 sg12 S'strcpy' p257 sg14 (lp258 g16 aS'a' p259 aS'gettext("Hello there")' p260 asg18 I2 sg19 g16 sg20 g111 sg22 I2 sg23 S' strcpy(a, gettext("Hello there")); // Did this work?' p261 sg45 S'Risk is low because the source is a constant string.' p262 sg25 g113 sg27 g114 sg29 g115 sg32 I16 sg33 I4 sg34 I312 sbag1 (g2 g3 Ntp263 Rp264 (dp265 g7 g8 sg9 g10 sg11 I407 sg12 S'sprintf' p266 sg14 (lp267 g16 aS's' p268 aS'"hello"' p269 asg18 I2 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, "hello");' p270 sg45 S'Risk is low because the source has a constant maximum length.' p271 sg25 g126 sg27 g127 sg29 g128 sg32 I19 sg33 I4 sg34 I400 sbag1 (g2 g3 Ntp272 Rp273 (dp274 g7 g8 sg9 g10 sg11 I1047 sg12 S'char' p275 sg14 (lp276 sg18 I2 sg19 g16 sS'lookahead' p277 S"char d[20];\n char s[20];\n int n;\n\n _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */\n memcpy(d,s); // fail - no size\n memcpy(d, s, sizeof(d)); // pass\n memcpy(& n, s, sizeof( n )); // pass\n memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination\n memcpy(d,s,n); // fail - size unguessable\n CopyMemory(d,s);\n lstrcat(d,s);\n strncpy(d,s);\n _tcsncpy(d,s);\n strncat(d,s,10);\n strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */\n _tcsncat(d,s" p278 sg20 S'FF1013' p279 sg22 I3 sg23 S' char d[20];' p280 sg25 c__main__ c_static_array p281 sg27 S'Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)' p282 sg29 S'Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length' p283 sg32 I45 sg33 I2 sg34 I1043 sS'extract_lookahead' p284 I1 sbag1 (g2 g3 Ntp285 Rp286 (dp287 g7 g8 sg9 g10 sg11 I1061 sg12 S'char' p288 sg14 (lp289 sg18 I2 sg19 g16 sg277 S"char s[20];\n int n;\n\n _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */\n memcpy(d,s); // fail - no size\n memcpy(d, s, sizeof(d)); // pass\n memcpy(& n, s, sizeof( n )); // pass\n memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination\n memcpy(d,s,n); // fail - size unguessable\n CopyMemory(d,s);\n lstrcat(d,s);\n strncpy(d,s);\n _tcsncpy(d,s);\n strncat(d,s,10);\n strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */\n _tcsncat(d,s,sizeof(d)); /" p290 sg20 g279 sg22 I3 sg23 S' char s[20];' p291 sg25 g281 sg27 g282 sg29 g283 sg32 I46 sg33 I2 sg34 I1057 sg284 I1 sbag1 (g2 g3 Ntp292 Rp293 (dp294 g7 g8 sg9 g10 sg11 I1161 sg12 S'memcpy' p295 sg14 (lp296 g16 aS'd' p297 aS's' p298 asg18 I2 sg19 g16 sg20 S'FF1004' p299 sg22 I3 sg23 S' memcpy(d,s); // fail - no size' p300 sg25 c__main__ c_memcpy p301 sg27 S'Does not check for buffer overflows when copying to destination (CWE-120)' p302 sg29 S'Make sure destination can always hold the source data' p303 sg32 I50 sg33 I2 sg34 I1155 sbag1 (g2 g3 Ntp304 Rp305 (dp306 g7 g8 sg9 g10 sg11 I1268 sg12 S'memcpy' p307 sg14 (lp308 g16 aS'&n' p309 aS's' p310 aS'sizeof(s)' p311 asg18 I2 sg19 g16 sg20 g299 sg22 I3 sg23 S' memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination' p312 sg25 g301 sg27 g302 sg29 g303 sg32 I53 sg33 I2 sg34 I1262 sbag1 (g2 g3 Ntp313 Rp314 (dp315 g7 g8 sg9 g10 sg11 I1330 sg12 S'memcpy' p316 sg14 (lp317 g16 aS'd' p318 aS's' p319 aS'n' p320 asg18 I2 sg19 g16 sg20 g299 sg22 I3 sg23 S' memcpy(d,s,n); // fail - size unguessable' p321 sg25 g301 sg27 g302 sg29 g303 sg32 I54 sg33 I2 sg34 I1324 sbag1 (g2 g3 Ntp322 Rp323 (dp324 g7 g8 sg9 g10 sg11 I1378 sg12 S'CopyMemory' p325 sg14 (lp326 g16 aS'd' p327 aS's' p328 asg18 I2 sg19 g16 sg20 g299 sg22 I3 sg23 S' CopyMemory(d,s);' p329 sg25 g301 sg27 g302 sg29 g303 sg32 I55 sg33 I2 sg34 I1368 sbag1 (g2 g3 Ntp330 Rp331 (dp332 g7 g92 sg9 g10 sg11 I3455 sg12 S'fopen' p333 sg14 (lp334 g16 aS'"/etc/passwd"' p335 aS'"r"' p336 asg18 I2 sg19 g16 sg20 S'FF1040' p337 sg22 I7 sg23 S' f = fopen("/etc/passwd", "r"); ' p338 sg25 g26 sg27 S'Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)' p339 sg29 g16 sg32 I105 sg33 I2 sg34 I3450 sbag1 (g2 g3 Ntp340 Rp341 (dp342 g7 g8 sg9 g10 sg11 I282 sg12 S'strcpy' p343 sg14 (lp344 g16 aS'a' p345 aS'"\\n"' p346 asg18 I1 sg19 g16 sg20 g111 sg22 I2 sg23 S' strcpy(a, "\\n"); // Did this work?' p347 sg45 S'Risk is low because the source is a constant character.' p348 sg25 g113 sg27 g114 sg29 g115 sg32 I15 sg33 I4 sg34 I276 sbag1 (g2 g3 Ntp349 Rp350 (dp351 g7 g8 sg9 g10 sg11 I388 sg12 S'sprintf' p352 sg14 (lp353 g16 aS's' p354 aS'"\\n"' p355 asg18 I1 sg19 g16 sg20 g124 sg22 I2 sg23 S' sprintf(s, "\\n");' p356 sg45 S'Risk is low because the source is a constant character.' p357 sg25 g126 sg27 g127 sg29 g128 sg32 I18 sg33 I4 sg34 I381 sbag1 (g2 g3 Ntp358 Rp359 (dp360 g7 g8 sg9 g10 sg11 I574 sg12 S'scanf' p361 sg14 (lp362 g16 aS'"%10s"' p363 ag168 asg18 I1 sg19 g16 sg20 g169 sg22 I2 sg23 S' scanf("%10s", s);' p364 sg25 g171 sg27 S"It's unclear if the %s limit in the format string is small enough (CWE-120)" p365 sg29 S'Check that the limit is sufficiently small, or use a different input function' p366 sg31 I1 sg32 I26 sg33 I4 sg34 I569 sbag1 (g2 g3 Ntp367 Rp368 (dp369 g7 g8 sg9 g10 sg11 I1410 sg12 S'strncpy' p370 sg14 (lp371 g16 aS'd' p372 aS's' p373 asg18 I1 sg19 g16 sg20 S'FF1008' p374 sg22 I3 sg23 S' strncpy(d,s);' p375 sg25 g113 sg27 S"Easily used incorrectly; doesn't always \\0-terminate or check for invalid pointers [MS-banned] (CWE-120)" p376 sg29 g16 sg32 I57 sg33 I1 sg34 I1403 sbag1 (g2 g3 Ntp377 Rp378 (dp379 g7 g8 sg9 g10 sg11 I1427 sg12 S'_tcsncpy' p380 sg14 (lp381 g16 aS'd' p382 aS's' p383 asg18 I1 sg19 g16 sg20 S'FF1009' p384 sg22 I3 sg23 S' _tcsncpy(d,s);' p385 sg25 g113 sg27 g376 sg29 g16 sg32 I58 sg33 I1 sg34 I1419 sbag1 (g2 g3 Ntp386 Rp387 (dp388 g7 g8 sg9 g10 sg11 I1443 sg12 S'strncat' p389 sg14 (lp390 g16 aS'd' p391 aS's' p392 aS'10' p393 asg18 I1 sg19 g16 sg20 g43 sg22 I3 sg23 S' strncat(d,s,10);' p394 sg25 g47 sg27 g48 sg29 g49 sg32 I59 sg33 I1 sg34 I1436 sbag1 (g2 g3 Ntp395 Rp396 (dp397 g7 g8 sg9 g10 sg11 I1599 sg12 S'strlen' p398 sg14 (lp399 g16 aS'd' p400 asg18 I1 sg19 g16 sg20 S'FF1022' p401 sg22 I7 sg23 S' n = strlen(d);' p402 sg25 g26 sg27 S'Does not handle strings that are not \\0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126)' p403 sg29 g16 sg32 I62 sg33 I1 sg34 I1593 sbag1 (g2 g3 Ntp404 Rp405 (dp406 g7 g8 sg9 g10 sg11 I1918 sg12 S'MultiByteToWideChar' p407 sg14 (lp408 g16 aS'CP_ACP' p409 aS'0' p410 aS'szName' p411 aS'-1' p412 aS'wszUserName' p413 aS'sizeof(wszUserName)/sizeof(wszUserName[0])' p414 asg18 I1 sg19 g16 sg20 g72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));' p415 sg45 S'Risk is very low, the length appears to be in characters not bytes.' p416 sg25 g75 sg27 g76 sg29 g16 sg32 I68 sg33 I2 sg34 I1899 sbag1 (g2 g3 Ntp417 Rp418 (dp419 g7 g8 sg9 g10 sg11 I2045 sg12 S'MultiByteToWideChar' p420 sg14 (lp421 g16 aS'CP_ACP' p422 aS'0' p423 aS'szName' p424 aS'-1' p425 aS'wszUserName' p426 aS'sizeof wszUserName /sizeof(wszUserName[0])' p427 asg18 I1 sg19 g16 sg20 g72 sg22 I3 sg23 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));' p428 sg45 g416 sg25 g75 sg27 g76 sg29 g16 sg32 I70 sg33 I2 sg34 I2026 sbag1 (g2 g3 Ntp429 Rp430 (dp431 g7 g141 sg9 g10 sg11 I200 sg12 S'printf' p432 sg14 (lp433 g16 aS'"hello\\n"' p434 asg18 I0 sg19 g16 sg20 g157 sg22 I2 sg23 S' printf("hello\\n");' p435 sg45 S'Constant format string, so not considered risky.' p436 sg25 g159 sg27 g160 sg29 g161 sg32 I9 sg33 I4 sg34 I194 sbag1 (g2 g3 Ntp437 Rp438 (dp439 g7 g8 sg9 g10 sg11 I539 sg12 S'scanf' p440 sg14 (lp441 g16 aS'"%d"' p442 aS'&x' p443 asg18 I0 sg19 g16 sg20 g169 sg22 I2 sg23 S' scanf("%d", &x);' p444 sg45 S'No risky scanf format detected.' p445 sg25 g171 sg27 g172 sg29 g173 sg31 I1 sg32 I24 sg33 I4 sg34 I534 sbag1 (g2 g3 Ntp446 Rp447 (dp448 g7 g141 sg9 g10 sg11 I643 sg12 S'printf' p449 sg14 (lp450 g16 aS'"\\\\"' p451 asg18 I0 sg19 g16 sg20 g157 sg22 I2 sg23 S' printf("\\\\");' p452 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I29 sg33 I4 sg34 I637 sbag1 (g2 g3 Ntp453 Rp454 (dp455 g7 g141 sg9 g10 sg11 I837 sg12 S'syslog' p456 sg14 (lp457 g16 aS'LOG_ERR' p458 aS'"cannot open config file (%s): %s"' p459 aS'filename' p460 aS'strerror(errno)' p461 asg18 I0 sg19 g16 sg20 g188 sg22 I2 sg23 S' syslog(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno))' p462 sg45 g436 sg25 g159 sg190 I2 sg27 g191 sg29 g192 sg32 I35 sg33 I4 sg34 I831 sbag1 (g2 g3 Ntp463 Rp464 (dp465 g7 g141 sg9 g10 sg11 I914 sg12 S'syslog' p466 sg14 (lp467 g16 aS'LOG_CRIT' p468 aS'"malloc() failed"' p469 asg18 I0 sg19 g16 sg20 g188 sg22 I2 sg23 S' syslog(LOG_CRIT,"malloc() failed");' p470 sg45 g436 sg25 g159 sg190 I2 sg27 g191 sg29 g192 sg32 I36 sg33 I4 sg34 I908 sbag1 (g2 g3 Ntp471 Rp472 (dp473 g7 g141 sg9 g10 sg11 I3049 sg12 S'printf' p474 sg14 (lp475 g16 aS'"%c\\n"' p476 aS"'x'" p477 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'x\');' p478 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I85 sg33 I4 sg34 I3043 sbag1 (g2 g3 Ntp479 Rp480 (dp481 g7 g141 sg9 g10 sg11 I3072 sg12 S'printf' p482 sg14 (lp483 g16 aS'"%c\\n"' p484 aS'\'"\'' p485 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'"\');' p486 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I86 sg33 I4 sg34 I3066 sbag1 (g2 g3 Ntp487 Rp488 (dp489 g7 g141 sg9 g10 sg11 I3095 sg12 S'printf' p490 sg14 (lp491 g16 aS'"%c\\n"' p492 aS'\'\\"\'' p493 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\"\');' p494 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I87 sg33 I4 sg34 I3089 sbag1 (g2 g3 Ntp495 Rp496 (dp497 g7 g141 sg9 g10 sg11 I3119 sg12 S'printf' p498 sg14 (lp499 g16 aS'"%c\\n"' p500 aS"'\\''" p501 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\\'\');' p502 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I88 sg33 I4 sg34 I3113 sbag1 (g2 g3 Ntp503 Rp504 (dp505 g7 g141 sg9 g10 sg11 I3143 sg12 S'printf' p506 sg14 (lp507 g16 aS'"%c\\n"' p508 aS"'\\177'" p509 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\177\');' p510 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I89 sg33 I4 sg34 I3137 sbag1 (g2 g3 Ntp511 Rp512 (dp513 g7 g141 sg9 g10 sg11 I3169 sg12 S'printf' p514 sg14 (lp515 g16 aS'"%c\\n"' p516 aS"'\\xfe'" p517 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\xfe\');' p518 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I90 sg33 I4 sg34 I3163 sbag1 (g2 g3 Ntp519 Rp520 (dp521 g7 g141 sg9 g10 sg11 I3195 sg12 S'printf' p522 sg14 (lp523 g16 aS'"%c\\n"' p524 aS"'\\xd'" p525 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\xd\');' p526 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I91 sg33 I4 sg34 I3189 sbag1 (g2 g3 Ntp527 Rp528 (dp529 g7 g141 sg9 g10 sg11 I3220 sg12 S'printf' p530 sg14 (lp531 g16 aS'"%c\\n"' p532 aS"'\\n'" p533 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\n\');' p534 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I92 sg33 I4 sg34 I3214 sbag1 (g2 g3 Ntp535 Rp536 (dp537 g7 g141 sg9 g10 sg11 I3244 sg12 S'printf' p538 sg14 (lp539 g16 aS'"%c\\n"' p540 aS"'\\\\'" p541 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", \'\\\\\');' p542 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I93 sg33 I4 sg34 I3238 sbag1 (g2 g3 Ntp543 Rp544 (dp545 g7 g141 sg9 g10 sg11 I3268 sg12 S'printf' p546 sg14 (lp547 g16 aS'"%c\\n"' p548 aS'"\'"' p549 asg18 I0 sg19 g16 sg20 g157 sg22 I3 sg23 S' printf("%c\\n", "\'");' p550 sg45 g436 sg25 g159 sg27 g160 sg29 g161 sg32 I94 sg33 I4 sg34 I3262 sbag1 (g2 g3 Ntp551 Rp552 (dp553 g7 g141 sg9 g10 sg11 I3593 sg12 S'fprintf' p554 sg14 (lp555 g16 aS'stderr' p556 aS'"Assertion failed.\\n"\\\n "File: %s\\nLine: %d\\n"\\\n "Assertion: %s\\n\\n"' p557 aS'__FILE__' p558 aS'__LINE__' p559 aS'#x' p560 asg18 I0 sg19 g16 sg20 S'FF1017' p561 sg22 I2 sg23 S' fprintf(stderr,"Assertion failed.\\n"\\' p562 sg45 g436 sg25 g159 sg190 I2 sg27 g160 sg29 g161 sg32 I113 sg33 I4 sg34 I3586 sba.flawfinder-2.0.19/test/test-cpp-digit-separator.cpp000644 000765 000024 00000000034 13774402723 023212 0ustar00dwheelerstaff000000 000000 int main() { return 0'000; }flawfinder-2.0.19/test/test-diff-005.patch000644 000765 000024 00000000401 13774402305 021055 0ustar00dwheelerstaff000000 000000 --- test.c 2017-08-26 15:33:59.480235200 -0400 +++ test-patched.c 2017-08-23 22:20:22.458331500 -0400 @@ -9,6 +9,10 @@ printf("hello\n"); } +int bad(char *a, char *b) { + strcpy(b, a); +} + /* This is a strcpy test. */ int demo(char *a, char *b) { flawfinder-2.0.19/test/test-results-005.txt000644 000765 000024 00000000324 14112766124 021371 0ustar00dwheelerstaff000000 000000 test-patched.c:13:2: [4] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). flawfinder-2.0.19/test/test.c000644 000765 000024 00000007452 13777165075 017022 0ustar00dwheelerstaff000000 000000 /* Test flawfinder. This program won't compile or run; that's not necessary for this to be a useful test. */ #include #define hello(x) goodbye(x) #define WOKKA "stuff" main() { printf("hello\n"); } /* This is a strcpy test. */ int demo(char *a, char *b) { strcpy(a, "\n"); // Did this work? strcpy(a, gettext("Hello there")); // Did this work? strcpy(b, a); sprintf(s, "\n"); sprintf(s, "hello"); sprintf(s, "hello %s", bug); sprintf(s, gettext("hello %s"), bug); sprintf(s, unknown, bug); printf(bf, x); scanf("%d", &x); scanf("%s", s); scanf("%10s", s); scanf("%s", s); gets(f); // Flawfinder: ignore printf("\\"); /* Flawfinder: ignore */ gets(f); gets(f); /* These are okay, but flawfinder version < 0.20 incorrectly used the first parameter as the parameter for the format string */ syslog(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno)) syslog(LOG_CRIT,"malloc() failed"); /* But this one SHOULD trigger a warning. */ syslog(LOG_ERR, attacker_string); } demo2() { char d[20]; char s[20]; int n; _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */ memcpy(d,s); // fail - no size memcpy(d, s, sizeof(d)); // pass memcpy(& n, s, sizeof( n )); // pass memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination memcpy(d,s,n); // fail - size unguessable CopyMemory(d,s); lstrcat(d,s); strncpy(d,s); _tcsncpy(d,s); strncat(d,s,10); strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */ _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */ n = strlen(d); /* This is wrong, and should be flagged as risky: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)); /* This is also wrong, and should be flagged as risky: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName); /* This is much better: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0])); /* This is much better: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0])); /* This is an example of bad code - the third paramer is NULL, so it creates a NULL ACL. Note that Flawfinder can't detect when a SECURITY_DESCRIPTOR structure is manually created with a NULL value as the ACL; doing so would require a tool that handles C/C++ and knows about types more that flawfinder currently does. Anyway, this needs to be detected: */ SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE); /* This one is a bad idea - first param shouldn't be NULL */ CreateProcess(NULL, "C:\\Program Files\\GoodGuy\\GoodGuy.exe -x", ""); /* Bad, may load from current directory */ (void) LoadLibraryEx(L"user32.dll", nullptr, LOAD_LIBRARY_AS_DATAFILE); /* This should be ignored, since it's loading only from System32 */ (void) LoadLibraryEx(L"user32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET); /* Test interaction of quote characters */ printf("%c\n", 'x'); printf("%c\n", '"'); printf("%c\n", '\"'); printf("%c\n", '\''); printf("%c\n", '\177'); printf("%c\n", '\xfe'); printf("%c\n", '\xd'); printf("%c\n", '\n'); printf("%c\n", '\\'); printf("%c\n", "'"); } int getopt_example(int argc,char *argv[]) { while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) { } } int testfile() { FILE *f; f = fopen("/etc/passwd", "r"); fclose(f); } /* Regression test: handle \\\n after end of string */ #define assert(x) {\ if (!(x)) {\ fprintf(stderr,"Assertion failed.\n"\ "File: %s\nLine: %d\n"\ "Assertion: %s\n\n"\ ,__FILE__,__LINE__,#x);\ exit(1);\ };\ } int accesstest() { int access = 0; /* Not a function call. Should be caught by the false positive test, and NOT labelled as a problem. */ } flawfinder-2.0.19/test/test-results-004.txt000644 000765 000024 00000003031 14112766123 021365 0ustar00dwheelerstaff000000 000000 test.c:32:2: [5] (buffer) gets:Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60:3: [5] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61:3: [5] (buffer) _tcsncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). flawfinder-2.0.19/test/correct-results.html000644 000765 000024 00000036275 14112766110 021707 0ustar00dwheelerstaff000000 000000 Flawfinder Results

        Flawfinder Results

        Here are the security scan results from Flawfinder version 2.0.19, (C) 2001-2019 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 222

        Examining test.c
        Examining test2.c

        Final Results

        • test.c:32: [5] (buffer) gets: Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead.
           gets(f);
          
        • test.c:60: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.
            strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */
          
        • test.c:61: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.
            _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */
          
        • test.c:64: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));
          
        • test.c:66: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);
          
        • test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).
            SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);
          
        • test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).
            SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);
          
        • test.c:17: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).
           strcpy(b, a);
          
        • test.c:20: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf.
           sprintf(s, "hello %s", bug);
          
        • test.c:21: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf.
           sprintf(s, gettext("hello %s"), bug);
          
        • test.c:22: [4] (format) sprintf: Potential format string problem (CWE-134). Make format string constant.
           sprintf(s, unknown, bug);
          
        • test.c:23: [4] (format) printf: If format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant for the format specification.
           printf(bf, x);
          
        • test.c:25: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function.
           scanf("%s", s);
          
        • test.c:27: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function.
           scanf("%s", s);
          
        • test.c:38: [4] (format) syslog: If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant format string for syslog.
           syslog(LOG_ERR, attacker_string);
          
        • test.c:49: [4] (buffer) _mbscpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using a function version that stops copying at the end of the buffer.
            _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */
          
        • test.c:56: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120).
            lstrcat(d,s);
          
        • test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.
            CreateProcess(NULL, "C:\\Program Files\\GoodGuy\\GoodGuy.exe -x", "");
          
        • test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.
            CreateProcess(NULL, "C:\\Program Files\\GoodGuy\\GoodGuy.exe -x", "");
          
        • test.c:81: [3] (misc) LoadLibraryEx: Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20). Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders.
            (void) LoadLibraryEx(L"user32.dll", nullptr, LOAD_LIBRARY_AS_DATAFILE);
          
        • test.c:99: [3] (buffer) getopt_long: Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20). Check implementation on installation, or limit the size of all string inputs.
              while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) {
          
        • test.c:16: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string.
           strcpy(a, gettext("Hello there")); // Did this work?
          
        • test.c:19: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length.
           sprintf(s, "hello");
          
        • test.c:45: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.
            char d[20];
          
        • test.c:46: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.
            char s[20];
          
        • test.c:50: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            memcpy(d,s); // fail - no size
          
        • test.c:53: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination
          
        • test.c:54: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            memcpy(d,s,n); // fail - size unguessable
          
        • test.c:55: [2] (buffer) CopyMemory: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            CopyMemory(d,s);
          
        • test.c:105: [2] (misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362).
            f = fopen("/etc/passwd", "r"); 
          
        • test.c:15: [1] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant character.
           strcpy(a, "\n"); // Did this work?
          
        • test.c:18: [1] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source is a constant character.
           sprintf(s, "\n");
          
        • test.c:26: [1] (buffer) scanf: It's unclear if the %s limit in the format string is small enough (CWE-120). Check that the limit is sufficiently small, or use a different input function.
           scanf("%10s", s);
          
        • test.c:57: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).
            strncpy(d,s);
          
        • test.c:58: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).
            _tcsncpy(d,s);
          
        • test.c:59: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings.
            strncat(d,s,10);
          
        • test.c:62: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126).
            n = strlen(d);
          
        • test.c:68: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));
          
        • test.c:70: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));
          

        Analysis Summary

        Hits = 39
        Lines analyzed = 126
        Physical Source Lines of Code (SLOC) = 86
        Hits@level = [0] 16 [1] 9 [2] 9 [3] 4 [4] 10 [5] 7
        Hits@level+ = [0+] 55 [1+] 39 [2+] 30 [3+] 21 [4+] 17 [5+] 7
        Hits/KSLOC@level+ = [0+] 639.535 [1+] 453.488 [2+] 348.837 [3+] 244.186 [4+] 197.674 [5+] 81.3953
        Suppressed hits = 2 (use --neverignore to show them)
        Minimum risk level = 1
        Not every hit is necessarily a security vulnerability. You can inhibit a report by adding a comment in this form: // flawfinder: ignore Make *sure* it's a false positive! You can use the option --neverignore to show these.
        There may be other security vulnerabilities; review your code!
        See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. flawfinder-2.0.19/test/test-results.html000644 000765 000024 00000036275 14112766123 021231 0ustar00dwheelerstaff000000 000000 Flawfinder Results

        Flawfinder Results

        Here are the security scan results from Flawfinder version 2.0.19, (C) 2001-2019 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 222

        Examining test.c
        Examining test2.c

        Final Results

        • test.c:32: [5] (buffer) gets: Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead.
           gets(f);
          
        • test.c:60: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.
            strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */
          
        • test.c:61: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.
            _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */
          
        • test.c:64: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));
          
        • test.c:66: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);
          
        • test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).
            SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);
          
        • test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).
            SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);
          
        • test.c:17: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).
           strcpy(b, a);
          
        • test.c:20: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf.
           sprintf(s, "hello %s", bug);
          
        • test.c:21: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf.
           sprintf(s, gettext("hello %s"), bug);
          
        • test.c:22: [4] (format) sprintf: Potential format string problem (CWE-134). Make format string constant.
           sprintf(s, unknown, bug);
          
        • test.c:23: [4] (format) printf: If format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant for the format specification.
           printf(bf, x);
          
        • test.c:25: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function.
           scanf("%s", s);
          
        • test.c:27: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function.
           scanf("%s", s);
          
        • test.c:38: [4] (format) syslog: If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant format string for syslog.
           syslog(LOG_ERR, attacker_string);
          
        • test.c:49: [4] (buffer) _mbscpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using a function version that stops copying at the end of the buffer.
            _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */
          
        • test.c:56: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120).
            lstrcat(d,s);
          
        • test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.
            CreateProcess(NULL, "C:\\Program Files\\GoodGuy\\GoodGuy.exe -x", "");
          
        • test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.
            CreateProcess(NULL, "C:\\Program Files\\GoodGuy\\GoodGuy.exe -x", "");
          
        • test.c:81: [3] (misc) LoadLibraryEx: Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20). Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders.
            (void) LoadLibraryEx(L"user32.dll", nullptr, LOAD_LIBRARY_AS_DATAFILE);
          
        • test.c:99: [3] (buffer) getopt_long: Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20). Check implementation on installation, or limit the size of all string inputs.
              while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) {
          
        • test.c:16: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string.
           strcpy(a, gettext("Hello there")); // Did this work?
          
        • test.c:19: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length.
           sprintf(s, "hello");
          
        • test.c:45: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.
            char d[20];
          
        • test.c:46: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.
            char s[20];
          
        • test.c:50: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            memcpy(d,s); // fail - no size
          
        • test.c:53: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination
          
        • test.c:54: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            memcpy(d,s,n); // fail - size unguessable
          
        • test.c:55: [2] (buffer) CopyMemory: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.
            CopyMemory(d,s);
          
        • test.c:105: [2] (misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362).
            f = fopen("/etc/passwd", "r"); 
          
        • test.c:15: [1] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant character.
           strcpy(a, "\n"); // Did this work?
          
        • test.c:18: [1] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source is a constant character.
           sprintf(s, "\n");
          
        • test.c:26: [1] (buffer) scanf: It's unclear if the %s limit in the format string is small enough (CWE-120). Check that the limit is sufficiently small, or use a different input function.
           scanf("%10s", s);
          
        • test.c:57: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).
            strncpy(d,s);
          
        • test.c:58: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).
            _tcsncpy(d,s);
          
        • test.c:59: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings.
            strncat(d,s,10);
          
        • test.c:62: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126).
            n = strlen(d);
          
        • test.c:68: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));
          
        • test.c:70: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes.
            MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));
          

        Analysis Summary

        Hits = 39
        Lines analyzed = 126
        Physical Source Lines of Code (SLOC) = 86
        Hits@level = [0] 16 [1] 9 [2] 9 [3] 4 [4] 10 [5] 7
        Hits@level+ = [0+] 55 [1+] 39 [2+] 30 [3+] 21 [4+] 17 [5+] 7
        Hits/KSLOC@level+ = [0+] 639.535 [1+] 453.488 [2+] 348.837 [3+] 244.186 [4+] 197.674 [5+] 81.3953
        Suppressed hits = 2 (use --neverignore to show them)
        Minimum risk level = 1
        Not every hit is necessarily a security vulnerability. You can inhibit a report by adding a comment in this form: // flawfinder: ignore Make *sure* it's a false positive! You can use the option --neverignore to show these.
        There may be other security vulnerabilities; review your code!
        See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. flawfinder-2.0.19/test/test-results.txt000644 000765 000024 00000021370 14112766123 021072 0ustar00dwheelerstaff000000 000000 Flawfinder version 2.0.19, (C) 2001-2019 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 222 Examining test.c Examining test2.c FINAL RESULTS: test.c:32: [5] (buffer) gets: Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66: [5] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77: [5] (misc) SetSecurityDescriptorDacl: Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:17: [4] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). test.c:20: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:21: [4] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. test.c:22: [4] (format) sprintf: Potential format string problem (CWE-134). Make format string constant. test.c:23: [4] (format) printf: If format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant for the format specification. test.c:25: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:27: [4] (buffer) scanf: The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20). Specify a limit to %s, or use a different input function. test.c:38: [4] (format) syslog: If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134). Use a constant format string for syslog. test.c:49: [4] (buffer) _mbscpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using a function version that stops copying at the end of the buffer. test.c:56: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120). test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:79: [3] (shell) CreateProcess: This causes a new process to execute and is difficult to use safely (CWE-78). Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run. test.c:81: [3] (misc) LoadLibraryEx: Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20). Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders. test.c:99: [3] (buffer) getopt_long: Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20). Check implementation on installation, or limit the size of all string inputs. test.c:16: [2] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant string. test.c:19: [2] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source has a constant maximum length. test.c:45: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:46: [2] (buffer) char: Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. test.c:50: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:53: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:54: [2] (buffer) memcpy: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:55: [2] (buffer) CopyMemory: Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data. test.c:105: [2] (misc) fopen: Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362). test.c:15: [1] (buffer) strcpy: Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused). Risk is low because the source is a constant character. test.c:18: [1] (buffer) sprintf: Does not check for buffer overflows (CWE-120). Use sprintf_s, snprintf, or vsnprintf. Risk is low because the source is a constant character. test.c:26: [1] (buffer) scanf: It's unclear if the %s limit in the format string is small enough (CWE-120). Check that the limit is sufficiently small, or use a different input function. test.c:57: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:58: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). test.c:59: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. test.c:62: [1] (buffer) strlen: Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126). test.c:68: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. test.c:70: [1] (buffer) MultiByteToWideChar: Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is very low, the length appears to be in characters not bytes. ANALYSIS SUMMARY: Hits = 39 Lines analyzed = 126 Physical Source Lines of Code (SLOC) = 86 Hits@level = [0] 16 [1] 9 [2] 9 [3] 4 [4] 10 [5] 7 Hits@level+ = [0+] 55 [1+] 39 [2+] 30 [3+] 21 [4+] 17 [5+] 7 Hits/KSLOC@level+ = [0+] 639.535 [1+] 453.488 [2+] 348.837 [3+] 244.186 [4+] 197.674 [5+] 81.3953 Suppressed hits = 2 (use --neverignore to show them) Minimum risk level = 1 Not every hit is necessarily a security vulnerability. You can inhibit a report by adding a comment in this form: // flawfinder: ignore Make *sure* it's a false positive! You can use the option --neverignore to show these. There may be other security vulnerabilities; review your code! See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. Testing for no ending newline: Lines analyzed = 32 flawfinder-2.0.19/test/test-results-006.txt000644 000765 000024 00000003031 14112766124 021370 0ustar00dwheelerstaff000000 000000 test.c:32:2: [5] (buffer) gets:Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60:3: [5] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61:3: [5] (buffer) _tcsncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). flawfinder-2.0.19/test/._correct-results.csv000644 000765 000024 00000000351 14112766110 021735 0ustar00dwheelerstaff000000 000000 Mac OS X  2·éATTRéÀ)Àcom.apple.lastuseddate#PSÐcom.apple.quarantine¥cE`›â´:q/0082;604563a6;Numbers;flawfinder-2.0.19/test/PaxHeader/correct-results.csv000644 000765 000024 00000000033 14112766110 023466 xustar00dwheelerstaff000000 000000 27 mtime=1630268488.121843 flawfinder-2.0.19/test/correct-results.csv000644 000765 000024 00000035150 14112766110 021525 0ustar00dwheelerstaff000000 000000 File,Line,Column,DefaultLevel,Level,Category,Name,Warning,Suggestion,Note,CWEs,Context,Fingerprint,ToolVersion,RuleId,HelpUri test.c,32,2,5,5,buffer,gets,"Does not check for buffer overflows (CWE-120, CWE-20).",Use fgets() instead.,,"CWE-120, CWE-20", gets(f);,6a5bb383fb44030b0d9428b17359e94ba3979bc1ce702be450427f85592c649a,2.0.19,FF1014,https://cwe.mitre.org/data/definitions/120.html test.c,60,3,1,5,buffer,strncat,"Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120).","Consider strcat_s, strlcat, snprintf, or automatically resizing strings.","Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.",CWE-120," strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */",cbd19c308547e79af13436d8f7dbcf6c62e49e4f62ba9aee38fbef29e0772f74,2.0.19,FF1010,https://cwe.mitre.org/data/definitions/120.html test.c,61,3,1,5,buffer,_tcsncat,"Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120).","Consider strcat_s, strlcat, or automatically resizing strings.","Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.",CWE-120," _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */",c3f6ba2c710efc878e66df4578894fd408452cb7cdec7ae6f492a3b1796f8c42,2.0.19,FF1011,https://cwe.mitre.org/data/definitions/120.html test.c,64,3,2,5,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is high, it appears that the size is given as bytes, but the function requires size as characters.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));",4f5b73ff337a54d6e1d9a369659ca0ddb4f80e6b7e38a17e5b112f6d3e266e69,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html test.c,66,3,2,5,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is high, it appears that the size is given as bytes, but the function requires size as characters.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);",9ecdc1e903acc16a646bf7909a630ae22a7593b70952c39ce6bd9c5a23fad0fd,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html test.c,77,3,5,5,misc,SetSecurityDescriptorDacl,"Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb,2.0.19,FF1060,https://cwe.mitre.org/data/definitions/732.html test.c,77,3,5,5,misc,SetSecurityDescriptorDacl,"Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732).",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb,2.0.19,FF1060,https://cwe.mitre.org/data/definitions/732.html test.c,17,2,4,4,buffer,strcpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,"Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).",,CWE-120," strcpy(b, a);",c01c8472bb53022e912da4da2faebc67d537855da324020c44bfd5e608a79b77,2.0.19,FF1001,https://cwe.mitre.org/data/definitions/120.html test.c,20,2,4,4,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",,CWE-120," sprintf(s, ""hello %s"", bug);",814237858ab012010f3355a49480dd6fa0a2cb8cf8356a98ac1c17c9febf6521,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,21,2,4,4,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",,CWE-120," sprintf(s, gettext(""hello %s""), bug);",b793f18f143fb2297c49e0639384ad73db86eb01a44377aa4d5d09b44b03d747,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,22,2,4,4,format,sprintf,Potential format string problem (CWE-134).,Make format string constant.,,CWE-134," sprintf(s, unknown, bug);",16ebc2ff96ee4bab2695783709e97b597ca9c8b8cc149e33aed859f0fafd3431,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/134.html test.c,23,2,4,4,format,printf,"If format strings can be influenced by an attacker, they can be exploited (CWE-134).",Use a constant for the format specification.,,CWE-134," printf(bf, x);",46f42896019245d2dffc4caf4fe018b073ce2a58203676eaa28b6374558a5b5d,2.0.19,FF1016,https://cwe.mitre.org/data/definitions/134.html test.c,25,2,4,4,buffer,scanf,"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).","Specify a limit to %s, or use a different input function.",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f,2.0.19,FF1020,https://cwe.mitre.org/data/definitions/120.html test.c,27,2,4,4,buffer,scanf,"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20).","Specify a limit to %s, or use a different input function.",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f,2.0.19,FF1020,https://cwe.mitre.org/data/definitions/120.html test.c,38,2,4,4,format,syslog,"If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134).",Use a constant format string for syslog.,,CWE-134," syslog(LOG_ERR, attacker_string);",22e98963d5af7b197a090bd522d2d39b8d8ee7bdf08453fd2008939c92cd9677,2.0.19,FF1018,https://cwe.mitre.org/data/definitions/134.html test.c,49,3,4,4,buffer,_mbscpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,Consider using a function version that stops copying at the end of the buffer.,,CWE-120," _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */",e00a4a1a0a3603db98a23fcff3c9cdfd9012f5a81826814d9508e0f22089b993,2.0.19,FF1003,https://cwe.mitre.org/data/definitions/120.html test.c,56,3,4,4,buffer,lstrcat,Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120).,,,CWE-120," lstrcat(d,s);",364b4c512862fdccbca27d2fa7737995b5d24b637a760976c940ae636218d340,2.0.19,FF1006,https://cwe.mitre.org/data/definitions/120.html test.c,79,3,3,3,shell,CreateProcess,This causes a new process to execute and is difficult to use safely (CWE-78).,"Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf,2.0.19,FF1046,https://cwe.mitre.org/data/definitions/78.html test.c,79,3,3,3,shell,CreateProcess,This causes a new process to execute and is difficult to use safely (CWE-78).,"Specify the application path in the first argument, NOT as part of the second, or embedded spaces could allow an attacker to force a different program to run.",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf,2.0.19,FF1046,https://cwe.mitre.org/data/definitions/78.html test.c,81,10,3,3,misc,LoadLibraryEx,"Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20).",Use a flag like LOAD_LIBRARY_SEARCH_SYSTEM32 or LOAD_LIBRARY_SEARCH_APPLICATION_DIR to search only desired folders.,,"CWE-829, CWE-20"," (void) LoadLibraryEx(L""user32.dll"", nullptr, LOAD_LIBRARY_AS_DATAFILE);",b1f99ecaa31e682487d795afbf03282fd56ad9f2aa630d0196219b277d2a68c9,2.0.19,FF1059,https://cwe.mitre.org/data/definitions/829.html test.c,99,20,3,3,buffer,getopt_long,"Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20).","Check implementation on installation, or limit the size of all string inputs.",,"CWE-120, CWE-20"," while ((optc = getopt_long (argc, argv, ""a"",longopts, NULL )) != EOF) {",5bedf6e5bccf596008ef191ec4c5d4cc51a32cff0c05ef62d5f10fab93d0cc24,2.0.19,FF1027,https://cwe.mitre.org/data/definitions/120.html test.c,16,2,4,2,buffer,strcpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,"Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).",Risk is low because the source is a constant string.,CWE-120," strcpy(a, gettext(""Hello there"")); // Did this work?",d64070fb93ff0bb797fb926f4dddc7212d42f77e288d5ceb0cd30ed2979fa28d,2.0.19,FF1001,https://cwe.mitre.org/data/definitions/120.html test.c,19,2,4,2,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",Risk is low because the source has a constant maximum length.,CWE-120," sprintf(s, ""hello"");",907b46be1c3ea7b38f90a4d1b0f43b7751cd8cbe38fae840930ff006b702157d,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,45,3,2,2,buffer,char,"Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120).","Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.",,CWE-119!/CWE-120, char d[20];,36c87517700337a59cc3ad3218cfdde56cad37d69cdeccee5a55ab232d5c7946,2.0.19,FF1013,https://cwe.mitre.org/data/definitions/119.html test.c,46,3,2,2,buffer,char,"Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120).","Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length.",,CWE-119!/CWE-120, char s[20];,213de8e8815fc84c423b55fd845fea541f25744718e486234364bb457863b597,2.0.19,FF1013,https://cwe.mitre.org/data/definitions/119.html test.c,50,3,2,2,buffer,memcpy,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," memcpy(d,s); // fail - no size",e667b352fb0748c67b607b11577b11bad87545779c39923e61839dd04056055f,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,53,3,2,2,buffer,memcpy,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination",01bcc2c8ba2d928ac3315b4dcc6593042ea05e62888a10a6d2cf16797a65ed32,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,54,3,2,2,buffer,memcpy,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," memcpy(d,s,n); // fail - size unguessable",2517a2fb5981193a6017cca660d16e85aab133706cbec302df97aaa623fc77ef,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,55,3,2,2,buffer,CopyMemory,Does not check for buffer overflows when copying to destination (CWE-120).,Make sure destination can always hold the source data.,,CWE-120," CopyMemory(d,s);",977f8c805ddd76ff32e0f7aea08701ba97d9ce6955136e98b308ed4f70eb2e11,2.0.19,FF1004,https://cwe.mitre.org/data/definitions/120.html test.c,105,7,2,2,misc,fopen,"Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362).",,,CWE-362," f = fopen(""/etc/passwd"", ""r""); ",2ec6928c77a8b54caa61d0459f367c4394ee1f5e6f488753f587bfa9c780bad8,2.0.19,FF1040,https://cwe.mitre.org/data/definitions/362.html test.c,15,2,4,1,buffer,strcpy,Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120).,"Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).",Risk is low because the source is a constant character.,CWE-120," strcpy(a, ""\n""); // Did this work?",0badc5f4c500d17b42794feaca54ee0f49e607a32510af3ed749579001017edb,2.0.19,FF1001,https://cwe.mitre.org/data/definitions/120.html test.c,18,2,4,1,buffer,sprintf,Does not check for buffer overflows (CWE-120).,"Use sprintf_s, snprintf, or vsnprintf.",Risk is low because the source is a constant character.,CWE-120," sprintf(s, ""\n"");",c65fbd60851f3c8ace22332805966606488c0d242c1823493c582e267609b1a7,2.0.19,FF1015,https://cwe.mitre.org/data/definitions/120.html test.c,26,2,4,1,buffer,scanf,It's unclear if the %s limit in the format string is small enough (CWE-120).,"Check that the limit is sufficiently small, or use a different input function.",,CWE-120," scanf(""%10s"", s);",e24c4c801f10acfa93098b2bef58524efe4f88237f2dd8b58be9afa838616afe,2.0.19,FF1020,https://cwe.mitre.org/data/definitions/120.html test.c,57,3,1,1,buffer,strncpy,Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).,,,CWE-120," strncpy(d,s);",8fa14bf72393a00f667ffcc06b7b7e5f0b6d2f16d8d67444db06b0deb35b5f5e,2.0.19,FF1008,https://cwe.mitre.org/data/definitions/120.html test.c,58,3,1,1,buffer,_tcsncpy,Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120).,,,CWE-120," _tcsncpy(d,s);",691fabd4ca960a00e4c538eee0187ee0fdf59bd43dd71e792c14175150369b8b,2.0.19,FF1009,https://cwe.mitre.org/data/definitions/120.html test.c,59,3,1,1,buffer,strncat,"Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120).","Consider strcat_s, strlcat, snprintf, or automatically resizing strings.",,CWE-120," strncat(d,s,10);",dd92f996a554bfbc038bea27640ba25dcf298383140a8330dca7cdacf493a701,2.0.19,FF1010,https://cwe.mitre.org/data/definitions/120.html test.c,62,7,1,1,buffer,strlen,Does not handle strings that are not \0-terminated; if given one it may perform an over-read (it could cause a crash if unprotected) (CWE-126).,,,CWE-126, n = strlen(d);,db7201c7df7f543ea76febb060bda167e414e71e3d18095fe1def69f8c47a4f6,2.0.19,FF1022,https://cwe.mitre.org/data/definitions/126.html test.c,68,3,2,1,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is very low, the length appears to be in characters not bytes.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));",1813fc329227b38abae867d8023a9e29c7517d679fe55c86f8300dde681b6470,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html test.c,70,3,2,1,buffer,MultiByteToWideChar,"Requires maximum length in CHARACTERS, not bytes (CWE-120).",,"Risk is very low, the length appears to be in characters not bytes.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));",7c6cdcb10ad3a16b8bfd56e3dac84829f9bc3e39d4dde74a2be9bbe000102fc5,2.0.19,FF1023,https://cwe.mitre.org/data/definitions/120.html flawfinder-2.0.19/test/correct-results-006.txt000644 000765 000024 00000003031 14112766110 022045 0ustar00dwheelerstaff000000 000000 test.c:32:2: [5] (buffer) gets:Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60:3: [5] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61:3: [5] (buffer) _tcsncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). flawfinder-2.0.19/test/correct-results-004.txt000644 000765 000024 00000003031 14112766110 022043 0ustar00dwheelerstaff000000 000000 test.c:32:2: [5] (buffer) gets:Does not check for buffer overflows (CWE-120, CWE-20). Use fgets() instead. test.c:60:3: [5] (buffer) strncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, snprintf, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:61:3: [5] (buffer) _tcsncat:Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left. test.c:64:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:66:3: [5] (buffer) MultiByteToWideChar:Requires maximum length in CHARACTERS, not bytes (CWE-120). Risk is high, it appears that the size is given as bytes, but the function requires size as characters. test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). test.c:77:3: [5] (misc) SetSecurityDescriptorDacl:Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732). flawfinder-2.0.19/test/test2.c000644 000765 000024 00000000054 13774402305 017056 0ustar00dwheelerstaff000000 000000 /* Here's a file with no contents to try */ flawfinder-2.0.19/test/correct-results-005.txt000644 000765 000024 00000000324 14112766110 022046 0ustar00dwheelerstaff000000 000000 test-patched.c:13:2: [4] (buffer) strcpy:Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120). Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused).