flawfinder-2.0.10/0000755400514740010010000000000013504006140014557 5ustar dwheelerDomain Usersflawfinder-2.0.10/announcement0000644400514740010010000000252413406345645017220 0ustar dwheelerDomain Users 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.10/buggy-latin1.c0000755400514740010010000000007113150363277017245 0ustar dwheelerDomain Users // Buggy é main() { char x[1]; strcpy(x,"aaaaé"); } flawfinder-2.0.10/buggy.c0000755400514740010010000000003113150360413016040 0ustar dwheelerDomain Users // Buggy é main() {} flawfinder-2.0.10/ChangeLog0000644400514740010010000010016413503474437016354 0ustar dwheelerDomain Users2019-06-22 David A. Wheeler * 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.10/CONTRIBUTING.md0000644400514740010010000001144513421443513017024 0ustar dwheelerDomain Users# 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.10/COPYING0000644400514740010010000004312713406345645015642 0ustar dwheelerDomain Users 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.10/correct-results-004.txt0000755400514740010010000000303113470413366020777 0ustar dwheelerDomain Userstest.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.10/correct-results-005.txt0000755400514740010010000000032413470413366021002 0ustar dwheelerDomain Userstest-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.10/correct-results-006.txt0000755400514740010010000000303113470413367021002 0ustar dwheelerDomain Userstest.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.10/correct-results-008.txt0000644400514740010010000000131113470413374020776 0ustar dwheelerDomain UsersFlawfinder version 2.0.10, (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: 223 ANALYSIS SUMMARY: No hits found. Lines analyzed = 121 Physical Source Lines of Code (SLOC) = 84 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.10/correct-results.csv0000755400514740010010000002723313470413365020463 0ustar dwheelerDomain UsersFile,Line,Column,Level,Category,Name,Warning,Suggestion,Note,CWEs,Context,Fingerprint test.c,32,2,5,buffer,gets,"Does not check for buffer overflows (CWE-120, CWE-20)",Use fgets() instead,,"CWE-120, CWE-20", gets(f);,6a5bb383fb44030b0d9428b17359e94ba3979bc1ce702be450427f85592c649a 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.",CWE-120," strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */",cbd19c308547e79af13436d8f7dbcf6c62e49e4f62ba9aee38fbef29e0772f74 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.",CWE-120," _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */",c3f6ba2c710efc878e66df4578894fd408452cb7cdec7ae6f492a3b1796f8c42 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));",4f5b73ff337a54d6e1d9a369659ca0ddb4f80e6b7e38a17e5b112f6d3e266e69 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);",9ecdc1e903acc16a646bf7909a630ae22a7593b70952c39ce6bd9c5a23fad0fd 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)",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb 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)",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb 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)",,CWE-120," strcpy(b, a);",c01c8472bb53022e912da4da2faebc67d537855da324020c44bfd5e608a79b77 test.c,20,2,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 test.c,21,2,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 test.c,22,2,4,format,sprintf,Potential format string problem (CWE-134),Make format string constant,,CWE-134," sprintf(s, unknown, bug);",16ebc2ff96ee4bab2695783709e97b597ca9c8b8cc149e33aed859f0fafd3431 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,,CWE-134," printf(bf, x);",46f42896019245d2dffc4caf4fe018b073ce2a58203676eaa28b6374558a5b5d 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",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f 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",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f 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,,CWE-134," syslog(LOG_ERR, attacker_string);",22e98963d5af7b197a090bd522d2d39b8d8ee7bdf08453fd2008939c92cd9677 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,,CWE-120," _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */",e00a4a1a0a3603db98a23fcff3c9cdfd9012f5a81826814d9508e0f22089b993 test.c,56,3,4,buffer,lstrcat,Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120),,,CWE-120," lstrcat(d,s);",364b4c512862fdccbca27d2fa7737995b5d24b637a760976c940ae636218d340 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",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf 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",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf test.c,95,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",,"CWE-120, CWE-20"," while ((optc = getopt_long (argc, argv, ""a"",longopts, NULL )) != EOF) {",5bedf6e5bccf596008ef191ec4c5d4cc51a32cff0c05ef62d5f10fab93d0cc24 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.,CWE-120," strcpy(a, gettext(""Hello there"")); // Did this work?",d64070fb93ff0bb797fb926f4dddc7212d42f77e288d5ceb0cd30ed2979fa28d 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.,CWE-120," sprintf(s, ""hello"");",907b46be1c3ea7b38f90a4d1b0f43b7751cd8cbe38fae840930ff006b702157d 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",,CWE-119!/CWE-120, char d[20];,36c87517700337a59cc3ad3218cfdde56cad37d69cdeccee5a55ab232d5c7946 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",,CWE-119!/CWE-120, char s[20];,213de8e8815fc84c423b55fd845fea541f25744718e486234364bb457863b597 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,,CWE-120," memcpy(d,s); // fail - no size",e667b352fb0748c67b607b11577b11bad87545779c39923e61839dd04056055f 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,,CWE-120," memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination",01bcc2c8ba2d928ac3315b4dcc6593042ea05e62888a10a6d2cf16797a65ed32 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,,CWE-120," memcpy(d,s,n); // fail - size unguessable",2517a2fb5981193a6017cca660d16e85aab133706cbec302df97aaa623fc77ef 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,,CWE-120," CopyMemory(d,s);",977f8c805ddd76ff32e0f7aea08701ba97d9ce6955136e98b308ed4f70eb2e11 test.c,101,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)",,,CWE-362," f = fopen(""/etc/passwd"", ""r""); ",2ec6928c77a8b54caa61d0459f367c4394ee1f5e6f488753f587bfa9c780bad8 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.,CWE-120," strcpy(a, ""\n""); // Did this work?",0badc5f4c500d17b42794feaca54ee0f49e607a32510af3ed749579001017edb 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.,CWE-120," sprintf(s, ""\n"");",c65fbd60851f3c8ace22332805966606488c0d242c1823493c582e267609b1a7 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",,CWE-120," scanf(""%10s"", s);",e24c4c801f10acfa93098b2bef58524efe4f88237f2dd8b58be9afa838616afe test.c,57,3,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 test.c,58,3,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 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",,CWE-120," strncat(d,s,10);",dd92f996a554bfbc038bea27640ba25dcf298383140a8330dca7cdacf493a701 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),,,CWE-126, n = strlen(d);,db7201c7df7f543ea76febb060bda167e414e71e3d18095fe1def69f8c47a4f6 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));",1813fc329227b38abae867d8023a9e29c7517d679fe55c86f8300dde681b6470 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));",7c6cdcb10ad3a16b8bfd56e3dac84829f9bc3e39d4dde74a2be9bbe000102fc5 flawfinder-2.0.10/correct-results.html0000755400514740010010000003503413470413365020632 0ustar dwheelerDomain Users Flawfinder Results

Flawfinder Results

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

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:95: [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:101: [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 = 38
Lines analyzed = 122
Physical Source Lines of Code (SLOC) = 84
Hits@level = [0] 16 [1] 9 [2] 9 [3] 3 [4] 10 [5] 7
Hits@level+ = [0+] 54 [1+] 38 [2+] 29 [3+] 20 [4+] 17 [5+] 7
Hits/KSLOC@level+ = [0+] 642.857 [1+] 452.381 [2+] 345.238 [3+] 238.095 [4+] 202.381 [5+] 83.3333
Suppressed hits = 2 (use --neverignore to show them)
Minimum risk level = 1
Not every hit is necessarily a security vulnerability.
There may be other security vulnerabilities; review your code!
See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. flawfinder-2.0.10/correct-results.txt0000755400514740010010000002050313470413364020477 0ustar dwheelerDomain UsersFlawfinder version 2.0.10, (C) 2001-2019 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 223 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:95: [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:101: [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 = 38 Lines analyzed = 122 Physical Source Lines of Code (SLOC) = 84 Hits@level = [0] 16 [1] 9 [2] 9 [3] 3 [4] 10 [5] 7 Hits@level+ = [0+] 54 [1+] 38 [2+] 29 [3+] 20 [4+] 17 [5+] 7 Hits/KSLOC@level+ = [0+] 642.857 [1+] 452.381 [2+] 345.238 [3+] 238.095 [4+] 202.381 [5+] 83.3333 Suppressed hits = 2 (use --neverignore to show them) Minimum risk level = 1 Not every hit is necessarily a security vulnerability. 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.10/cwe.l0000644400514740010010000000054513406345645015537 0ustar dwheelerDomain Users%{ /* 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.10/flawfinder0000755400514740010010000026367313503474037016664 0ustar dwheelerDomain Users#!/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 formatter version = "2.0.10" # 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 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() # 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 = data self.hook, self.level = hook, level self.warning, self.suggestion = warning, suggestion self.category, self.url = category, url # 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() # Show as CSV format def show_csv(self): csv_writer.writerow([ self.filename, self.line, self.column, self.level, self.category, self.name, self.warning, self.suggestion, self.note, self.cwes(), self.context_text, self.fingerprint() ]) def show(self): if csv_output: self.show_csv() 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)) # 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 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 == ';': 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 > 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 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() text = "".join(my_input.readlines()) 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) and p_digits.match( text[i]): # Process a number. i += 1 # 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', 'Level', 'Category', 'Name', 'Warning', 'Suggestion', 'Note', 'CWEs', 'Context', 'Fingerprint' ]) 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++ '.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("\u2013") or h(f).startswith("\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). --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 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=", "loadhitlist=", "savehitlist=", "diffhitlist=", "version", "help" ]) for (opt, value) in optlist: if opt == "--context" or opt == "-c": show_context = 1 elif opt == "--columns" or opt == "-C": show_columns = 1 elif opt == "--quiet" or opt == "-Q": quiet = 1 elif opt == "--dataonly" or opt == "-D": showheading = 0 elif opt == "--inputs" or opt == "--input" or opt == "-I": show_inputs = 1 minimum_level = 0 elif opt == "--falsepositive" or opt == "falsepositives" or opt == "-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 == "--html" or opt == "-H": output_format = 1 single_line = 0 elif opt == "--minlevel" or opt == "-m": minimum_level = int(value) elif opt == "--singleline" or opt == "-S": single_line = 1 elif opt == "--csv": csv_output = 1 quiet = 1 showheading = 0 csv_writer = csv.writer(sys.stdout) elif opt == "--error-level": error_level = int(value) elif opt == "--immediate" or opt == "-i": show_immediately = 1 elif opt == "-n" or opt == "--neverignore": never_ignore = 1 elif opt == "-e" or opt == "--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 == "-P" or opt == "--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. On Unix-like systems 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 == "windows" or os.name == "nt" or os.name == "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("
        ") if count > 0: print("Not every hit is necessarily a security vulnerability.") if output_format: 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(): show_final_results() save_if_desired() return 1 if error_level_exceeded else 0 if __name__ == '__main__': try: sys.exit(flawfind()) except KeyboardInterrupt: print("*** Flawfinder interrupted") flawfinder-2.0.10/flawfinder.10000644400514740010010000015100113406345645017001 0ustar dwheelerDomain Users'\" .\" (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 "4 Apr 2018" "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 [ \-\-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. .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). 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 "\-\-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" Flawfinder presumes that the character encoding your system uses is also the character encoding used by your source files. Even if this isn't correct, 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 wants the world to always use encodings perfectly correctly, everywhere, even though the world often doesn't care what Python 3 wants. This is a problem 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: \fIUnicodeDecodeError: 'utf-8' codec can't decode byte ... in position ...: invalid continuation byte\fR If this happens to you, there are several options. The first option is to convert the encoding of the files to be analyzed so that it's a single encoding (usually the system encoding). For example, the program "iconv" can be used to convert encodings. 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. I strongly recommend using the UTF-8 encoding for all source code and in the system itself; if you do that, many problems disappear. The second option is to tell flawfinder what the encoding of the files is. E.G., you can set the LANG environment variable. You can set PYTHONIOENCODING to the encoding you want your output to be in, if that's different. This in theory would work, but I haven't had much success with this. The third option is to run flawfinder using Python 2 instead of Python 3. E.g., "python2 flawfinder ...". .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 \-\-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) is itself that the removal is very temporary (in which case we should report it) or an indicator of a problem with 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.10/flawfinder.1.gz0000755400514740010010000004561613435140123017423 0ustar dwheelerDomain Users‹¥Ë\­}ûsÛȱîïóW ̹%r—¤,y7»kÕÍ=²,ǺǶtD9Þ­8u’ ˆ˜”¬Têþí·¿~Ì @Ê»çQ•ÚX$8˜GO?¿î>øÔsãO½¤6HÎÊÍc•ß-›äøÙ³£Ññ³£“Wé}>ONÇÉÇe–­²*éÏä_ÿjÿÏÊõƒð@7˼N6UyW¥ë„þ¹¨²,©ËEóVÙIòXn“YZ$U6Ïë¦Ê§Û&Kò&I‹ùaY%ërž/y úp[ÌéÍ2Kš¬Z×I¹à?þôþCò§¬Èªt•\m§«|–¼ÍgYQgIJïÆ'õ2›'S?yYLtÉë’FN›¼,N’,§ï«ä>«jú;9¶—èˆÃ¤¬dƒÒ“¯’rƒhÆÉ*mÂoÇüÜÞMk'yÁã/Ë -kI£ÒBòÕ*™fɶÎÛÕÇ §“7o.?Ü$§ïI>ž^_Ÿ¾¿ù儞n–%}›Ýg2V¾Þ¬ršW¥EóHkà!Þ_Ÿ½¡ßœ¾¼x{qó -%y}qóþ|2I^_^'§ÉÕéõÍÅÙ‡·§×ÉÕ‡ë«ËÉù8I&&–ñ_Ùêíæ,rÜ„önϲ9í0¾LI%ÌPupQ¯³¤-Ó_$}“Ç$ƒ¡]ôðX2Úö@U½ú¾àßÉ_wy# @ i¢A®ö'MôR#é“”¨ú7î^>Úðùv–E„}{ !KÇÙ÷Ƶ/ ˆ™6›æÑèŠÕìj¥+©òúó Oÿ":mÀyêª,©YtÙò \èFI˜{Añ”¯sºtë¿oñ“i•Î>gø}1w÷)_ºEU®Ò‚H¤VKÜr%# q.ß“;ì+‚·ÐÀÑkæÙ&+æ5t29ÏR´ÒŶ˜‰öUV?¼OWÛÌ4y·II¡#Ú¨¼no?ÒÛODMÄ3$¢)êd=šö‡×NHdF\@¦óŠ¥½ØB÷Áº@´Î~@g¼†Ê®’ û^¨2Τ‹nn*9SdêHÅ #KnÝžÏEIÚT:…F~—5,ûPt×kZó*§í¦=ÅuÎéUÁŠSºÊÿ‘ͪ´õ€'ïlx§»ë¥ªq±Œ9Û‹RL˜?¡yÓMʪlç·'¢>“ÅE´Y;æIÛõ”¦N{Κ†S^ìÎДîz¼CìsÑ»k°7Ъœ`n*ûÜôeUÿqsþ3ý{ètGÞ峪ó óÀ¿xkèàæ+üök3¥^­Ž¼X”IJìE²lšÍ‹ÃLJ‡qµÉÇ´ÎÃÿ·ÙγÇò0­š|FrH|ƒ4‹x)³²_%ŠUŠöûª7S¦[ËWŶsìÞCb;ŸK¦Ð ö’· o íë*Kéö ®„ÙÂ1«1uQùŒ£ë‡¡åb…¡—d¦·H²†U„Èö»7`nY=«r¦&C7TÞT‘†wO$âÎäL>féç÷èœ(ƒì1ü&éŸ}<'ë`¶E<·ê×l+Ð¥OHS yéR¶mg[&ÎiF¥E(9îõ"Ÿå¼]4Þˆ^HÜ4§›¹g’¼´Þ_ÞMFÓ´ û×^~8ƒÆgŒAE~Ê$ÀLDžõ,7<ˆU¦µðPOu' §$³®çÅxm_Á$;̊Ѷ>Ôk{8ÿøãwß7NëÍ·ˆ‰*1¶In¾N¿\Äû’­ôŠŽ¸ÂçÔ8ü{“Κ-ïL´¨ûí ñ4'.ü8LXÖ~˜ýa¬‚lìº&®º„åKtŠßÐCcbUQMÿMsæ:)&ó*[—÷ô‡Ûû®ŠÙ©q·²y‰BAÀ‹Ö©Ó‡,“\ºÙ´/ }ƒÕòQÅÊ%^m: N•)¼nFLâd¥ƒ|#i‚·E ý.áOIUñé(›'Åvö™žtëô3q«­i7|«VÙ©±|ÃÓ…  r ¾„t6Ë6Å,$·™®5þ¤yTzΗ-ƒnßÄÅvž7ìëPÎ5ô}VŸÛ5ÍZÚ ==,°°ˆYŠÕÖ:ˆr[ÃÁS°4«KY@G $iWnÖ¸Ò¼àeê¤Y³fÎ3Hù½~ ¾ËahÖ*¶› ñBº;C‡Ý Ûdr‹GBùX¡rGs¡©„‡@pü‚~ºhT Ž=€öFI·’øY¶Z˜KlmËįE›±W¬·µªùeáµé樌j•мj²R/®’OýéÖ&½P}ýÍž¯“oEµ++ÞGð*¾c¤E×D<Ãȃ¹)öɼè1 s½‹›Éw/Dͼ>½™¼èéù,ŸÜH"¦IJÊ¡³“ù_ç¬vãê-i B.8 ‡ª,q&Ab¿€‘aò°ÌéçLLuç2òã¶xöiÒK\RipzJ"þ(Ä!CòèúÌIçXlÙ'žÕ…—¬KÿïÁŽÍSK½ BúEÚ¤Óª™¨Æøõí-»²æàà„¬)UïÊ­tý`<]›$J:Ó<­æaÌb¶"-¢Æ}I«»Xk‚ݱYÔzºítZkâ8òCÐä´l «‰‹3¯ë­Y¬842éÂcÏØgž_T}È膤xwx+“IÓäC‘­òÏÂ5?Ò’òáö,<óÔ–èôˆžg²Þ¶#N(DMªœ• T³@åA¼‘¾Í+7ÏévÕÄJ‰¶Àþ¦å=Ý[Ox DP%l~±e¿ãÑ ò‚í%²)¡1h0åzLd½ÕF"©Ø[C²·tš&iXs’·Í·• ÷U†¶cK§ëà²f³ùí[¤§~2Ρ¹àŸµIR§sXï¹ãçÀ«¿²¼Xßåð\ˆ.úQä<ˆÜ²ûT@5O¢3ö´èX>¥´ý¬Ò‚¢±#ÇÒî݃*". ùåj=• êg¹fíkž²Û—­\!ƒë9±]PVŸkðõy‰ëˆê¦±>gEþ–Ë®O†ìfƒ§Z:vPÇõiGo2!"”<0ydµEŒi¸~8[LœávEø`Á„Ú›Ð,IøÐ¬sú~ÞÍÓ?7. MÚ±T~zy­i^…©(|³›ƒ7‰la¨4u“¯¡÷ŠÍý¡àëŽÃ©Eo "nIÆùlvàu\¬»Z|D³U )±xÒÕƒe°õ½eJÒ®v ë¸*W4Rù0äMÖÒù¯æqC?ÐJ8í”ÂÍïh‘ø©.’ Ç %ó3lÛj+›‘žëÌ߆½X²æ4³²óNqœ¥9KYüvGý#W ÆéŽþÌôÔ]Ì#5WE«£'¡¼O3öœ5Xtø x/Dˆ;wH ¡ÖHö3ö¬MY¤mˆ?Î]ß[•ÓGµíØeV±ƒ±ìR9Û ‚â€Ý #Þb'±MNV=ž³0á=“}(çsY&Oˆå~]n–ÄRØD›+y25¹l¡¼`%­ `¥< î1'·‰h¯áCeâ÷A iF—0]=Ö¹. û¬RuèjU™piõWt´ÂýذÐÏ9 Ì‚^xà)èÆ<Æ"T‹WÂ/Y‘í:‚“>C¾p°`u3—ê ¬I…Ò=8&cŒˆt–¹¶Fæ=¹49/òÅÛŸ‘FBØØ}\ÂUn[ìCÜØ-Â÷Ü&+Äùç™R•ÝSþvŸzëHa*l×öC’)üš½ì¡âX¶üó½ñ¬7Lzã%ÿ7›éÿmøÿ7wò÷ÿw¶¡OégWWò÷—/òÿß~+ÿ¯ËÓýs‰_±6>~ÓíǯéööÓˆô…u–¢öx= A¶š`˜@òÊ‹×õœ*XºÊ¾±æ9]™WömO`ÊÓ;çÉ&'v9ërEF4ñrˆCø¹ñ$¨*WõãzZ"2f¡Æ™<êú¦ñ‡Ð¨jqbÕ«Ü?õF™)xâýÃ%œõž¹%Ú¯|˜§»jjÇÁ‰Ñ+áë’Ï1¯c_È€yßÖXÚ®F¼fh6 î3¼{ý´VN,üçaFKZiŒƒµ±%Ý{ÈWU å÷PK¡#ö'o/Ï~8¸&üð•,«(‹Ñ”dáç!ÿÓ,13mÆ,¦Ÿ˜6\w‰bubŽ4±Œ*aN,)øUØÛõLEšøÙ;íý{ý£è˜&í’Þ_žý5I’gÉ_Žðÿ?õø7##¿E…:ÔYÞMèR{~odb=§>¤5p.:ñ£gÏžñÂçù}>—ÏZtŽ÷q|Œn¯\z>:Ï D:m Õ ¼È[Gª{-¿òŽ3xªb…÷‚-ïÚ H)¯ÕE;5›n0ŒO6zAkà±Dëùšh!ò‚7,÷Õ²öX(ù™ ¬¢l~3AÛî# ¶üä4¢Dÿø©ÚòÊÁ8.%qÈ5^¨ñ.[õ‹Ž{¶ãD}Ú' Ñ)T·N±Qžò—²û6æqì»"=fǃF@ª Þ7iÇì2… ž[¸Çì;°úú±nàÛäjÍØ=‹¦ŠÏS½ÙðiÇ8ì àÎ\œûLCïFpy‰ i¼Öœa—6­`—îl[74%²œ³‚Y£’igŒ•™›4[¨Êd?$ìiƒë7€æeÖCäl“»F:Ÿ*yoé>~2­½œ¼bó]:»œ$? Ñ_,º¾ï„õ%°–€;yŒwP\º „’™NÉÌkf*Ô/“bÂ;þ­ ¦¿žðA4Ȭ…]#”ïTQjù¹$èÃÆ0b9íKÑWÓ÷@vNG\dˆ4‘2ý7xëj©-Ö´HZŒG\¡Ë2°lA¼É?9´Oß;Q\UlJözH°ªf–íqÑBö³)-šÀ’-MSý‡ÌUWðkDD~MºEQÄÑ7Øþ÷â,ÊÄØƒFœïŽNtèºÀŸ€…€ðHã°'yX¶cdK–û¢£™(±-!Ôâ&…Å£köÝ*bD¦?d•Å¿Çp@ÍqˆîĘ _ѱ%6åsl"”é¶ÕM°®ÁÇ1.‚Ô;C›"+CÌ,_ñ;ØÍºÕ…Þàq@&´øõâÉM€­ ZÅ8 XÚ¾YF²œ&ޝ›Þ5lEC:ñt{!.ø\ Ö;¿4UZVó¼€ÖÐEGŸÒ4ã‚3t ŸqÍÀ¸„YÄšH!íýzüÈ0 ò¿ŽbûjH™Û=ŽÖéÎÌK8‚ãBŒgHr² HW¹£cÚ°€æ‹0Wxnð2”ûÃ5é¹M³©_ÆäC¾ÑÙÈ|M= {þ0¹’׌|½üxsIß~8wiã~ËPNdý =·Þ œ#~ V¯¼0‚zDAU î<ׂé-\/ìJÞ [â!'Uær6Kk’ñšL2J£™*‚Å|KC ×èó¾E\¡f£ºæ§Å½õÓâ Cu‚Ê|÷³AS›wÈüZ´"8Ý¢Rç^«àÐ`òañ9I’Wy†­2Åè¶Qç)Ç{““ºF——9´HOÜåÇ%͉²ð4 –ò猙tòtДØ4íÅç,Ûˆlæh„1ŸíÆ4³’!Å»aóy© ˆÌUÓîJ‰™ptžFvê G Ë·}Gab®n3åàú ^v­‹w§Ž‚ú2ÖŽÇÒ“ ëj>B$b¸Á¶ ÈgÑWqÝ“èÚtŒA(ì⣠X”œ¨Ù<'B¼yþ¡9ÜOÙªÜHt¾¸ÏiåÌü¢î7Ö ÙMîºWs× °P(/_½ÁX„pgÉŽÒ 3ysóî­™à'çφ|¿#¨À‰žoVœXÜ™°Q³Bkµyõõ¬?‡,U/âÓ– é|›Añýˆsý9¥ã1§‚’ò⾄-_ݶìŠOÒÇ'ƒ6犆÷ÉGüÒÞ!õbªÃ¼~ >Ë›z¼3e‘poqC2bŸ¾õÀ‰¤©ò;ÒüHí«˜;JhE³Ï/‘ìâ%‚—Û¾³ n?0U6Ã?ž·˜ì!¶.ŸáÐá/‡ ;Žê d¹¦¬\åkñl‰ÒvÄGv5WFºF~îàÊÔnÆ-ˤw ø¨Û¼ê$ ;£U@ÈE„$æ…ÆÔaúˆ‚îÜTbq$û/”›~ÌþQë–™Æß–tH-™’ùÑøø'Uã "Â;Æž!¨,Üe¤ÓZ ¶ù<ÛPt«¹Qÿ¾¶ÝKàÃ5¸ÞºVÄ/:›“Ȳ{2 4v¯ÄB¨5£—3÷vŽØüµ ã˜ª'n6 Û ÜÚÖ¼Ï0nÞQ…-ÜÅÌñ[Õ˜]HÎÔ·’aMOÎ;è}üD_åäMª†v–Å0Ul—ì™úþ0w}2r> D¼ Oh4 ÇÐBU>HyÍ+ÆÀ<Û Õ׊,«v…iz{ ˜(…™oðJ²ÅÁ‹åʵŒöZU„|¢ œHÂÞSKs dlúÖÊÀÛ[0tQ6°’u~Ø®±"gí'ñÍ®VA3G^£Â=½#«ºîž ƒÐ£H¦¢=:±Îè›~6¾“CúæðÄTC}öâÓ§õcÝl‹OŸHøµ'‰Û·ï®>;’ˆ(›*CÙõÜè]ìðü8%Ô³/0?°ö(,pšÝåš§Ô÷"`?/-þUêaŒHEbć³í‚:ÝR?sÓ‰ëÞƒ%ãÃÃ㻼9±Žëûâp€täU­I‡í<ƒf³áì‰b‘ßmÕíÝq¦’˜Ü‘~’ë.dÞˆiÕXŽ$óN’2Ê÷5‚ÑvXãç¦Ù2½ÏËJœñ»»þ¦)Œ–b‹äEþ7ʦÆÏ\iîiëÛóÃ-ª1§C­)ÔJÒ“t"Zƒz--{…CÃÎã„i[Q\Ô®ÌR=Râš!ùKÄf” ¶SYü¶4‹ò®`ïhœ‰¦ª»SÂtzbêq"ZRÒ1Ù` >mØÊGKþÕ,oþÚë wêdÑø9²Y£÷zŠÐk Æñ|±ÞY”GáÝZý*¯,=D~Ì@ £jžãÔß5ÕZŽÙRuGiu•¦ 2dž˜GNÂú’¿$²yšŽ]“þý²ÂMtÑkÀ4ÐK iâKô˜æÌ½Ì8Êãw•¿ó’ùrd#žZØZüÝø›dà‹C8²ƒ²êP0³%%è§pŒ‘Aóe¨±`¸ Œô?}Jîëqr8 Šú.ÁI‰¦'ôAhø’vNIK´OYJ“\ŸÓÇÁ‰‹·7öI©%*ò Þü±}»ô I’I1›mÙ$~~éX|´Lã>N\Ä’•·«ïU•µ‚È‘Œåu\>Kù(ʱ‘É«2Â7Buh§vZí ÐŒgFCïôë¢ ‚ÐngæyÁ½sÛ1Æ‘«—0@ù„[5Ý+b"žnZÊñw½­,‘X±40²Ÿúõ\þŒýÑêüÀBZaÆ Tq´´FP'6ƒï»š âøät}•¦o }Î{ Û³8a§ê.›ÐWĘÉh4Øç» s*0_—ñ*˜œ~Ù—ë°â"2“ä¯Ó_ùL¯ÎÄIuõðNÁ†^½à{ëERóBìK^EP_N9æ èWX DGµí¥'y)DŒbœÂ3•Ï»•!¸„ŸÅhô’Ÿ{n’5O`(~Ö|Rb1µ¨æ(R*Tg¤õ&ýÛÛBÂ(ÎèÅGëô‹š>—„ ³o€¶wv«U•"Þ´×dƒ0Á˜4i#Ôáÿ”@?¦Ô©a'é@*òÞEx§v %V Oˆ2^,ú‹„ð{ýÞPñÿHúÏf«T´&-鯴BËyäQÉ~rœµ`P¤˜/‚-¤I+â3Ozâé |„£‚¦œ –!ŽU0|ÛÔ…¨ƒ¡YœÉÆÔ3~lG±#*Úá Á‹ÒÎæË²œ#~×|-Öçp¢I›Š†vw•¾ý½øÖ픦áÌ!ïóJ½äÀÁðÒlÞÕ<ƒT]HB¢Å |,Yòb†‰bj#œh ‹L?8hƒ•|l¢}§¸èÉf§ê‰=²§ì‰²X“ ÞuÁ9[†{@'KïèI`ûH“*±cù‰Ü¦f牛ƒÞÔCnìÑñ³ÞÐI ¿˜D¿EzÃdò\¥wÑňamwôº=̰UÍe×/¡•[¢ƒ<f(ˆ3|iþ²~”¡ÔRš™–' KFÉÑÒnNʤÕÿ7˜4w9pxÞ;ÉÚsð™†2 RL¢ûÍT¢±2×þíÑÀß¹$ DX4ŧhým»Þ$fýŠC‹÷ˆ«‚YJ?C±,í]\‚Rï‡,lNx7Ô;(!(×ᇃÎMÒºÑg39ý‚xÕ8S“ƒ× CÍ`~´ç½Ãå†ÞWZ)"hhÑñ¨³«;µúÞýÉCS- AÎ7äˆÙIÿlòçê•aïåNÉMž³ÊZ­ Ë@Š÷TâE%˜/ÏȬŠïôŠjª.À¤BšJ,ž%¾p$y…Ô¹>‚ö§‚Ò,G¸@±Ï'Ý6%gÓ±5-~¯:*,Å;®r$v’LJn,À#ð5d«ÅˆÊŠ´˜c×{Mשgûà*=Äüç1bÅõΘ0ý—Jî}†j°ŸšÀÑ€ž| %Â?éýg£ï‡‚m10ž?SP‹ÿ‰å3¶b øÒ{OSõÆõc2ð§Ó£ª¶ËÓÍüâó–ˆL¦ ©û–7O¿›li š# þ§µ~†ªLt„y0nde݃bÌ?(ÕCï·œñÜ5Öúñ¼Ž6XÔLÎ8V’Á¼Û|ùü£Ýœîx±š±'Z5-Üìú&üzòættüý`Ê{4±Ø*Iup–‘Ç̰Jó•ìRN‡ÃZ&;S¢ù‹ð>vÄ Ø3ƒÃO¢^SØæ|Ë1V—„™tõHl¬x.¬†§š×ÝÙ²m ž¹>ܼýØU#íFÄä+õb{Ô¿+<ËEIT݇  ùÚ€áÊQgY°ZøBKŠy‡uqðÁ'21vÜÐì9~ (M„ëwÔ>I’Û]–ga]£Ü]D Õ'uöðdR.v Çæ‹ù ;z¨o ?qj×ÈÔð„Ž…©Ç–=CãM4Ǻ\: âKÒÊR…—«º;+¥Ös—ŒÔÊ×—ü^ÁJšŒéKD¯Dz#xŸÑÐ*¸è ?s…y'LÄTcx’¨ÃCaZ¤3ÉÐÐX¿°Uabß"!Y4GñØ…Ü\8ÔcWòsWQh vÌ`ص¯‰ä£³cw´d×BÛü‹È|Û­Õ$Ï:l¿¥ùHª°ÖxÄOŠ6Ö[8·pÜ>óýõ$#—ÐŽÏÑ]‰9ÔŸ"zÍs•,O[•=+ز2\‡nŸ"vFÿWÉCQõŠŽB±˜¸çuÁ)ÒÛ4^ä<×þ‡m¨<¡V G$dD¿V¥ÙšŸnG#‰¦öµ9ÊTvßV6þf`(+¸º6)¥)J„ÐïÙ{|â|=@>T|G«¯|é 8v“p¹VO00Z x5!ÌÙÜñ‰‡-.‰'ÌóÌ›ßçP¡Þ»§s…Ywô¿ÈôZ_’³-¤. ðìýzâyK^׺”Þ%ô¿w*yÞ­5&¼—¯]­´}›œ푬QÖ´x³ Åžh!—`–JèU38¥ßéyŸU¿å…Ï•X ìeàƒ±³X S{(«ÓÔø…ü±=áäÅ…xÑ}Q ’Ì‘»Rˇ[õ@ÎV&j׌‹ á¨ÚïZžŸbì¿kmT4®©W›{€1q¸ÝZÜPÓ*X™‰ß.%ˆÑâQ¼=©ÇPÍ„«+ŒòB –Y*º ßð5Ÿ o>Ÿ_c±blj‡ùÒdîs.äFð•Ç=Á£–ŠDv)'5ã8F±&à7Mõ¨~Œô¾ÌY³?E”}Ó”š&Þ€ÈýDbÕ`8Ù¥h'Äcbü¤Öá« ÿ=Ç“/’ƒm³ýxÀüm¦rež) ˆ„"ãíÂmÇß/\^ܧ«Ü'rˆ’‡Ç!C„ç¨÷°áŠ 'h UUeˆÈ-õFZù÷ÓEЙÒ1’PÁªþV[êŒEy¦-nmµóéðR³}üOû[U ™É #±/]m„ïå˜I¯UË((ž¿\ëãTFv„Bè—k›­¯Tf¿0Æ:3Ï6;!¤¤1߮ᮠª¶.M"Œñ–ð@~ÉL5ƒç¬r)㩾X>I@À{—["eS= ·Ð"mqex_0Õï©n'Oü†’ÔP&D"i¥@B½,æm h°‰1S4ñ°Ÿr°öñŸÆ!±…ž¸oÃéû?Ř÷(ÊòKôèÕ/7o.ß_\ž¿?»|uA?Áâ×yÓCš>ˆ5jéËCás)Ò£|ÔÜx"ï¼J‚5 Qà >©È±µ@¯Ñ-¢Víê2„–ÚxkëÆ,±C@£ô6üÁqükºÞ=ÅÊŸÿ|úîêíùDÒG™±e°í|’€f6†Å†GwÚ?ÏjŽ¢>­¨2…q„vR,j›Üré¤Î+ÝA= íL‚Úñìüz,³"öGüŸK’Q¶Ngß Ó©M6\½—’…,0)®M:[–@[€ë¬¶åÊõû˜¶T"G[~Û™>pqæK§.Y€ÐÓômgp"®»§Ïcr¶÷D†IÌ•÷žHÒ/J;lÃ@óÙµ^‰Çs:­8ÿµâqï®÷á꼉©«µŠgqé‰,ãlÐ]’ýmË·ÀŒoé·ŽÊü£-—+³ÿ²N£³Ž …DsBÍ]j·‹\Ý$ò…¤;Ux£˜¾¦Îã“}õëÚ"\²øæMÁ¿€}ãdô¤øÈ!µÄq°¢Ñ=º½³Ïdl£^¶*¯×J|ÁGÀjqÔÉíhmRû õ;cÜùy˜§˜$÷qhâämdb™òŽéÆ® Ë–Š‹Æ%®[Fú°Õ'š—Êǂه.b£Šú½a!ÓP—¯HÌ9Ô¢I8mè8ötís0T Šˆ9<À¢Áe¤XZõ›Ç5ÃÃyj[ú™Õ¥Ò.K~!Ã}Ž7vøG“––yëÌIÛ¾·ç$hºz'WYoÀa››’a᣿'»•’¢¯ü;»y¢é1H˃• CE‡„wVe†ŽÀýL7v— ¬æQ½½ªðºÞ‹ß…‡F&Óþ˜Øò{C9Y)Ý‹GÃÛÊ4Èl~Òëâƒ.ÈC‹L-)ă„(© žÂ¾Ç‰‘¥YgÛyÙ¶|½ADt°4 ®Áßi­Ât .5_k•U¾4A~wòÓ„þ¸Ú$ ³\¦ßvK!Ü ö° ´Kå,Ž&¬•:ëÔæun_’²(Ez¹˜W’¸Ú#W'dŒ•c™·«àtéÈ©3—š+:_ÞyÏq¼tÕÀ¥“+z¾8Cp¨0¤“¾|ßþÒù>€=%:BÕ£ÁQ±ª–Š>=©’vVc \õ4…ÜR«qe’8dmŽ%¥Ú™+zf¬¿îñ,g«²Îtpþ7ÖyÔ»X§[xõLȱ6 SA•OQjäajv’´v­þÿð ObÁõ*~ñåÖÚÕK2{ŸÂ…¹¬›LªU°"Òè¦Ïâ B¼ÁЫ©Oaâ ƒHYP¢œÕá4 Áun9§ˆÓ͵ CBÛUï—ìëuÅcrˆóS\¬¨ÎŽŸ 2³2rºèL˜D´¢µ~䥨é mo`Ü]p­iÁ•yvLÎ]á9ôûñ”ä”ã$bp-÷5ØÞõ߬Ýù4ng¼ÈlïFÏIbë—+‹˜k•%)ÌÓž Ÿx… u‰x{I–Œ„R:ú{4ð¨+£=¦Bðq‚øx'°i.x£9!®LfÛAP‘­Y©+¡³®Šžè¸!Ù²}>‘¨uôlŸY‡ gA=_n;]%­d[9÷isäw{è2_gÐ3Êw£/üDÏy©ž¹´kµèïÆ6x¼Ãdg|ÇãëCrk~Ûè>T‹ãÑçì1+9ý.,Ôl…Êðl‚g!û zý1-QF¦ßxˆ_³OÎðø€{€ˆm)åÈTÖ »/ã4ŠäúüæÃõ{ÑeT6º&L×­»ÐƒqÓ•£KjKüÎŸŠ°`\G©æÉc9L&©²­ômc/$ù˜lB²¡iØ ïCDŠóW4ýœÁ€Ìqó…³Â±{u‚¯ ì3Hl11r¿SZ=1§õ#˜§áœpíá•Àõ…Ü)ͽÆ=5‹¹%5{`zâ[ïš÷ËôöÅlw‘€:•qê+#¢Okˆ„…€A“Åùgsí7B-ŽÄl8QIü8‰s?ZQ½Ä x´›^¶§—‘A,*âŽ{B™Æ­Ò ñ§ZÚ^5èŒ.ß§[×?“Ô~ú ŠLCúÀ$N7{°àÊd|7WÖ›:’`ìÎF[=ékáúd¶ç=41¨úµw „ŒÑ Ox2ñ\¤lGÜï¦ @ãiúÖ¨I š³oU ú&cº ò nŸ} ŒïÑ»Kx Æ0výê¹øôEpèбŒ2´Òò\øÇdÄè®lJÁÐŽ~µÒ>u•C§¤Áޑ♎áhJßΡµ\×…íÞ×ı,Ÿ^*«ªƒ¸BŸx-ÉKÀnâP$ø:œ0@fMøD$Œnÿï¡äà ï•}Ž"óNÍ…¥ U)àA¼½NÎùw E3Ö:®[Â"´ÆžÞm—bœ[/WUà~f‡h¿6Ç¥ü´Nê ¥ó"„~_E¡ßó(ô›ô/^׃ž·òûÌ× >–~²ˆy²II¡V³¸47«í€D?»|÷îò}òñüôßÞŸÓLÎßxw~}ŠòrÒ Ó{‡~µ•&À=··©,|¥z!J[pTO.h«2_žúA‡3_7Šá\û<<…šÏ¨¡Œ¬Ž- ]G âÄ{EÏŠÊãGBR‰´٬ʼáÃ|²íãxìÌ}əս$ÁûV·¤nÁ/PRPëlfX×âG‹:8p}+&:{ÈÆë¼©²qYÝreŸÃEúw (hg_ QNÉa\ÔÞvj¶êÒ¡°–èÿT£ÒàV²Œçô¿ÖSµÓPU”ìψyÃ>›…逘ÖZÌ2˜®# ¬IÕ\§Í©ûs¸§ªÛí­2;2Å=ÞKÉKG¯HEQ„qvèhz{{¶J뚘ÜKùí%i-hup¸.¬øÊ¡²oe-.žTâU¨ú/eDørÔÆGcCÁâZ¤b°Íé‹GÙ¢âöEË’QÅDðï.n®ÏyBZE¨Ý§?Yg (–iæ¬vF—´cu1¦kfÙê0Å$Ö©ô7“òܸdA­Vʬœ$vÂÄ{c‡¥¨ku(ìÓz¥‚5 Ê+õõž@ýàË\s#c|²Ö‚[¶¦Qk&~­i >?²Ÿ¼@‚ÉÇ7“­®.~õó?Êÿÿð»W+AWL Õ'‡;£Ó0íª’æ™ Ç(RU«l³²··,Üó£œøßI ƒSZ„ð¢M¼ŒF ¦ZØÌ3H×úáïöüc_#3ý+0A±¡]LX¿TɉK”bAÞÏlö³• ¶Œt}‚N‰òÄô²lVŽ/ë­˜çRׇŽtŒ© œB=ÁÐ×HúåÍsN©ÞÒè>1ËÈ5xhá [¤ÝËêô ·‡¼Äuó½bÆ?y¥½eþï–nÒñs®:üÝ $M™á¬oU¨»Ð’oQ=enË3^ßr‡wÚ×Se cðÿÏz55 R R¨Öõ¡ÖûÔïx\uW°Y3ÐršÄAó˜nï|î ÷6%ÝfÇv‚‚nýSå¡no,Kjù¡qå]hÜ^‹Ü V v jLšÏw»Õîm´ª|Z6‰jÕ蛆 ­ÕÎv¾ù–&‡ pÐ ÷ yØ–båÃw¦«MõŸ{_ßz蜾LÉT–5ó†ã°­ÙóeáZ)»E¸$7_Š£gÏþ—tðë<\dw龇;•×™©zbmE¼†Âåû‚Mµ\!ÈÛíczI®fåzÆô’vv¨‚Öpyàa›ÆõËiÍM=àjiªíLË K$GØ“R¦ûËšH!ÀÁÞ®hmÜZ¨Vʪ_¿ñÞº¥o…4NÈXýÝ>Ó곕åÑ$Ì}Æ:]\%ŸúÓmrìÄ zñ´´óðqôð[t¶ICðë*m–\…9Ìu†\8®yúÊ»Æû··x*¹©RL>]‘AíßÁoøáÇè ï³-il+mA·L4œun‚ŒE*ÀjEr9ñeìé=Ñ_Åß$Q‚ÞöMûu¤Fï³9ëË.7™•YÓä%ÆKu{¾ËÖX–x HëPχ×<Ÿ}£­*QuÒÕ};»p„SQßÃYì·83¿ÅDýrbý¯y,ºK>þËø©ÐnGž÷"ùP¨»bB«‰L8½±;àO !80£÷ÂG÷±J7…èüâø{úÅùº ¼Õl’(|Ä)¹BÞâŠÆ«Û¿{~üÍKô‹4yYq¿tzÑ5úU%gÕã¦Ìp³¤}8µÔâλI_^ ¦q…iˆ|š,S0E"‰4ðä<…L‹Ù²*­+:6þµjh@1ìwúù?`w´ÐM†JvX#*"µŸ$íɯîëÚSgI?<ǵ,T<&WP¥4Éi Ž·Výšv(gaìW×èÇïà pOß‘:¼ÙªÛÞî‰ñ”[Õ\=Ø.iËœtû[nÀñ³C}og×~|F»v­ò”-â‚Èòé/$ÙƒS 'Æã_[¨wwæÇãŸxg´¨$ê"R¶)Ù CkŒ¸ ô‘oZ #UÆÓ ñµìÀ:jÀnÝsœl=”Øt„J›¨¬Œßâš·¢}v+ò cDƒÎ£å.:©ÒÙۢܞyö!„~{ûO4î(Z@ï"s¾5]P-Ìó÷méKWÄþæÕ—:Æiá¶?0ס5ÅÙš‰5øZÊ\Ëg9a‹„]ú»~Ë…D>îJ¸ÖâÓHw*Tñ4ßš´Ð†0· Yæ¤bÌe7º=£<Óö §ŸS‡O¸Š?èl§òöžÂ‹–‹ûÁi¬Hæ²ä_ú3mI~4 Wˆ’g”¸Ôy™é;9·À¯•øßÉâcê­qòžÊü ÙˆR”`µ‹O½‰×í^#Tq÷O¢Ñ²ÑNìPge`!UÚmªä|s“hû9¿„!Нk½6á¦'1®6m×…Ðv(0,¸$ñÎV÷Œ¸?¡Bw[ (¸Áüýñ3mCʇh 7ÛŠ´ê,¸2Øv4¯µ…â çÛoõ«—S¦!Q&uFp‹äuk}Zw-žŠ†c‘%ývéU¿WüÙCH¢Á|ÒÑξqäÐÌRÛ2.é´‘E[ïO:ù§Dªõuô' ôd´` oÅÔm1ÒçÆË±´eBZ(%*MÓ¹„¯’ÑîÛG÷<¼ÓƒÈÄéÜž¬à“—‚Ûeð5 ´j{ežÇbkÿ˶Ç69W”d»3®g,‡ÃGîâNc'×úÿ´R!Œý¾t®gø{@‘“Aš5g›<Íš‡,óA=Ìñ)í• »Hê˜Òï¶à†§¯Ê§[i“¬r‡~2Yýpð½ì”zó=(Œ&µ†C1”èŒOÀýÙƒ³Ø‰„q"èªy_ºA¬ÂÏqe9~×^X”C¡óÑzC[ÌØãïëîžz¤(tXÞ»;¬¡cÊÒÔûÐGâövöÆ`a*C²Š]kóX|9uÂ׊³ÜŽç¨‚]×|ɈãÒx²DE¼aÝNÉçˆ÷Éš£¾ëÜ@Úžv-ºŠâ€1к¤F¾:Ñ£ªŸ.•9Fu €-çaAªZ…ÆbÏ·ê«ìЪ`6¼zŒ«@øÀ›ˆfI€„¦ÁÐ^¤R°«IOÛíóñ‚·štÈ©$†‹j“@,x˜”‡^î0"/D»¥[L†ÆöÑãVþ‘å‘«gò`Þ¾«¬5¢ÄÙ£,À¼vRáùM29?ûp}qó‹G¢ÐuZeR©Û˜wUíû½ïõª‰oñÑ« (œ1h-³`I @ùgø ŠšVÁª*è“Ö×Õ#@<¼TgêæqŒñ!¯I‡CoUd@¬¬Ž€Í½n¸Ò/ÇydïHì õ.ðj¿¡#­/€:xKqÞ/Õÿ=ÄP8Ž\¡³cæÄ‚æÓ•_Œ‹«Nhþ¤×ÆÁQ[cñ¤Áñy¥‚¬GÒš¯é=—~ØápNIOZºÐa<ê1èk>䏯nç?Ý®°È§:óYÏ¡š¼Š{ÏàúF½Ë¢æ}ªðþZn={ þ”7o¶Óaœ`?ìdØ+¾ ±¿×À)¬·†"?‰Š7¬ÉT·† >E¨ó)Ú9®c6è„0ãjS›±†™ŠêÏôíVK™ÎÈŒ›m›<°Ü¬=Å;5œ¤ÞÅ8È*··›Ÿø3†ï‹{„§;lwKƒ}ݧ݀ˆáQƒ6“>VÆA"μ“ù|ÎÕy/;‹î¥í!ü!ªŠ £4—a+½BµAÓ×ÞÛBZuF}õ; ¼þ!å÷±jIªÎ£Š`âfj3/9×å·7›o«._Õh_¨éªtEq«D˜ÈGæì4`Qï€è\¥ x6 ¶…ÊÚl ®²£ yÈS=œeI¶6Ç1‡Ÿ7ØôœHÔcÍP"UؘX;ÔªÝR£žHÎ+?žÅÈJ+vËAÄÙ ¤Èl}ì"› ›SÒ÷ø‚%·Œ„w“Ñ«Ë w,óâîÊçC´š£Þd&C©\¡=ãùZ¡ðFQÇíífZ’ÐÖ–&Ÿ4‘éCZ®‚‘i˜~p]±†§‘¸\[ב9…‹³;.¹’Z}ÁïÊ Ó9Ž7rÍ¢„dT×a–Žb$ ·œþ»‡û ã ÚýÆOZÍ(Y5Œn¼ xèJ ³&šÐ>¬tbÔ;´ŸlOØÚ²òâ¢:ióvN%Û²hêБLd@†·ãC›?æÖ5µ¦¡¸÷.„…cED’—îP…yªŠk…ÏUfzµ¶yŒhÊû¬Ùë€öò¤‘‡N¥Öü“YòWÔ+•ër$™ÅD¡¤Eô>—`Sê{ù~˜\]ÓN?üİlú»b©¦©qùî“P™Jkñí«¢¸¹®"ªóË&=à]s™Z",Q «°à‚ Èkg¶+³gº=éZsº…§[›?MûÕ_ïÕ“gP%Ž#Y*µRk¢µ tåèåÒu©6$èÀ]Øâgœ_®˜i¨;`áb:ƒ“4}åKh…x/;r;Ø!𸻬±Ú |Å€îá„2ns"EÌÕzçzã+¶–Q­2Î{æþ˳%Ò½{_´Q*W §ønT=Ä6ƒ9‡:°<”Ó¯X&Yö/MƒÛ÷P@@Éñv ÝsvdN/ÎaHŸø§œq=íÈ5«^å8ì‡ÁZ‘.$+ÂTqd³¯j)½1#²ÿã¹P÷t»jR‹þ)ìH>Å~q“áœ-œdE«ñ±tÔùã9ñ½N ?X}šÕÊ“d§&~¤A:‹RÑ!Ë/wlšË¹à«I~+ߣíÊ4±ˆ™…¼Þ2¢êàabh­³z×Ò¼h$÷Ú_5ÍP…ròhÕ‰ö`¢8°Wª­>42lVh\É©tìs ’ÑIÁfå˜qß8qÌÛ()ÒÕ·DL³ö’­Zj¿#ìo”|ÓêÂ(ÓÐ:–¾F O3ŒJ+†ÐyÌ ™¡–Qü™e‡8Ëî¨í45.ÓM–5™²\ï5ðeð^ÍØ î•åà'ÉkCVÙƒŠÎÔ=1h{¬†,Ò™ÖßàfèÐ(^3䦟‘œe]]g\2œ^ddX##¿š†>¢ ¼Þ×AónUN‰]7¿ »5sIú,0j œÏk߇¤X6öIWš@š‹me& LÓ›ë¼ÞÖÞ9 o_´$ ½•¢Î èð° Ñ5}åÂàc¯³Ê|3bÁ`cŽy°ˆÃe–Þ猫üK5i޴Ъ£ÎîŽç]ñsjQ¿l×áB´’àâ{iµIé°_¼_2 [Mm•½}2D{5Cb$C¹Ê¤JLÈûõ•æBW<׉úYÁFmäK4vû¼ÿ¾–s G_1(#ù×€[çsH<ñ®ùHW äÏp#ð§‡Kò£TÜm¢’jǸŸ¬ÐÐ(ÛF\Àg09"˜}«–ßç "îd—üú¹ô|(œ:؇å‹ç·vã‡ÅpPÈÇÎsîî¤;È€:Kn²‰Ååüô$ÃõØžxtêµY?.®7…reRĨ@Å2ñ¬¯¥ŽÆ*û‚ëmÎÕøžä0ë»qùþ‹=Œ70q./¢~¬;T]þÒô­ôÐ\?´˜ÀµÍOУˆ´É:š˜bêÛ'È5t×zó 7ÎOh™÷É·^Ûé÷¦YO’ÏB:®/:õO¬Wâ:ñ+DÅÜC%i[ê’.M^E‹ûØ»)€êûšqI|sdÛéA¥ÄÅF½ó'Ê#{56·: ΫáU"®]ùs[Ð28;ö˜.°º~—ãúªé iÅhŒ~œÃ6 .²g‘w%@øŽëõh˜y¥¹Á\= Ïç×MUþ šSYÁz8y" j—9 .ã[X¤fÉÉ‘˜+qD‰5Žü?µ3Üž|ãÛ¨ª­¢å™èCÞª@Xgœ-†ÞæÁfo{îS­a­ÒG™¯ð3Í-[ù²ÜZ¤Þã<Ó ò†ëð $(œFÕx1:OÚê&qfF€¦öŸË@ì…Š˜Gwv)e¦Tdö \¨»ÇlN ^/ô*EîDß¼¹/ "YO2ï+ þSÇ!ôR_G›Žû0;™xKÝ€ÁÙP8,êÆ:ˆcõ¡ãŠ÷!y{w²¨»RµÈVÍЉ#Cyôè.‹r(î«9‘Y2ŸÕŸ\Ó¡ß÷6Oú/Š®ŽH¢5ï oÄm5×l@Òæ¶@¡Bm­Á0pNìQ¤¨†®™Ò‚Ýq/­03‘n{ßQ´Gµ¶s¡Ö­‹kø«í‡ò•ê)ÃMlEÞqñx»®\)2;‹jYËáñÍd¥Ý΀᛼˭í¶PEM¸Tq5ˆ9XâÖÆ½j æêÔº7y/Tà»Ý3%pû=Ö—¥!`íûWJÍ9A™ÌRꊭäÞ´äkúE%0Óˆá ÷.]N´3^#΀3Ñ(uYùÖ¡F¯ôÀ&)„ni#uÅýê_äEhIe¶sg›®ÄVÔxvùþ…Vj üªöµû||ÔYÐGö"÷ÃõE}øáúmë&†Û#;^qâM§µªV³]¸×')> pR¹ŸéÄ`žœõ>w¬E Ø6à4@¤«\ðÕ:ï45!êÂY¢ž¯$£àÕ–‰ q³ÞR9«*_¸_!´X®¿Ââ ™ ™R×|”l]([´îÅ%Æ pÍÆ¤}Û‹èC~µª´Yû›ÕMií›]&.$T+¥s„ cÛââÞÀè$»º>’D•–öT‰*b"/·qU ÝRzô¤]æ:³¢$ûfÉ2£áð/ip¤n>aÐ@¹ #×qÚÒSÚ6HKá§Js¯)"ܾwkžáWÀ—1n9(ø¡ •#ùǵTACÒÒBÕÔ’Ø9Ÿ' ,áFo,Kowúh ¬ ˆ×—ÓÞ$i.18ÒüáIÓ³ ïôQ­»ÍEÍD`x*·ò'jVµ²¦}³"ÈA¸Þäü<9};¹ì¹I¶S—ü!›ÖpÏ<…=M¬®0dV¸ñ½D"–WªÎbUo.?ÞÐKéÖŒ/®“Þo¶öô釛7—×îUzO[v:N>Êo’¾ýú_ãaèÂüX6iÒflawfinder-2.0.10/flawfinder.pdf0000755400514740010010000024715013421453504017417 0ustar dwheelerDomain Users%PDF-1.4 %Çì¢ 5 0 obj <> stream xœ­[ËrÜF–Ýó+Ü´Y 2ñVG/425­ [V‹œ±'HE¬B±ÐDeÅ;z7[õ§èçÜ|!]TD‡#$ŠxäÍû8çÜ›ðïŽï1ǧÿÔßóõÑùÇĹëŽ|çîè÷#&.:ê¯ùÚù+ÜÒ/®–Gòæ$ÜI²ÀK3çj}ä¾ýñõéÕßXâei–↫Å B/aÎÕîèÚýåí»÷?\|¼qÙÍ©ó¶ÊOYäî¾Ô‹¢uèÑOWÿudÜSOŽn§÷Î|3¬4‡!ŒL󲈌™…ø1ÉœY‹çÞ +|º‘E^”ê}?]Ðï‡Mpß ýÄ™1N—}iã¿l«¾:UqÊBl'dîçržWÕ£ƒKΦ鋺/óÊéŠù¶-ûGG<èù,ŒÝ]çܸǫ²ïŽ±Ñ²vºfÛÎ gÞ, ±Ë‰ý°{Æb웬¼üß÷?¸|w)m÷ÑMâa(L”æwF^h¯»×Óǽ ð}}õë×UQm&ÞȼdxþŸ“ç¹~rE¸É0˜|`}}Ó§kë™ÇbŸÅòžkØðpÊ|·h»²©…Wž¼5äBû oÅK«²ëÛmUtO¼ÃMNºŸD:±,õOÚ­è2²ÑoN3‘ »«Êú~¿Ù²ñ›±<åȳŒ'n3ZfÑô‹²Ý¿PŒÊ |öMþ©aøÈ9AêÅÁÔ9Iè¥éËœƒ×nò~¾ú³º‰k§û¸_ª¢Î×Ådil!5[x6ë>LÞŒš †ÌxÁ›Õ¦xê/Œ86UÖ›mß=ñ•ÿƒßí-“Ì‹àð†RЇìùúu]ÖU¡àѽAä±!Z…yIó‡·WÓh¤^˜»ûu¼-dÒdº­Qö¬§‘ˆ½hÈÁ_÷n{üò—åé2¯ºbÓte_Ú›BÛýÖæm'Ûnx6BoÇ€ÛS kÄšÄcöâ|©GqâÀÄè@”®Ý¶¼«›ö”!­XÄ\Í&ݘ&Yrh3õ“ÍØp,¬J…({aE"Á("rðYqW|þ³0 {Ól9õZ3æQA¤î‡×ÎÕ@ÃH’Á¹WßO¸'&*<˜{Ú½S·ñëÛV½0cDHõõâ˜Ï›º/>÷¶áÞsÛ1!›ÓÈ“(›P©o—÷3ÁI 1ˈj»®§”§Ið¬ož³ƒ{˲o³£{ÐoKÇoƒŸ“CT%Þ6xv‘÷ySW“]WÆßž±ãÅ»²¤R¿®&€¢»’ FDüøÒh<Ñ¡ý6³7c -‰ÎCwŽÝ@ž v“°¾ìÑÉÊ$L™«ZZúÛiZÑåž1u1œ®µ§ RßO·iz‡º}±˜÷Mûè|ú~_7' @ŸY-ñ—o>¾ûpõîç {[M1höÀ-z`È@¨ÕÏwEÞÎWEçô«¶ÙÞ­œ7ço¾ÿÞnϪiîsÎÚßåc•€Gerj3Ô"'•‡úÒ2ò?Ðß´ƒg Xy6˜Š7lkµ@—F#ªv?ôÝ3YôA†¼6 á{‘Ÿ‰ç»r½©;#™E¨®$Ö,í{©ºù¡pþ¥Æ5i¤!-ß 62K: kHOæåµÓ,)®"œ%Ü Ÿ!:o´< ÑÑ,ÛHQÂʳZü¶°s/IR6¬žŠÕóùʬød£è‡#ó}(À­¾«>sÐÊ K‘yï¬òÑkØr>ø+Õþz3˜—B\¥SëD6}±)’E&Ls(µ15«Žä)ÐRyÊ÷|FÞÑX¤£á‘0qØó›× §ì;§ÛÞZÎ?sZJÒn쎒 ’øKªÇ›SgWÂ+·Ê²ˆyY2“ãÚ²ýh±@¢¯¶ÝÝg¨¸èɨ~ÖM×+O1Â`ð„/+fÓ6‡ý°}æ&À½Ôªæ`œ¸hæ>}.sÍb2qûUáÿ#uég«öOdfFÌÚØÓm—Ü…D]ÎÚß(2Û®p~£{³ÈÖf¿é‚HBÑþi¼‹é¨{râ,m|H¬«4Ò|D¹.IÏ&±gÍ0=H˜6VÝœ"Û‘04žT&†"ÜRE0žxQ¨³™Ìе¨å,¯É#IÀ¤KÀ0±Î¤Îª‘Àã¦9˜­p zÒlÀÇ}®]4z¢7hˆdÓeêÖÍDª‘þd~fjNÂË,ô/´+*œeÒk¢Ô›-UA~ Vëçö”ûtHnÙïh<—EŒ»y[ w”£3Ïkz )°pm&‹ý`$£"iËYö›¬,Æí¿k·ìW@ƒyƒ:)úbìÊY”2pNä¾[ óEÛdËëÆñ@—»|T-ñ€ó *@ª§ÝO ‘”Æ:ËnÄ‘ŽÈ|µl®`wbôÛM† Ë4Ó½&6àJ@<”*Q3VSW»bï-¢€ãj3€ŒÜÙ{Ðúðí°eY_uùÁƒn“ùÇ AM’^ØNyL¿ Ýe/Œ’^’ÇgW €`¾Â> : ˜·º·…sûèüçûÿvާ+0äGlárf«WøúÂö˜ö¸{¨µ(ÏêezcwQ69Ö ïÊ^<¨ÍKu:‘;bz+dA¡U»šêb_?àÎfÓƒ’<!Í~”5{2.YÔSÚªK  c±–pøM;ð+ÓÙÿ™(âP)û`è¸Nn\Šý!ŸÕj)P(H²Á6-ÖH téP±©}Áe×´*ZmÙÝÿ‰|!exÄ¡ºb‹ÅBé\º !A´ LpºU#ÜLçF»ÚùÒv=ª4ö‘w,v¯à\zÆ©&@ÁbtŠQ¸‡¯K}É‹.»Î®ë€3fRRð’—D†TBu,KÈ ˆßî÷-YÛæóûSò¯ÏC· =!-dâ Í…Ø[¶ÍÚñÏð{:÷òÃÌ-@‚šp½-î‚$ ÐúA0xìŒð%:sî¨:„?È|Æ.*»g| âÑx  ‚=^ZØÉÁM†piH±)êEç€=hâ‘úËm=§l?ð ¡iÙöúªò„ü¯¶${;æ-„E_´ôi4 ÑþF¡ÅÏ<ég/2–Ë‘©”A³<:¤”ƒ0ÔÒAœê®Ïâ]ßRb‹´w5<ÚIߎߟÐ`U¾äq$x"?2èLƒÝt j9¡-Yê•)ë\éé·#ja ‘ìqn+d½;Ó4UæS–Bwªá }:S*/‘Sæk©…)*q‡§cFO‹° (%ËÆ™‘ØË´óÕäZpE¥bÂ{Ù5ÍHifŒY(“»#öLñƒ^ðY1P¯©žXÍ_`‹²›oðÝ2„ØD¬Ø&õb­¾B©·íPtC¬N‰ÖXqà`5^1µX ­¡™øË¼%…ÝÌà È÷ÄL®Bt¹O=Oy ” ¶›p}€´/§Ç×?]Înóº.ŸŽ±çE9G3cÄ‹¡‘º(¥:’÷™?ÜHÍ;©¬ hý z]çÕsßo^Ÿ¯»Eí­õ= ä¼¨gÛî\ñÓùí-OÓýOÞm>;rØ$LX¬ˆ JTÖ+š ýªÏA9j:'.€¼ëgºë’oŒWCÁe_¬åÆÁIø+!…î}íHE&*ÖÂâ²S5sQqœ4ÎWÅüžYçò9:3•§t)͇u†ãVÕL ·m!1E4d†…|ÉBÌK‡‰á]®bÕ6…æ6…òÔTs½PAæ“!I—/õžLû.[<·|>/64ï¶îÛmGÿ„«Z¥ }` gÿ\#l ¿UBN-¹iX6L§[pæêží¢¤µr-FÏŒàXçíýø á±`Ù ÐDíV8̧ia<,!µÔ–†˜÷nƒri¶}Â: b1€?<@Ìô º­E'Ð5ÒU¨šÑ`¨ë›#ÆšyY‹²¸ôZ{Z¤² ˼HŸºëä2îmìÑähó•).y(~1ÖÒvD'ÇüÐ ütxˆ«‡jÝ8+ñ ÄSë8'“Óm7¨àަ‘”;(ÞM!™x&éˆ"§ä°S€r©ÿ¨Å/ u ;o§‡4xkÅ þöqî"a¯¾£©pWTKM½›Ñȯc_L´ëm×?퇳ˆ´ŠV:5-)µÆ”|]›ƒ”~g.[¬ófiWâðÉêµüÖ•+DÛ©sW8¬{¥° ½Vl}}íþßé,à‘«/ÈéÓˆLeÔ+Õ‘Œf”ä&óÔwò)=š=å|w>v`NHa³pÏfno*2°£d— TuP’2!Ñ#íïï›ÔùÖWêù½ÔYß-ÐìJÕT1Ô}[ d%ÇÚ4‚S;:– ÿøÝÕeøJŽ?¾>e¨TŸ1÷êòÕ±JQíãdU4’¡£µO–"®¦V2‹~.¢¯´¹{Yâ•ý‰Æ|.ç– „7›ÞŒF'ƒ\iº®.T›Ýv¾R(F¶k›úîlOƒUµ§SùÃý‰šÀµ*èr¬}æìV¥<±˜a@³”©XÀc·ÉÀvõ¤Õ£ÿ-"ŒÇ w´çЧ--c£nÑü&,Ìëѳl¶|¬lòF Sj"ážPe§0Ï €< ·²BÔŸ˜œ>5y> stream xœ•ZírÜ6²ý¯§@騲Äà'n~å:›÷º’l¬TjKJU¨ކ×r–äXž}ûQôŽ÷4É‘âä–«<ö ‰nôÇéÓ ü[D¡ý±Ÿ«ÝÙW?çâa8‹ÄÃٿϤùQØÕNü÷ (苛Ϳ#E®D®ã°Ðâfw|÷ö›Ë›ÿ=“y¨ ]à›õ™Œ“0—âæñì6øõ»7?|û·Ÿïyw)¾kÊK™ŸÚuÕ zõ·›œÅZ…öÍÅã´îuœc--®ãÌüN+8fq$ù¥(Ì##Í-|ªA”­¨Û±êÛ²ër,ïË¡«²iªµ·•øÝ¬SÄ¡*r+ü÷þÐTC5^ÐO± Ób.B_›·í“¢^WíX‚¼Í¡]u×ø½EÙCZ·Ûu­Ù†RE˜è\\Ke,fØ­·*¶ÝF ÕêÐ×ãQ|6[,ðBn5KBiBq³­è$ #é,î×Ʋ]—ýzÒ°]5‡5D4eÏÆKÃXgÓ›»ê¡íawB›u½¹TI¨u*ƒMÕc—bß´YØsßw÷Mµ®Œÿ®UJá Ýæ —Ê2,»nÄ}7nÅCÕV=^¯‡áPY;­ÈO»}¹‚ÉŒ©`v…VgRËP§Úúæøš~ŒÌ0‡ 5’eÔ¾zýê)öЗ»+Qâ±jú,g»öÕªþ´¿´õÇë¦~o*&ð.Ë1¦½NT¦íÝ¥©‘ãŠ_Í[yÅ©{«n×MƒÔÇ%œõRTTF âÑÙ±ëUÈá¨ÃLiç™(MŒP8\<=5õ0§ŠnOKоÚwý8˜x¤iƒ!òÇ\L†Jf›Èö4/C{Á»u/ÖÕæR”Q¢ƒòÐŒ¢¯‡÷¢©Ø½€‹ÔØ]ê0w;þPyh¤.þ!ÓœMÕ T¿Œ­t¨½UH ~ E<­Eyo,ç¥PXéRŒ]ôDTpU-ÞÄT–¢`Ðg‘|’t“ 4L§µ7‹àS©ý¾;À„u‹{¨ª¤’7ý+{h‡ii&“ÌîЯl0F°{¡§ôJ,Ü­ºu%>5•¸ C«-%Ò [Ã¡Ö ¨¾õàà¯dð£ÀÏ ¬¿oëñÊn‚âú¤øÙczX,õâB”“ÎÀÏ,Ò.fY‚ðA‰•‘ ÆXkXÛhÉ©®éyZ% eâ`ø¸Ÿ›¸`({$ÊÁ¢Øu¬ è7E·*úCKBI¾…ƒÙÖ'ä‘jq6Û<¥P¸0r\Km7—b£…3À÷“†:LTácÛ)ÁË ÞîaˆrY‚bÈ“øÈ‹ây|¬ï‚¹5¤Cüà0!ŸžN–N’°Èþ,HO.vßw—W€“¦+×°Ñ}¹zwY+Ð%É|:ãìí«u=ì›òˆèsºÐ³ `ŽÝÁaØv¼Ë$ãdÕ ÒåW7í‘‚Î¥ÿmÐ%Ég&„<„šâ”¯táŠÓ¦ïvˆ2¤§°ZÙ Ó)Èîâ6xzrkÈT¯thž—ÉÍ[¦§lCfzÎ6j*1jqìºæ ÀYš¢7vbèvu¹ƒ–\:yW( &Ü=€Uç²—έõx©MEVA׿ÄýQ¬;ÄÒy«q”Šù¼pb¦µr[PqÊ•àcÄ€¢ïÍʈð jëÿ”¦¾ÜÃûz¿'Äd ¿Ó5f5’gø½"SóžÑe¤ ÈÿM×½§¯KæQCöÒ$Lgzp…«ZaŒXAGçØËd˜Îq/ËÌÓžÎÝ{ F;ùškr~ ŸšÒ 2Sd_°òÌŸãö0Qk¬K«þÌW’=ÔeÌqnÞ£¼¹y—\‰Çm½Úв:"¡¼ TŒ,Ϧ]¤® Û˜ƒ$­XϼA¦Ê"¼P®®Úê=9(viÆYâãÓ °‚9Q@¼ì: >–»º­˜6Œ4¯ólZ 6’>ŽH½IaoD2hµqT5Œ5üV¾ÀØ©’,Œ“)ü~iÍ™Ë ªÂèžXÕ8¥>RË1^Ø7eû"£à‹™Ÿû¤þJ<¬VnQM ‰/Ãã¼>鬘ִT·ì[ ÌÏåÃÀ0µjÊöáŠX€1“RÎx뮌¾ú;²P¦&êM4†ÄÍ¥4Ìã\{œ®â»„é#½ÁsÖ x=/­ì”ë݃ժŒñëÖb42 TÔÉ»¶Å1›åN”²OwœÛ`]‡‘0hì»F|vŒ±ÆT!¶VÄöÕÇ+±^h§bOÂí#HÌÓÅå{üÂZeûôÍr½ _σ¢(ÔÄöSåÇ=Âø‘¢{¨ÊžùaÍDï>j9îë¦kbν‹Y* ¤¦D-¢Î@¦` «^LD®ÌãEmEñ³úz4Ý%LÆÝSoâÇìFEr®²ï[@ö ­; †€% C“?™˜ê°H}$Ø·\Q¨Ñç´…EÙ×ÜU¬« ˆÚ.T”) gÖǧjŠ´‚0 Õ 0Ý)COå {!!Ésö2læŽTQìvGœú†ÒÐ<®ÉÌÒ=YÖh´ƒz^ lw„TàNh¶áÔè‚ÄȦD<~XÐÊ4žÜ`WZ*ŠÍryjͧaÌBñÁlc Í:¨Ä¤‰s ѪG§3·Ät꯹xËÚÌÈ–J-”dˆGÞ_Jª·yj´ib2¾÷hžç‰Û]nwW­CñÆ@•ÊG¹ß’¾Ý©# ~&ùÉSÌûÀ<rèæŸíô8éÈ€Bi”žDJž>ÃûKS':ªÕ,c’0Ö¾;ïvûšhü€hšÞû#—ÙT™ÆÒ›.“…Ïãž%+$‘ÛÐm𡮘DæqðXõLO Ã&¹è¹bí+ÊT¥¨£nÌVeiÅP™Õp%9¡ÂÛÎébÃð*,-OšœÌ\‡qž¹½Ž ôº §B%toPZÖDwåªÇ‚Õ§¶æY¥Çf·^sБ“ð48xTL†Š-«Úu`ÖC·ß‚ƒ‡Po>šâ{Rº$M Òio–¡vÍJ92!Î=#‰í3}w¸ã¡ð ]åòÄ勤ŒbÓ˜ Žmov´c9TMu  gjÑî‘f*v¿ÔåN¸aÇ8esˆé™"#ílê +¶ÀÎz$ˆ;Úå/ÜåmÝ÷ÒÍLÜÌv‚oZt à¹E"Ý~>ÍII,ó‰[¦ÓT-¸Õé(}ªÌNÆ.^Äiu&‡2í8Ë!4é¾Ý¼ ¶<™¤3*. °«å¡*·‘Òìt”Ò¼ð/*S³2z´Ú,COf®iŽWIÇEµO§Òç3Ä¿H£º‰;Ž[k)õìÝkô{vb÷AT‹5€Žªð2Êâ½Ö™œÜÂy1@$^›ñâ'vÑÂ?×(!Çx«/7ÝxAç¶vTí€H½»üš[ ×$ƒ¼ ö>χäIJOüBÓ6g¦™Q# ŠÌõ6ÇÙD ýS1¥!MM|;ýDS@’½®†º¯ÂËë”F|è~Ýfg¬j]SÇ×Ù*EƒÅÙ3’ž¦§‘ÚpBRÔxI^Í5Ë“PF†°äàAè€Ü´ïóImA^(ïÆÇŦ¥¯lÅŽæݾ²Øhäk ã(?çùþ­ozî˜h$ú@ý%[ËÔ:âÉ`´›÷|YÛ£ â4´ó‹2%OÄó°bµ²ê1ñ£ \ÇšfÊÇÚËÇ!Zfór³ï«á°sÊ›mÐŇ4ðoãznÔÉ™A’+–Áq™iüÔ$škt’=ÓˆŠ±yˆhŒÊÔô{n;N»]q®Î¯ð÷Öü]­ìÇÞ|îðn7Aß3ͦ€œcÁyøÚ<ºÚó+¯ú‰ÿÿñ#¾zÅŸ¼òk~zoÿ»5o^‡ßŸÓÇV¹?4Q:ó£yç>3WÌ¢9yýýÉVø\g.63›»EÁôAP•æÀ òsN%ç8;dõG=u»?øÑ¥a0.QÊQÀÔ¾qÓ‰ÙlµséF·A¿Dµ9äçE˜°“.í8Òýé°'dwëâ×EFè4­d³¦.^¤Œ%¯Å¾FÇgUö*/•mAÚeã6cÛ6°}O(ÊRxoÜ8…xUkž Ðxíô`d8î^¶ÍydßÁþFsNS6ÔüÙaË#=çl6ýdhf ^øh’JÙÓ=/€]_ ¦M=O`„ÚX•=Gùœ½_œ™i©™KÞ’7é¿+û£›æ4ã`F¤•¸þV˜j×¼L½.DçÒ÷œ™•õŒå%‰ï­> õÀÓ 6Â×iœƒÛoF¦4æVäCiŠá|4“ÁOð÷[w:‡Îf\?×ÜÁL}d+Co(~@öþÃ]Ã`{E&Î+ñÔ¸Iµ90Ør”›A¾›ÎhŽ,FÏ ædÆ®MGnt s¼{ûãë»Kvm‘‰±JÒ9 ;ÙèŠol›LM1K2z³ç™í6­lÂŽm»öú¾)Û÷WæŸv@k´"kçYˆ‚àÍmF€Î椊©¯ø¤-ln”ÕÞèbiW*R•«­?ˆóüdÜND§1èç~AòmÐÜf³Q¡ÉûŽ´ŽëÙ¶ÑPDZ?îÞðé@6yÉ®MP ” žÖL¦ÄùmôÛBvŽ×.e£Ûù¾¢\Zç¤Þ°ò7¡Ï9£,,’E Êù»³…¯4>8 %tMñ©Šì…©SÍb™Ø~>Å2ýq(;4`x.TÒ°«(þ’TùRogbõR¬Æ ùTmíH”9‘ƒb{êöqt'i*¡6ÆÙãÑ#ˆy®çó#éy×ó$~vl-AúT’†ZúB·Ë 7ÍW45_’Õ­fÍ—tÔ±˜ÎµnX%ú¾™bìL×YÏ{ÁH€awö€-YtÏòåÆóíÙV^JšØ$ŠÖqðj»èš§Óßȳ\>8AEuÕô¹]Oc(ƒHþ_šW &¸*—x5ÁE»v¥ÐykÚÁmê“ÖÔÆÓuU؉¢¿(őگ~C(*`•N‚8?7QæŽX9y2.êgàT¼¸»ˆ¼MAôsCëÙ½Ò-]?l™Ö¸Ü‰s¶0­è•ÕßdÍ’ñIHÑ~îøGŒÏvʰ!Mà&&™DÜBÜWìjâöÖíç¤À¹sùéÕ™ò­¡/;„•@nú š¨â‡ê¤CæZõ^ü+û-hþk€®hJ-ê§V Ù68ÏO¦¢bâYîæŽ²𬛛-›F&½µÚÉ Sœ8öGŽ;ütµlèº×Õ¤Þ75S/E‘ÁÜuÍd9É@ý×ü£¥b‰=Zž‘˜1MC‚7"ËÌÃM|xò>š ×ÁŽÀH¿·gæ$Ù jÉ0xo=‡á‹3Ñ%ßħö‚Ä›Ö,á°§fz0\’ÇÆÈõCÛõÕ¹“,1UE0kîÀ ».ˆtÍÃŽˆ¾1%Cz/oi?ožôbj¸çt8?XJ‰ÑìH Ü›ÏÍ«aÕ×÷/\ºJÓ0¸üÙ|†¨ò òfæX“š;ZqºoÆ…o—ApêàÓÝ1›ëQ¤x49‰Î(~~/h2^Æ5ÖIÐÝ›‘ªz˜°¶Žý1­¹¹ö÷¢Œ¶l¯6™Í´;ãÁ®ì%—jýõ¢”ŠûA—sÒ6SOOÌß– ©ÍLg±­$LÒ—Ø*¶•Ð`QÝjYŒüÄ”4´Ó*0ƇÊhaº¬LƒoE©±³kúªv=ð‰M½£=—6/®Á Ã"Ñ0U({µ› Éö‰žé ­IUüWnÙmyˆ>?š,§)ÁüTìèÊŸSæ±éìØ¯œIÈ¡s:ŠxvÙ¬§Ï#ͱùäã%A¶3Kõ‚%1C¢Ñ%`ÍûCsE¢ëé/\ >º5³‹ªhÓt ™¯ãzº/¯:ƒÎßëöІé!LzˆÃq«]hÏí4#×&WÛþÕÙ‰il»hT2ϳù1™“¶¬ÕãìZbƒ†«mµz/è† ¡øZ‘Âû‘oðôTõ}×?äoB'ú´KzáÚ㼸'ýðÒ8cïÎq¶U³ëÎÐpeŠ ”‚Ö¸ƒRÆÜ*·òéO_Ñù üxp—`ÄßøEüý§·h’WU‹dýགX'‰ŠF~M9N‰'?¨WîJØËWÁ¢$[x-IõÙ\вWˆøj’»œæï(ϯ Õ|›CcÕnÌ0t›ñÑÞœŠ {º ‘ä~ÞetþgðA-‹Í…EŸÜ²˜ÎC$ïXÀ·îØðî*ôbÓWN*}Ž O‡}²ÈÝš¥T›,ßÑËïÌËdˆHÅæÉ︣‘M¥?uÏ {Á‡nÇÙ9‘»Ûž!Zü½ ÈEé&ªm£h‘bùÅa8ú7[cmËát˜½pŸ!6cöç¨6ÌÃVûkPÁ äÏ‹ÅËhcwÄ Ës™éLÛWr>g%ðO+juëî>hÑ­ ‡éãlê¢÷Ž'ëØRW{ÓMRÿކôæÝ Ðù|è+ŸyÅt7ÍOà‚ÍÒ‹YBÄ‹C˺ì¹±¬na A/ˆkš—ý±30ƒ${21àeaäçe<Ý÷ô§à&]²*úêo7gÿÄŸÿÿa€Ëendstream endobj 18 0 obj 5134 endobj 22 0 obj <> stream xœZY’ÛFýïSÔ_ƒvBv;æC–¥qOÈnÔ;B= EÐXÔ¢bŽ E‡š#Ì æemÙòØ¡Y$X•ËË—/þ>gý1¯÷O^¥lÛ_l{ñÛW_2ó×zϾ¹Å}p»¹Ð¿á,,ÍC?ËÙíþÂ{ñòéâö× žúy–gxà¶¼àaä§œÝ>\¼ñ~~qý÷Ï_ÝyünÁ^ÔÅ‚ÇÞÃǦ”£Ÿþëöa.|óË“ÇéÜ'¯8äç1™°ŒðŸiΖaBOúŠo^]?Ánº]ðÌ»yuýô¥:v²O/¹Pç';yI ?àÁúB_ð@˜ûûbEßô ÏüLd\ø‚ž§ûºJn˜\ð.Ç‘÷¾ØjÉÚ Ûµêbwtúy˜š¼‡ßéä%‚«Óc?¢þ²x˜®å~ì zãéXí«ín`+ÉÆ^–þb‹½ë}±­Ɇ]1°c;²]¡l˜®I?ÉCëD¬ðÞá'Ó8‹ççŽz;Éž=yöå—¬oÇn-Ùº-%Û´r#)ìOm`?KTƽ¾ÝKvèÚmWìYSìeÉÞ?|8²;ïaW­wÊÊ}qdm§þjÚŒž‡FD‰Ÿ(ùÜœ ‹g1Êý,åÎb{wW ƒlîW¬hJºH¥:‰‘1=+ô³’õ²èÖ»ªÙ’Wø×zÄGí^(ü8'÷ò0ÓfŒu#»bUÕÕPÉ^õ­ri]4ìã{$Bî‘'ˆ€ý€ht=“ͺ›‰Ä÷ì쌻…â~å@–­ˆ-}úÏ?šàÚMIÌ‘Û,ˆ­›žNbÕ³aÚ®*ê+v­'~”G—u­n>œÃêEßû ]—‹8ðƒ )zcO‘+ØOMõ~YWo ö5ê"A‡é d?å ñ{ó±äþŠõ#PQôìeÕŒï¯ØÍA6ß¼þöŠò}±¾yÍ~Ññáqè+Ä%  Ë4TN^oT\ç8…ÛUëúqUV\#Ç9uPC:€ã7ó®Ž'ö¦¦x<$Y!P SEei¤cÕŽuIÀ_«úÈú¡èP°€9ÜÑÀ±ð<öÞì¡jJÍ<ÃÂæûÁd îqøã¶lùßUÑÄÜ™´&VÃo ýh‚—SÈûò„gb $¹¡ÏSü(ÏígÅX¨ŠaÀmýZTUQ?Hl[âdP'-¼-ða¤ Õ„¹®úXñТ&ÀOUØR§2@™h9°Ä:Ï‹F·Ý/ÒÈ»¯eß_žà }'±y»üÕù–ù xb9u®y»@:%@$pÑi?:ÙÃÏž†d5HëN|¥¹4'fKÆï÷yÓìöoFÆéçÉ1‘Y&TÕÈÜÓg–‡¶j†+ÅUMQ‘ˆ\](^å Õ(vUœÀš­d͸_á:DáDê© $ÏDÞó%DÁ¥=ŽûXK;ˆåP· ýGMBŸ¢û®ÏéxÀ?üÈÎUáÂr?f4f±aÚþ-<>£m?‹c‹´wRÃ0ËbMOhv¨o¼ºZˆ,Åf^³RÖºç`íŠõ[#.ø¬#Ê¡WÍ­œÅT蔲}‹“UªÆˆ¢Žª€—QwªÌP*¡„·œØG@ÊÜÍWà J<‰\…á&Š+enÝŒÍz¨TxQ+% Sè#<¢¢ƒnª$‹ ;£>PÜt­Àñ¹UÇ3‰€Òu4ýG °©»Ÿ†#0Ö¼Õ1Q ¯ó¢R~ÇúW$C@ª± ‹ÿbºd~y]hzfô`àߴݾ¨‰ñ@=1Þç°ÁCŽ‹O°<Âù"4àѬzè)AÉŒrïO•+¯–¦ÎÑhÞ¤­:Qß«Ð[zö±ë‡¯Yµ±ÚhnP WjaêtF=WFIäd†=¾Úãð’ X5¾SÐ8Ç©Üf´?̳%A>fHÏ4Œ ŽÕãaA c¯íޒ”û“{„ºu vmF ò%Os%?]Lë‹ ?ªZÅ¡ÎQ‘3ù xöƒÒ®u Ôí¹H2´eTM.+ʪ?Ô`J|H¶ôà°aëàjMvC¶kp¢DÃ4µªÎ$>Kí"Da íÝnÆ å;±1x, ¼+}M ð±õ›ûA®U,³2üÓ§}Õœ¡2IÐÓį̀8ÏE6ͦV¹›Çq‘ªzŸ]«²sÈ4{°¢à˜IýL‚ƶºË"ŸL‘>ÒéÁL§ðýÐmWVMAbÆõƒ ›WÔpôÐöèšg@ñ˜ˆGNfìgÃ⟥Ær]Pß©ßbžW@W®LT£€4Ëz©Ö,Ę=«Û ¨ÞšÌ§JÀQL‹ö–r~}Â…ã¾f+»vìß*†&qÉ}¥¾ \Ê}{Ú˜—%NÕˆJï¦ c°´u‰~½æ X­XQ½¶WÅ’ú"·µR¶–$ÔºÃÐRÜ`d,lDÀ7‰Vå#Q'*åKæË®£i¢Ø‚R0N½T l×à 飒ñ¼Œ…oR¡6U¯iŒQ¨“˜ÂqþÑ&²M/²*iÉ}m[ײí£6ºŒw“<Èü4tà!ç”Xñö{‚òw7ô\”ùH\ÑþŒ6aäݘ!]DÆ 5ÜÏd–÷í§›âOIb7 ‡þ«'OJYƒ bÒÖqîùëvÿD sriDj~u½ÀêúÿžÞ“ÓˆhgËuh:F ÇwR-¤ÉgïdzÜÅ?µ$É3ï]©ÒY²ñLœÈ`¯j6ÔRµ†hØéiÄSŸnew¯F"= ½`S¡Kí¦ÁD°ÄMàûÍÑju©Öê3èUF†šÑµüÅå…º³À5äT˜EÎÍz]ô°Iõz;Ã?(IM®™FÿËVaT9hs”G±c0IôJxÕ¢¬ Á8Õ¢É­× y½#8C½@o¶ã.ME§IäÀ]Ùš€a$ÿñú(Ö|z`>¢»;UGÓzZ(tl¤=JÕWœù¡ãú‡õ\<¤Al¯ ¡´leß\žüäœ'V~ºgLgö (û¶ךgÃBŒó³áé(i+«ÖLÀddåTû%„X‘z¾n¬èú‰¡U›ºœÑf };Á’™'A›3žçÍž±§ÉAv`I4µ2jÔù¯g®øÀòÓ0rqðÔ‰~…»ÂBy¶áQÛ’8R JâØUÓC•°_iÔ{+”0ÚqEаQZïÂÄj#›’JPy@Õž(Yõ2nö!úÐÍ4%>ùB/N¸à$©÷3‘º>g=Ï)ÏR§zíq­Y3êÐÂÚwl[¶Â”¦²¡×ij—6[uœi½!0¸VÒW³l£«æét§Þ¶5pK¯LýºƒÀ¼™«›Óòni{Z¶0HoШü$ž¶èæj‡ã©…FZk¶ÛÇz *3±åjW”‡9®¡‘(î0ˆ¼Mu2Ç&y2mTs­8ÐÆ¡Â;@•Q)çgè½në½ÐÓI i6Ó–B´¥öý™iB w+åãlô“¸ñÌÞF_Oóš^']± EèÓ˜rÒ“>}2k•ueuœYà n¶“ó•$¼róâ®ê¿R7Ä”—ç°NqWé5[¨Ø­ßgÃC 43OÍÕ˜•[ÀåvìA¢Ÿ¨‘Ån‚0žŽqR›É²ÚNYî(І>ªÄ°&´A<;Úg\oŠ?d³©ÔcaÌ)÷µ’}JûÀª.†ú]CoÚ@FëºÓDQñ‘¾`3¡ ¦ÂvyµX//mЪf]J¢hd¥ét£T !vœ™/ À~™õ fw"¨Z}š^q&ŠxÝIJÂw·ß¿Ä,a—¡(2úÝ©h2cw4¹mÆZ½qÐŒ ã³àœ±ÍN¸×L¦j¾ŒƒÀ»Õ­Z]%”Qh(%«ôšfEFíZÈc2Ñ© ^)1ÆÖ¾Q'o æ»=ïæÇÛë›^ŸéÔémÓç¡ r=ªÞØM㜠 „äFD @E¤5Xq-º¶F×C Ñý½‡ÆÍ fB¶f¸Y˜ù¬‡–]šXY Å3i vt2n5ÖÈHõdzD¡ÈìÍNVýn–^NÝÆ²£Ò=ji ôa"óÍâ?O0iÌø:É(¥S;¦ýÃ’^1Å%H¸6¼6VýxP[jµà%ý[t¥û#Bõyÿب«‡~¼y}ý pxÝ÷£dé•™ò´àæ\ ï·_¼ñDÀCöd“îd÷ zÿqçÝÿ4(ñÅžµÍe€²<ùÊ€ü#t'E%ºaŒ†dÝ(/}fÀúŽÓé­%7˜`ußÚHè%áßø £9©‰ÓW¶#4Ö²,ú‰~ªâ¹fIÏþ„v”ÀOŸÎDzšø¡óB?m^NÕŧªhgÛ»E±À܈¶Ó;‹yc͹kû³l]ŒƒF戉œ|Æ^V«NÉ1Ùh…òJB#/ŸÐ[ÒKßÍXÔ6KšýfcE$¦¡ãþÞ¥ =dêto¼M}Šë2cêmU9²× h¦«AÍñØ…Õ{¦ƒ3#ñÅ´þ+à¡‘îJ¼Ëb^•©{¡e‡&5®˜ºC e‹Š^«˜üµ.%ZÒ™+{cú£ˆqzOý'£«4™óË^ÉÈg(m"ˆ—$¼¯éý©Z®ñ(ö…›¸ŠµÔÞÓKa»” Ìy¨‹—· NìGQÄÏo4  }¸{'¶5/«"~Úhý(6‹µ˜1üLs>m]H Ù•"=j6D[Ië›{³ â0·p¹_.iŸõ·wjt£^UÔ£´/ºr:b}‘p•uû›K0}ûI–yÝý¬>ˆuÝÚþ^kÖv‰XáoÎ×1³ÊÍܤƒöT¿&¹2š¼±uo\/ÖH‘¯S’zÇ¡^¤¨˜d®µ…Ýz%­Ï ˆÚÙi€Ñ2ñ9òk3kÂ×Ôÿ3Áf6Ÿ£-,sº~q¶K€H‹\ „á¾Ç~×hËd]túvÓûï@(ü¯¹æ³»/CdCBĤG¾w}•¿i›öéÓNÖ‡SÏ”šI¢ÿ#¬y»i!‘:8œr+›õûÍCÇÐ 3õuA]X¢ é£ç·ÿÄŸÿF°ÙSendstream endobj 23 0 obj 3990 endobj 28 0 obj <> stream xœ…ZÛ’ÛÆ}߯˜Ò‹°).ƒ;¬ÊƒlI‰R.'±7åÑUÁ! ‹h\–¢¿aó)úÇœžž€\).=H»ÌôtŸîsº¡ßEàKÐówu¸¹ÿ1Ûþ&Û›ßo¤~(Ì_ÕA|û€9ýâasÃïH‘…"+"?/ÄÃáÆ{÷ýëÛ‡ßndæy‘cÁÃúFF±ŸIñpºùàýüîýoÞþ¸ôäòV¼Û—·2ñNOÍZu‚^ýåá7QúæÍ‹å´ïý20çßE¶-Ä]”꥟w¼ÀÚ—fŸv-= ýDhãÂΊ¥wêqØoc?à°a§ÞOü@Æ©ÙD4ãaG•ÍZ(ý,È"ïS=ô¾Ù2'8[`ʾî‡nÜ«þË> ý ‹9@ßc¥>}PÝ Ú·…_Y;š^ÛVbIWo·0f3vXÝÁ 2A晟Çù´k»~*u£]· ÍëN¬Õ†ÜSŽûAtuÿQìy‡; ‘E~–™8=*§Â¬Ø<Ø/´;°'-¸‹¢À/‚\ÜÉP?¦SŽ¡Ÿ¦.¶[¥?i3º¦n¶¸mÝTûqMÿ&|÷ó[Q¯U3ÔOª[z¸üBÔQûº*W{E¿(÷{1”«»^Ë®ÔÚ¿½K‚ÑɽëH¾›µÃ˜KÒT#­ì”8võ¡ìêýY4åAõ¢Ýˆc;Ðá8á|·.ø»{¸¼©È•½†aˆ0Ë(swK3½ãxÕD 6têØv0͹šœåÎð»V·¡á™ÇºR³KOù[ÁÉ`´zà~­‘œ+\ DþIÀãýP:„ôï¾Y.ç~µŒË8ËŠ©u½z³\Ví ‚/ÈO´0EºGÙlßœï§]HÇ¢<¯ø2Œ'¾Œ)J+E(_0¸NìYà‰r›Á\ö\q*„Å%«Z‚$F”I¡ òÿ«uâ¹Iê´Œ·n‡uÝ=ç¼ ×&oh¦Qo»á8íZd7+Ë•r ÚÖ çÐ ÿéVpº ÎrÅy¾±\½ªõB !*Æ]ÀBÝ•™)4ÁÄnçf®`°$´¡I$ËU{žA1ÂAÊ&òã(ž–¦–Œ(>UÛ ]»'Ùl*P¨+P&¡±CWæ‚UN‘A` 2€S‹e[÷„:¿lîIÚ¯nCR2qá5*äA %½c <àMÒÐ|¶Ý¡dÒH¢ÄSÇ#m£Ÿ¶cÇ•}VåYSõÀ|ó§½\ÓjáóÅF.Èc/½çùâïh躊ÜK/¡W/dèr?ãõ„TÀ{]÷šO‘$¼ÐæÈóÂ÷Šóa¥vìŽÁpn[Žëc b]ÓrÁ 8òehE×…Ó7°¸±]] mž“´EýïŸg|v,‡j÷WÓµ‡fQ̆¨ÎXãºêÝ“éGç›ÚÀívç]íIÝÉ‹¯ïiãC#8ÈÌnou¿¬Œ'eŒhÝÐ^d5!TO[ˆ±Ù.ì{Ȇ¶AN1È]=ôÀ…O17êdf!}íš9ëÎî7•ÓT>a¥.ú}ÕÕ+EHÛ¸­/E@#[/ʈ;Ók!ЧÐë%¶1Ä™¦hSèèòº<Áñ2ÕmõÑþÄ Òý˜—­ÚmS MMSç¨Jœõµ·1ÈÊg5;öXprbZÓw„ £Æ Áß~øxA»’:Á–7÷ãÀU—ÍÝmœÑU3odApcç‡ñD¼aa&(.ÍĤ§ ñ5ˆ›ÞÄÛàgèê“»Ítp„R;]ëÃ\ÐN}„Š<ÔÃ//HWè›#;Â`bäwÜLR7äÚ$  2Z±Ñ÷ãÁ¢gpQØV‡¬”jxBBýak•kOáË#xä:|UÙLÓ‘h2 Ñ2°+÷¨Œ–¸OÕ²¤î:åf\ýQUpëüOª¿‡\§ÓÒ3“£Øž1Z*·ì|š¼™B‰eÒÆ—__£EÐà Cˆ¬Ù²9­ïH™f†vvT ¿’Ó\ä*qt䉃ZÉg‰óÁkêÛ)ÁÖÍ0Ct é([ "iÛÙÉã”ö4» ®:ôØ‚ºSNÀÆÓDó­eìÊ {à Š]»˜D¬ª‘““ã ?wý–+1è,ý<Ÿ•˜¸0éþdÆ Ü&‘À˜¬çñ‰ Ž[!ØØ™dª]‰ mU£h6wµÕS×> ÑT+ÙÊo]Oc:Æ<&Æ_™dQ‹m³ÂŒ"¥CSÿgl¡ƒÝ„ìiLœsæF”4É7>͹1uQòÎzz¨^y…³ëГ~$×艒ȡ'â xÏËíAÿÈ">HÁÎæÔOe5°Î “s½'¤ºã8oQ»ûä¾Ìriýç¯ãñ¨º{߀ˆ ¬±¾àŽàJ•³v.ˆÍœ¹*{(uغƒ.TOŸXWYÆ<Ï[Ko¹½/îuÖ& ,ê´þI„yMhÝXNöª›Í¼¹ ¢ÂUÍ Ž¨Hý”U¥ŽÄáKäÁ-i¥0›>¹õ©|¯ ’ÐòAÌ# ßmÎ Pmgžùqæ ›vŽØÙ̉ :æåyyûê+IŽæ”Û/ÅÚí «òi¬ÂwIè*2}vžÞ2Å.¨!M¨ñ¤ ¶=™K×z0#Ë(VåDÔiΓ)Á‚¢¦«xâ3S¥Y¤•NζªÆŽfÂê¡ik瞺ðiž­µ®q< P®ÚË‹i@–¸úbN o\P…ˆMVèVÒM%sS@‘ëÉW¦’ù4;S‡…A>DC>¾ý”ÑMC~çŽ|˜DÄɽ@qý©²* .õÚ—†6LsvÖ–êwgú8½C‹ºŸ/ADºØÐ5³Üw¤¾ùðG¼±ûÒ€®€|óæbdÛÛ+%žÑ§°å²i‡Ëމ¾:ci8Ï8-1ŸÉTdý$­b˜]œ¾Ÿ¸(·ÄBùÕ5ä> stream xœYënÛFýï§x˜^X,gxGÑ©›l³Òn"l Ø „¡F[ŠTHʲÞÁû(~Ç=ßÜH*î¶p€Øâp滞s¾Ñøœôcþ/wß|HÙ¦¿ØæâËW™ù¯Ü±ï—XÑËõ…~‡³T°4ý,gËÝ…÷æÝ«ëåo<õó,ϰ`¹ºàaä§œ-wÞ/oÞ¾ÿáõ‡{ß_³7uqÍcïøÔ¬dÇèÕÿ,ÿyæÂ7oΖӾß|à9江æl&´4 ý½²–åP5öc5ôlhÙU¿¯‹½,8[p¡ö}~®šýaè•­ Ž[¾Ã‡o¯¯&b_mÄÇm«^÷c¶,/xì‡<æÙQ= Ôò2Ï̓¦>±õ¡1mC¶ÅÀÚÏCQ5lU [w펵° ZI<•lßµ›®Ø}‹?ªžuß²^Â…]ÕÔ’ÎX MÊ€0à~nm{Ór_ è‘~tçÕõˆr$"öÚ@…VÙ)?Nœþ×aM}ì±…EÅjfƒ2!öyhÓkl´aè,ðêïÌæÂlžùQö½_ÏŽ…ŸÇØv¡S‚%‹ÝÙ27;ØŒ îgάÀ ]…±Úv¬«úßÙY@3á'Q’ŸE4§·_ŒiŽ˜Âk]A ±YÚUmǪ¦¬=’ߨ¶êªüëEé——”å²hØg©k!`÷Þ§ë4Ĺ÷>5­2õJ}’E‘w…~A9Çj+¢Ô¹9Òû´+«…r+L…ÈÕz Ï:Õfߪª[Éõ5 ÊE’yÅ¡¬â¾ÚVɬÖ(O¹oûj¨¦UG~üëªXØ'cbŸßÌSg› Y Smñ-kÚAM²U M}Tt’ÕÕïÊð4N<‰VCh(’ÊržÄ~’„㆙*2šÍ­Vé°$y±–'™G=˜mzŸÝºN6C}2•BO°OîÇAj7ºÜF™/xj35ÚC°“…E ¬)vRÓB ùñ£(ËÆ™Ž&áÇ º°,½œÐ¸“EOÎnuãò@ٶ튪iWõ=h[‡šƒ² ë L&xÕnßvCÑ ¾%hÝÝP•”¦nÆŒ–R…!Ϧéf=iÆ$O¬õÞ¬çh»¿­äS#Jý@Sõ—E]“í]{ØlÇ6Ý·Uƒêשã1²¾_­Æ^[~UG¢tˆ0GP¡E¬j*3#¨´QMå¸7œi¶Ýí@E_4÷DÄÝ¡ÀP'¤Ê#æF>°¦à`"±¢ØÊï÷Ýx?¿bËi”&é[¾þðþüôDh<©@[ç§!Rbôó/c«©æÄˆ#]pÊŸH|w’°Bˆc5lÙ LÈ{¡pTÀ…Îòã YnW åÖ@U'1©òÌÛÀ0ó7ëqß P a?è"n Ûs-ÃW§„²Ú© m€òÎgJ4£,lÕùêþXìö5±KkZ>L;êHãмv‹²mh ¡‰œô¦YQ .oy=?¸Qš@ü8v=ù ¥d,©·Ñ ¡Ÿ"%„9’æòùx;:û¹Ý`§ŽÑr|â*À새\“É^% -åŽqR³¢Ý+ þo±Ñâ!Fð³dŽÁØI/‘³=þbEÏ6ÈW-§lƒL¿Œ“äO‡£"r#(Nçm‡*Ñ‘™N”e[vâïùv6J&Á|”„Ñ ÃäÈœ–„ÎåXD–…õ1¬9ì>C{Ý{pç(A4….Ú'#`uÕ¸L¯Äøš•E¹¥20c¦D+Nwx½6’‡~2™¦’@ cÊ5É>Íæî’ŒÅjE+ÈHdFkÇs“Á²îÕ{OÙÜõƒ¦Qs¤ëè81Õ?ªM¼^è—i‚šíÌï¯iÄŠ!k³TXø‡B^j¨^4ЪÚÎnš¾~;ìö¤Áú½,«§R‚nо©Ž¹Éë Ãk5Ù¡g®hjÌba¦±6tC1PÓÂ;ªm! î½þ€à«4µ$Zh‰N-xªÉ±E¶†6•…nns’MÏ“¨ âóû€iO±9«ø4òç„°A>ó[‘òOJY¼t-RÎú~|@˜ ¢À5=µ´ õ#dåKÿf¬­öÓ ¸h§‘®Å‹b—¨éËoö˜$š¡*j`‚‰Q¢ r?°XìÇæõ£Ï¾7>DŠ—xf¥µwZMÛQ8ÍëiœB^ýœÙ¤Æhg>êÏ´SŠYH$.@Á¬ÜO³óY½§¯*L €î±×Ž×ê.'Œ!õ ¾¿Ó‘›Y6û‡9aÚÜUbS®ÿìh&i5Ê¡»JHŠbŸ¦=¹Z<(à#¬/êµìíÇMÖ Õ•FŒ/tý¦©³TÂd…Aj=â¥n­€ Ž_þýΣŽê±Pe²u =Úw-MaÊÝE@WÂ{;艪¨Ýh¦5äkjoDŽÅtÜœÜxaTÝX¯ ¶•]>ví¬` Pдënm¯w¼aëiM€Ðl]›‘zÖÎQ;R:éaì‹©nÉâÔÌylGòYÝj‹ ¢-HZ¨¯Ž'm3[Bo¨{õJd‹ø81"Ö]PhAaè@ãfá$æSaX¶8 -ÒXÑ4tb²¡Y³7š'°’‡£ø¹FÎçç/‡JŠžŸÉVR#Ê-½Fc[f÷üåYpíT”Γ¦ò]Û0¢—õZëJ´JÝPó¸¯ ÌÙmçŽ •NÐfN™ø—SI–ånà ˆ|SÕòÒÖ3X•HõFÓ%äcÓú<Ñþ^¾CË»w&ܨu}’hδN1£éå°£ˆ[À¾U´ãv3LhâEvÔµ!(ï†]¾;ã2ŒåâÏ®´Èn »µ;å¥ëÑ8óïõæS»ËGÁ§W8ZßÞ{Á"¾a1D‡T²”é·…Ñå9AïxwËsçH£3O÷­‚wRⳌùò ¤mÄ “ÔŽÎS$´ss”ŒÎÌ‚×Þ{$ÛªäTë®Ù"AD¢É=ˆµ“æñì(9Ýäùå/ ùS¨WÛ´ÚHs ãú£ÂEN*|¢óQÊZ«·úË­ì©h$ 4wÞ©º†P‘­ýøã«…ˆˆ~k*MÍi¤3¹Ç‚¦×#•XÛà|éj`£Òݤ·»¢ªuÁTľ(åù)Ïàrê8*ŒÜ•éçéì…ã•©=UÊܾkgûa€ËFeó‡±2õ“¨¯V\ófš3£€ FñP¿Þ³•@HÊ»ñµ.H­û”¤.¥ÀPµ©Hm·Zéxoõå1Mµ?Ÿ À›ðÆ5t˜ê7þyôͤêÌ#-èkhMÀu"u`€Ïm‚ÔãWûŽAdêq„†q€ÓG¯—ÿÂÏÿ¨UÂùendstream endobj 34 0 obj 3221 endobj 38 0 obj <> stream xœ•XÛŽÛF}×W4æÅ0bؼ3‹<$°öb’ÝØòúÁ^ ©5j›"e69òø’Oñ?‘òx,`±/u9uêTdQÈYDÿìßÍañÃ˂ݪEÄn\döÏæÀ~YcAI?¬w ³‡³"fE•„eÅÖ‡Epuýórý~Á‹°*« ÖÛOÒ°àl}Z¼ Þ\½øíé³—ïþnÉ®šzɳàôg»=£­ÿ]ÿs‘Tqhwž-§sW ÇY[%9}Ì¡ûZí™T¬Û±a/ئk±ÄªÌÒàÓÀN{Ñ2Ñnº­Ø²Z±×ë«UêË~xÉ#ëÐ*Ø*.q7Ýüå˶ê®mîµ?9ý|ŸŸ.ŸÌ‚GÖЧ]û„ÆaÆÖ›E…I^Uöã°¥O}àQ—·¤:6õ½6z/j BÝnÙ®ëÑÓ}Çž,±;Â×ÓQU‡81¨›®½e'9ìÙ—/G)6tL ÁÞjÐW‘cLJ4»N›Ç æYX…a?Z|y×W‹¶ê1¸êæn¦<ŠÍ‡·A¨ÍÕÝ8Çrð|ýë5“­à7%?)y86pC(> TØSçæÉÃAleMdãJ~;=/ܪæžmmÔ÷{lÏ3Çc ¯p‰{ï=*Ã(xî<¢Xž–p3âiÔr`c;ÈF;)Úí»åCëy…Urf¼’ím#ÙZë_}ÓzÆyaþÔÚ®£E{mÖÀ§¨k€xç]×3Qoöäk¸\åqæe¼Vb76ú«D©ôõf4›îp”M=È®ÕðXã~èºF…Ú¼G ¦;Èaa0õµQXÆÆ‰aÃBºS¶°â ¯ƒYÃ…"X’ñß8ÚkTÜöB)¬…»jÐÿלB ¨/™ê9í„æ‰ÀeÛ …”?qÏR”—ãª`¸›ƒ8J|­Ö= #ŽH.Ù öÝ 6%GdýÚS3B ,h¨2 u[7÷ þ õ‡eE4•dP!ó2,²³ ë’>§¤ß¿OI *6ù;Rª’¸tyÊ3›( 65Ôèæ©BÙÈP„—`V týÙO/Ø Ø$Fi|ª‘dj …TÚsç¥Òþ‚ÒÃ$Š ¶"¨YNn;å5ÇÜ[ÄCôýQŠxƃ®_&n.y°jL扯ÈÅ4Åï>ÉwÂû^… ’ŸÚÍO×Ïþóìú+#"QR9y˜–&>/Å0ö-«YÛµŸEß!,;Í Q‘u£‡}@/µ&u{B˜ˆ¦Öˆ$Ò¡|Qe}5Ãê½¼Å:m®/Û,’ÕY¾0y­J‹°Äsm°«½kh’è6™³;ØÊ*1wë± JuÄw°¢‘°Ö{í ™)J>­LŒßwôÒh‹^µ6P{ò¶íz±¥bÞâ*1ÅÜ5n6u ¸º&‘?êØ²]™Œåq'e2…»¨´xÆN£ÐP}RRqVŽ!‹Êbö¶7U›^‡K&ÔQldÝ€øÿûnd‡ºÿÀ>´Ý2¶(=µ«îpNTªˆZ/æ¤ò£ué"´pµ{óâĆåµõ=tɉ꺊bà ¥T{0¶HœWü IX$‰Ad\zD¾ š NP"IÐݘÿåe vŽØaŠ-¾Y$6µì›{ &0âˆ:…k)á+Ó½¼P¦Á/Äj»©“ ‚FþC>U¨)ˬ½†ºb‘q„Çê¦<¯ÙwÁЄùŽrŠ7 kÊs?>¬cÀj¢µçz¿‚nÅA´šábî¡‹V©qíÊ9&jþûr¶þÉ^ÛË+ZÎk £ˆîѼò÷fæ|O“:븛MNŽ}ǰâ´ÿB!¬DhVs^Xã.0(´«eAˆ‰‹àa(sÓˆæ} éêí#îe0Ò‹ï‡BOò,÷© SSÿ×8Ð(Q›Œ]ߨՙF#êþL~¨nì7‚xõvP¡‘æ£ 5q êÍ,8IM-²oqÎìi÷•ñ)ŸMØåÜ|t–™è¥ 8{•™PÔÜ;‡Ed•“ö­‡ra($.”ØŒ½î‘©Zu­"ù¶* 7 úÐÖšÚH+µ†JH©NqÔHJl®•þ}?ì;­0PÓ‘¡oްOZýb tƒ§XÔn¤[Kp”›¸`š°“,L³Â…¤ÞȦZÊ0ÇLj¸ôåiq÷Å Ðþ+gÙB éÌU<Ì\C *mÃo`v#£Ô@”î ( Bs9Ò:×£2jy¯"zBÁt¤€"Ö5Ä)w^±Š^‹:@ÌÄî’ʱî¹›ÚtBä•N$|ñ0ÊJÇ—r™á^eÁN9š5 ¡ä©oë…«˜Z!ùUß11Qæ+vf´+‚k9ºe7úŽê+Î]Ó¾< !Ù> stream xœ•YÛrãÆ|×WLùE`,b13¸Ú•‡õZkoj³vlº—”ˆŠˆ@€@ÑÌ7¬?Åÿ˜>sZ¹ä”ª´+\æÒ§OŸ>ƒ_XrÑýw½¿xõCÆîû‹ˆÝ_ürÁõMfÿYïÙW+<Ó…Õö¼ÃY&XVÈ0/Øj¼}ÿz±úÏÏÂ"/r<°Ú\p‡g«ÓÅMðÏ·ï>|}ýÃmÀoìm].xœ>6Õ1zõß«¿]ÈB„öÍÙã4îRrŒU°¥Lé~DƒM¹WW¬l6¬«úV+ý$v•°Õú"ÍÃ(- ;ࣾÑ"XbloÔ!Ýxõìþ–<ÉCL³9–C¼Ù•]¹°ÔëfÝnªæÞ¼âœ-¹ÐÒΦ2âfŠ(Ì nÇNõǽêÙ°+üRl=Πì ìÜ;ÖŸûAíÙ±ÇÃUÏʺoÿèy<³awg ›Þ®Š‡2IôÌ øµVìc­z½÷, Ó4vÈ_?ê Da‘FÂ^S «¶˜¸¢U4—ôŸ¤„f’†2OÜ“Ãz„™ó0ÊR{ƒ–&´]§ÖÈå°îذ߈a‰ØAtª†ûþ<ìÚ† Úr¯XÓ6ËuÛlÛn_ •ê5i­4ŒòÔíÕ0£ÝXó¦Å;«ö`ÔÛµê{ªjð®Uk¥1[½¿Xýå&ø¶]ZI&ƒ“28> ‰º˜Z>áfü ¥°W‘ëetØ¥+¢+!3ÇÉíÙK&Y֠”?¼2±Y— »S¬¤­ÞÕj.–I‚œâ{< Êfè5N&ï8–/¦©3aWoØÐ‚s.«h2CRÅ„Séo ™sîõK10ã ã4Öcƒ«#q{vPÝŒ¨Ïlm¸QŸ hEªÁå2 Å8ôÕ<ËAÔ4‘/fyw>íTµ˜¿Ë0æñ<¦ã¼óšÁßk»·n‚]{¼ßY<±Mcžc¡¢œÑHch³j"4湤ác6`&o˃“X¸@ú1Y"»s2ŠÐ…TˆÍx @ÈVà =cYŒÜ“öÒǤ'°%YÈ'Å0°ÙÁŸÀv4ÕBäq˜ÛAc`–U„ɘK@pžÜÈÐAiÂó8 ~Hú²ëv¿WDÝ6tš;·Ž+«†OÑ̲e¤æºEJ XiU öå5½]„a³#}WW^¸ äÖGWðÔçVáʪî)užÙ…ÁcµQ¤ÑÛcÍîØQdip¬êaY5úé*k“ÖD¥½–*ü¾ô…Nß6ËD5Ÿæ2ö ê0.Ýú3Ír YÞ7þúó,³×ÏQ²™ ÞÀ[+#O ìKy²b„Èq…®´Ç·ªÑµ ŒEw+Uƒ·üŒ…#fÿÂzá<‰Œ³l†ÙÅMðSSA>Õ׊~_wÝ"¦UÅ$ø‚]‡í2¿dtoMUáÒ_OÈX¯7ÀØËI=2 Å X†ºd¶=ê.b‰¿¿À…Ee]m0Q3TͱÔwé=ßd–<‹@ƒwâ]yC4ù 1JeÒºþ‰È£ñ‹RµZƒñ5K¨Ê­›‰’J(+¤ÓÇ®ìÓb,am²~œ´@ŽfÉ “Ò ÂÔzãäF?fÓ–\Nu¬?ÿ.M›8ˆù”§©f·ˆ@„Ü…¦/=ªBÆŠ`øÚ›éõôXÖ¦j.%J4/¼¢Ë­¡ÕX?é^µ©2m9HGз­)‡©õ.Øë˜.HÒ™ ºbpüZîµÒÁ¤ºïÊ=û¬"pQg"žñàñ3çT´gµÐϽV#Â_Šø >ú¸Æ7d@•Íjež…ñ„\Û=XgBíD>j\(ÒIÕ5å{ßîmìvå ¢F-ŸÌ’}íQ±IŒÐEñ¨ÎnäfŠ˜éYôOFçQÆâ¹á½’ž’â;ǃ‹¬14Ê(È4w¼½ºóó;ò,¦[×Qóv>Ú‡È=œ½©¨•  ¸õÕ Zô¡%ë ;æ—‰.C‘Í|[…Ø >Áe#EŸ6MŒ­JæPQ>*ÒÝ7£ÁzØÑšÜ_‘È\. Ro™ˆó®œ³®ÈÁ‰©k›¦lAÑÕÌIG»‡þuòTT¶Éá@éãq,ó*ÆÚÁ”³w:­à[óÉtY`kZÀwFµ7ngƒÑ•Èü´z»Ì§´‡UÒ AnlÞÿ@ \›§eœø†èxP ½ª·_ºÚ¶1’tÅöeãUOè¥Î¦ž>’1uìÙ¦êIÏËn‘Xçx!zN†ej}épbq3%( mËC㸖ÇuËÏjlE P$y\‡ß„:ÞZizeÞ{ÿúÃ7xY¯*]X©¬õ1GZ&qa´½mÈy2ÝÇZRí«èìì3°2%€ÙÏö!™å#cÝ@Þ‚¾ÿyõíwÞ}wýáÍw_¿Ã†v¾9ZýÉt§ð±™' f>¬G·ó°ZJb]cª†kS@Áb”¸€Â{é…*5‘=è7¾œË‘™ u!œÓÕ`[Tëf˜úˆ„‡.wL| ãÚîlÚÎöˆžÈü¯{¸r.Xd$Aï>IF.°ùBKù¤{Ãîy_”¶?ÂköÇ5LöÕTB"<Ï'ŸEÅÝî C=+H°5©:žZÀת¤6plÛˆ¢QzÞƒžŸt»H ×·Å8d$ܰZŸ…ÖM骰HŒ!ô¨®ÿõúïß¿¿þq~,%S¯¾ ›sß:‹õ¸dyFÌm=ó:.]Âuç±k­uÌ„ubQèxpœ†…È~ÐV.x±?1-yhÈß<š"éúVlurQÂpêA±ßæ1ƒÿpQ-O³Ævr#,CTaŠæÑ;\ù®?—ɘMÂL¬{Pí ?…¡ šXŽíïéq¥¡ˆªX\ûІÑÝ+dxiMJl6y4‘gZ£å›yX]YR·çNS@Ìê«ûÆXª“9ÅÚ§#8‘Åîîi§cدÆ.½¶ÚTª¥-ƒ '7`ìÍ“c1žS~å/%jÝ´„*]^b4°ÅtîRucóehmŸôžºë¿böì³±ËE#Šå¢~h´¼(YùÔöYˆv–S–ıî·FA5Ò|˼åÝH»¶z^Lìò jž©]@²eÕ^êö废eµi’òÔhKëçÌñÉ¡W:¨›à·ÒNôêØw¯únŽñ`ý ¯]J¤í“®,&f‘AᤧiÈ@Øo^½ùüs[`ØTtDG¢n§ògÐÛ£wa/ ±wîa:­ÕÄ¥sÖàÞq}ìújq9ñHFš//ö[RZ×çÛŌҡí{È@3ïhêm{l6ÚÈP<øê ÞnÜ¢)õðì¡3Ù¦‡ê“´¿këj¾yй`H/ 8¹b~6x›4 Eß%ìá~?”1Çt˜¦ ›O¾7PƘüýwbú¤¡uêÿôÚB$¥—jY8/K +‰òcAàIü'ŽHQ÷¯¥á“³)¬¾€KlM¾¨ô´•@„õKÓkgS¯S3~L=ëFuå]UëïO?òÓ@6»ŸhSìµ8tÎ2¾Dþû€ÃÉ Tˆ­> stream xœ­YÛn#Ç}çWtô²#[ìî¹ûÁ€³ÄÁ&½Dü ðˆŠ“‹v.â2È'ì~ÊþcNõm†”%p @8ÓÕÕuNUj~d>̧?ó¹®/NØ]¿ðÙÝâãB¨‡Ì|¬köÇ^Hé‹Õv¡×–H–dO3¶ªÞÛw?\®þ± ÏÒ,Å «ÍB!O[í×Þ/oüëë7?ßxâæ’½­òKyûÏͦè-ýuõçEInV½Nv_þ,|³ÿ2H`6cË ¦W}²ï}ɱ¯_›‚,ép«õ"N¸ïòÔ3Ÿd<²44ºò®i;z(yD%Ön]Q»u"â2Î2óà°);íŸ Ï2Jyd[ ©üãòðͧ¼.›‚åUņ]Á^½|õí·ìsUô¬lÔ70U¬‡¶;°šÌ²¼Ù°rèY?ÞÚGeÑ_áõu5nÊæŽ¹“*—ƒPò8;:)TU¦ÓY›a:ŒÏ£ÔæÁNÛ bÄ vþküväIw.…ï¶m;¦bF~˜¬Û ý«ë¢z®0ãûl)Sòhsغ`ü8ˆôª ŸŒäQÕNc×a“YÈ6­¢_ yÔh©Žý¾a7Þ»¾< YH`Êì)vÌ"víU‡›Ë+HWÜ·Ý PT!ÁÑ_½ÿ;…£Î~¹ŒdÄx«]‰‡½ ÂR¤ fs&Á‰*¬t8¦b¶Ña­Y¹e‡vd{„šû"Œ½GZ¶;¼ß±û®]}Ͼäʼ R‡‘É9Øõ¡u|Ûq¸6öT«Öm[õ*vékïÆëÇõŽå=ÛäC@ë*ʶÑ+o.ùiJžö§×šÊçÁõ³cp'æ›@·MuPçëaÌ+|ÝâNxÖ s)%—"¶˜û™ÆüÎK wENÎÍmÛ’­z€È,uŒãUÀýX{…Àá°Œ°¤ÁÀ!ìNQ¬j›§0«ó»-æb;V„ Ùb¿/Á<¼/ïqÙÊ*•,´y“Wí•Ýmª#¡Þ¯/Q†];ÞífÜÙˆ·ù­ Øm1Ða×»¶\:EñÖ:ï Š,ö0(Êø +¿¾Bx‘—m5Ö à¦Øé@™5Ç¥áë{õ:¬** ˆí=ñ¥Çv r¥ocv¿¸Œ ¹;‹–¢ÜiˆþëZòÓë÷¯ž£\…)G¯wz„ž!Á"‹³wÕ¹ª€ ÓYS ‚ª¬:ËѦµô#ŒûLöH‰L•‘ã’©Tord ¡©3 0¡Gs ü`*!Bdj²²Å)(îºBiØX3Ö·E׳¼+œ%½³´}iË…°¸—-•[¨¨.©.¤ Li_Œ…cl‹B5¥/ÔÛ5´Ç%èÁôzÞ >Že1às7Ôõ‹¶ŠOƒ©ß³î’TGHOÇÓ{ÆúcàÄiôîÈô=ro3"ÑòF5"ìõŽ:P’Ð^«o®½?­þòÎä* `—"„×2ñ€ÕVS• ytxDòTJ×Ï’Tyþ¾»µé·(¿+¨å²þÐEM¼³\¿¸<êyKkÔÄ{ÛÚç©Ñ¡°ü𺻙(JÉ„!>‰0Ù‰ÝB÷¹±*µž}m›ÍgmVÌ…I“ïP;êònG ‹ˆhX•f~£?[O†™¹D ¤VΔý£F%£„S{J‡XšõÖs¡Ã!¸m®çõ#R¶*{@p´6ˆ ¯žŸ®¤Ä7üz½ûõDMfi¦&C?~Ä^¾Vä»#ö>Id:ÒÎåKë=¸ˆ¯ bÛ¼ÐÏô2LºÙ|;ÒØÖ­Üè‡|{¢·Ñ-(WN}âXizt)Šš;('Nr[=ý%8ù¢»7Ôs—JT“,<7Jpõ€îX Ê™ˆ!z§{‹,宜ˆÁGl üýòi¶mÊíöiÖ¬JƒßC\P8&é ÃßCŒ&‹QùeÛÎ8Oä$­o¾êl¦ô»öØDÌÃØJtoí‡iäê]lÍØnÂ:áqîD±Pg_ÀÿG["ñ4å ³Ê †VþWZõÐSPGý™üʤ–_gˆdÔ€‡ÆŒ¡Œ—‘à‘[?ífZ2ªá†¨‰¦1³^$1O¢ÀîºoçY;ÞZ}ò›Z‹ÒN6¿a\¦üò“ÀÛ¿Ðs8'-¨KvàÂöâa^ð'Œ€«¦èòÛ²*‡R³)gu»)?[ýcÑLÍj}ݵw]^_‘À8 gÿEöüdfÒ@ÏJtt½5€¤»íÚZëðŠrNwÜ4 O:®ña¦R¡ø?I+ê!±\œÑ(÷ù€– )’¢FÂ+ÖÈ"®¿ågň¯@z~º}jvÅ.h ás¥©:hÂÐ(A„á"ð}›~W·ó\§Ù&6ãÀh&03‘ʜ冋¼¹C¤¡nóÍÆ@-’T>*MyÉu’-óûûªÄB ʦ&¯ÍrätB!ôÒ^9 Öån:(T_ìÛÉïÚswÊjwøPp91ú±8ˆiÝ€ Z¯¸+>±‹W¿¼ÁÙüéÏø‚õw?I½õ˳`;Œjëì˜Hæ8²§MT à˜yë“8^¹pìËqEMx"] Ï÷󆹑hòG—x¡ø¡ÔÚ ¥† •4„{+J”¯κÛÚv¶jP(g{üÐÓV 8 6Ë( o¤Øü\jdô11¸á(פ€Áù•.—"ÕVKeùl÷DØÁý³Š·9Ý¡ê[DÊ{=Ó+éì€Wµ$.¡ÏAêý ‚™¬H­‰yG¢·éwÊšD’"1 bÆ®I¹Sôź…“æÂ1Él~²d%£kƒ²D«=–i@÷<Ç}ª i?;÷ ÉhÝ©ºž;âyŽ…ÏlF. ,‡ûr ½~Ðr¦lúS?4I³¹ ‡É”8f°Ç!ñÄ`?够ºÔHÿfãM¼"+)Ý”‹#Z9Ë)vJê£ ³Ì"™,K ØØ8¶IiÙ¦&?ÝbF0’}[êG¢Ì×ìüåíïÞÐ-`¾øb~JªŠ º£·€Í9 GÄν³ˆ%‰|’”¡pç.k“Nbi6“§z&ŸÒcùÑ\^MWYª&èEÕÝ"Ïo/€ô#›;HòïØõØú¢ ($´”©° ’™]ÕÙ]ŽDoS©2žÍR„JºÌ¥"Héa/íHûîW¹|K·ÇîE8ê5&w¨‘DÓpÑû`VÙÐ}$ja¡uXšzwFmë • :§°Q¤—Rãìoú×»[ögDkÝT«ãt$ý0M:gÀ¶V<‘©ªFÿ9%É…t––èã5zsIuÅ.¾ûƒFJ„ wMÖ5{ôx§Û–öfë{Í($-%Ó2 ¸¹•«´%('YäTFóŸwB}¥‹ÕÙ¼{?ÜwLÂiõ8 ¹´›§¾z³Zü„¿Sº%endstream endobj 49 0 obj 2938 endobj 53 0 obj <> stream xœ­ZÛrÜÆ}çWLñÅX… cfpµŸYª(å8™©”‹ÌˆÅ’0±ÀR›o_òùÇœž+Ê®T¥ôÀ­]`¦§ûôéÓ=ú…E!gý3«ÃÅ×2v?^Dìþâ— ®~dæOu`¼Æ9}q½¿Ðïp– –2Ì v}¸Þ}ÿzsýóÏÂ"/r–!¼°[*Ï+‹âˆ‡qœ³-j.{̦c§~Ø¡|Üð(Œ¢Lõ§¶f·A9^±±<);D˜(Óe cIpUǦa!mœ‚±žw½Ý¡mõñÕ 8^&#šúrY‡/ ë•_5€.o7WŒVQ‘æq!S}›¢$,»à¯6 ‰‰·ý¥|ö·J¸‹Îehðp’—R`T9:æ™öÕûŽ•mK&ŒÀG9Ö#ùŒuu½c¥̾(<b³ÜbêÉêÐ\Ð’Õ…H"|Œ¯=72ã6Ô1ÏU¨Ûr›»ÖóŠ=?4Õ;¶ecêŸó­HÓ0DÖáF˜›idýFÀ¼BdÁs‡ÀtæíHX:ÀPzeçâ>&±zª½0HK{‚ñÁ÷­t {Ô%œ02íŸ~¢Ï“J7¶~nw8W·ŸáÜfºbÍø²âë<2Œ´å2 E¶ð0þýÏûŽérz ‘!kñô÷ÁOýæ+ò~j,ähÁ\ùä;ϧÊñeÇ:C-úe!È5&ÇæUÜr‹êàŸ=m™'EPM?#H»fjº{‘ñÔÔÚ4JâüEÚ*<Æ@Îõ8·Ón¶I ø<¸^sWwÉvÍ€œFE]­‘™ÄÁljÀò­µ Ì-Z`²ás¬ñÃÙÇ¡Vø!x?©C=PÀÌŽÃ%¬R‹òL‚Ã2ëˈ ½äsCç¾+«G:<­øi•1tДàœöí5Ìnsô9Foö6é¹âxÁÁÉÎ%px1äp„ÏœBRž¹¸<ÿ }òA‹ä’(¡ˆ¤&Vòä< u7!G``¿'Á†h V\Ä.™›êñÓGc‰"ô‚D¤KÕóå·äªíÇÚJ}V«|¶R/Õ©:Šrs¾©bV Ù{SL"¡Ÿ 2‚ý@借[ƒ=ï”±ˆz,œûæ½&†H{” ã"Yü“¨%@%d:Òu·ØMÅMÑ;Ò¡÷g°|ê²®YõPv÷õα;«‡ ÚŒT’J]Q Ñûy>)s fôsÊ‘{µu9 h3(q›6d?©Ÿ¡`ÜÆî ï‡rU*_)D?÷„8ùgÈæÐñŠ-)T˜4E¢èØxLSËBDÿn«(×,?›zî9Õ,”Ày<µN­|ƒDlù¢ï¦²éÀµ: 9òž•«1yy«G!7¥áÝÕ¬¼CPú¾«÷Jf ' ý-‰QŒº¦‰ÞÉœþð¹Q¦™…(¢‚ÝtÕ…ÀÌ2qV­F”ÑBש'µ/QE[‹ÀÇÑÐŒ ]¤Y’@שèó*Õ¡–UÕìØeËvåT2d⨪ǪڈˆÅV×¼ù¾óµ]új÷ê½½œvy$›÷ÆŠ'`¤«e5š²æÊ­³dWZèÑOš­!©ˆ­©tò_¥ª"ãiœj³,¦jç„ÀåýPÙ¡ßi+£ èýÕ¡¦¤kƃ+ÂdDÜgOÔ׿[g_n2ç¹Fâ)µ¬u'X×D':=+é-õòê°`B‚µ¤KÊœ¦¬Užkpâr<Ùé/aŸ©£OÒS§øË¡£…õ8–÷õxåP;©ÒÙÖ&œÂˆÚ,Ì,HžJ/¢|…6B(WTewµ¦­O5ˆ%ú8v¿€ÀHHú™Ð&JYÅÒFI„©ygY²@± AÅ‚'°.rM`ë|øë~‚Dñ÷ÃK"MˆÚµC%5…ÉïÒT~ú–² ­×%*!ÊvM–^Â3~I‘¯üg.½—“š®‡J¼4O¤® s7õsõ\½Â•¤eÓžAÖc}‡|À¯_­Ki…_²Û,‰ZêY•†™‹Ú²­ØóPÃûݽò|N(•®§øS¯´uT É:«(öÒépã!üæ ’)zLJZ$-ÐDœZ íO«Öæs“oHKh€C™“W&µuõ[±çd£±•œÙ¥NècYMM;:vìG´ }GÙSj™í£íú‰ µÃÙÚ ¤¿ãßÁ¬ˆTÅÑ€ÃjUI™£KJeòHODÚ­&£\Àmgµš¬íçé8«LWm»>ÎÒï fpV4ÜÜ?â}UªsREÁ2 U¿·T™MíÓ¸ Å’ ǺjPÐá‡O÷ó Ö Mä•|ÚÊ¸à ‰¢ò¦ºâ\÷Ìëâr4™ÒÉ£8MŒ©™Kï+gѱüvë/Ûê‰ËeT±ÂÍ#vô¡ùH1NŠ:V±<©SÅVD‹a2„=®X íZ!ÅbHf ÙûÒU$Ùùòbjd¶^NRí²IWŸ¾@îw}9ìØm0oÍ㌞ò¤l|û㛳59¼%þ¿´(j‘±ìv²×£™ú‘„\ðñÔváÐn4Ï2™næWÚ«Ídâûz{Ù‡·×ÿð+÷ 'Õ‘]jÐÃ!¶†^j4KbŠXZ®¸Fñ=*¸KÕÅ8öUûÉvS 5ÅZëŽjÚ»$¢î}½ÃiLb‡“_Ð;9+m&¥sãM°»Ca‰‚Óä ÐQ.EŸšâ„|g«ÙÑøe5Úr~žxã*«e’T¾ e¦¯ynK¥ІNÎrª±JO´ª]z†¸?+Œ¼@«(Ö…Ñ™³†èà)½˜†7^ÓNMym›Âf£*RrƒŠ^ª ÖˆcÙðõ²îJ+w$|ôç›[£K |³t =°¿9ë×´—¿? ¾a!xgé¶( ¯_Ýh²²Hm;Á>æ2 iêYsC¨$¿Û\'ªÒƱPÅØˆ@à@4cµÓZÒ…TJEÁHšO}ߪI tÏ®­ŠD†„΋…uL¥Ò㢚JäÎi·,öe…´ÔÙöX¥?R-5DVÜ¡~:îËÍ{ëa]I86K«Ù£ÍŒS9Í”‚8ÇA×ð®ŸlŠén7¢ßÖTCC¾„ʺÅʦ%´¢§múi¢$Œ‹ó»ŠC]v¦eõgsZVôð5¨×zçLzJ ÚIËÈê¡k*4%àÄúë Ïf Ÿˆeö¶ŒáEæÆðI(õ6D¿§D®<¢†þ–b1À ú?“GX9^†¤¿)ܦkúYRKkf¨°½ï§~«`De<4ÆšÕ`Tˆ¬øIß•ÀñŸÙlÐ]¶øUÛÐ5ÑÃÅ">o=ÿÒƒ¶®TÔDírçÝX Þ4ÀØõÝW«{cA'R¦Î÷§ðîòŒì!›Q»MózŽiÚu…¢n¶ Ç mÐ@Ä¿Zvvð~¯†+æ:¬eæ³ßsús÷‘šÝO•™ŒÞ|@(u>´™íi¯ü¼+uÇ …`zfCë¦Ëׯ/Üœæ?À‡j(¶ê®ã:2[‚ižFǺӄ”Ñ7JüEyaܯDo’¸šcv»!_Ññ›½ntáÑ÷ªÄ;åД¤U²µW) mJk"[ 5c üxÜ–4Ü» ÉÁÕH˜(Æ]Ä~i$L¶j×K¦º…š{«ì|èíá•“¨«wyäßìª'œSί” Ót¹ ŽåH,ƒ–Ò6_®›CCDn ú¤´$é©Ô =ë£;×y0^2—G8}æn3ȵM®2ùó«´4ÿÏkš÷h®îtO;öÝÒhV€zz± Xµm<6}Ûm¤»Áò¶èJœÞï¿{;ÞnÖ­ÆÒ¬l¹j]±ygï AÅ‹ºnžiä. •NãÒV4>ìHœéѾúÊ_QÈåÿyŒãËTÔ xÇv¾ßBÖ›Ž7GUD ’§$wÉÒVe §¡„}“§PMf\n:´X£-c±ºy}˜ˆx®~†Zæ\}õöúâoø÷_bƒF©endstream endobj 54 0 obj 3949 endobj 58 0 obj <> stream xœZË’ÛF²Ý÷WÀЏ!ÐÁFãý°V²ÜšÑ\=<=ZH7Bh°ØÄhlš³­üÏ÷dfUlµl‡–L•ï“'³ø«ã{ãÓ?úÏjwqõ6sn‡ ß¹½øõ"à/ýGµs~\áœ>Xm.äÀÉB'+"//œÕîÂ}þòébõï‹ óмÈñÀj}D±—ÎêxñÁ}ÿüÅ럮ß~tƒ çyS.‚Ä=~iתwèÕÿ[ýã"*BO¿yö8{õ6 …¼"!.cü5+œË(¥§}ñìÍ«Wo^;ﯟþïëëwïœë׿¼º~ûtQÄ^‘f±»zo?ºÏÞ_ãL8Ù„s.ƒuö —óV[å<ëv»®uÞ/rßóƒ8uUù¹UÃà\·‡ê˱ƷúL§œO‹,ƃQæ~*M×ïÊÆiêatºÞY×=^ö'§Û8•œ¦OCD'TA<‹œ;”ô¥Ï_žò9É Y^_mëQUã¡WKg­†ú¶]¦µ"KëݾQ;ÕŽâ«T£Êµ3vŽbÉqâå™øÛ¾éê±¼i”¶3ô|?ž¢ä©DeP0¬OÎÝ¡i›º©ÇZ žç-.Ó ÷’"u«^•£bYƒêïÄ¿^JgÀ 4õ²\;%ôeÂ_†^’¦Ö •u¼D6³¡O"úH›²½=”·ŠbNî¨úú¦noµ÷<K«¿•4» ŠÂ‹ c¬Ž¥kæ3áîã®U«ð‚Ô´ÂÜí8®ª£òvõØ+¯ëAîÞ^•7Ýa¼Ú°ÀÁ6ï°ʳ_½í¸k>.<ç9§^½tܵ­½³ë`CÝrjspñ/²XÂ0å<,˜PD¡{ëk $`mŠr'{8A½4òm¦Åa(R5L ‡ý¾ëGÊqE"²]SÉu›E˜P²î—ª.›æDß^¢r÷Ð %bÃ$õâ8NØì¿×£Ž×žÌÁé§}]ñ)u[5$téôªQR(Èe˜žŸYØpïÊyHPH±‘”¥‘ØÑŽœd\ 'kTPýEqï‘;-,§"?n‚0òá€Ïm' ždÈÝh’+•zl© n¾aGDÅDÁ?@"3Þ_{ú˜€‰©8LE=ïtæÒ ¨(8;ðCýe¯&`ÁKy( 4–ήlÏ^O/É2“ß§nALóÐÝŒlµ'ð26 å"?n8¡`¾}õ€<ÆaænT/u# SÆù)#¿{ ?1|â‡p¬–,‡“ü¥Í¿)>TôŸXë0EaÅFä§›E€@~h¥ã¯FúeìÇ^ZL¾¯º½6=J5$GSÕŸŽ“çÐW“¤°zGŒn=nQãNµUÕgŸú?ŠZMÝîããó£á›4ˆ”"õ cBù¹œ7µgM9 uåüxª#Tƒ=ÎÁX´Zô-‹Fªÿ½³N?>–:Ì@L:h}ޤ€çE{¦$ HCÕrs–¹ÈžÈŸ|`ÎQGgÂlÄ7Ê¿öSIEÄ@†ÎDÆñ”¾QáäSMuÛ™‚½+OTMÔÕÕ=íè“3]øûêÕKTá”S6Cg0dp¶b|LZ˜€îU?êVèåS qxûy ²5¹¶V_ÚZjÛ‘`§Yá0Å»™Ñ×€ù««·×ÆŸ1š‹=]#ù¸pHcò³È-O¢žt›<,±ê,?+u¼’¤¶œËãœ'$S fCˆpéÅ;¥FcÒå›Ãˆ´„·~=Ô=³Á”UeS{ð¥oêÄfv TB¨áµTrЮÜï)ç©)êÄÕ(®Ú[5B'‰C£|„€IsØ•ƒç¬\œx qUë„<ÓµN¤4CEµ8Z_ìö}‡²@æRnükç/ ·lê5wÇ'Pø @×Ù#z9ÍÒ¥AèG]µtë`? µŽâU¡ÅÈyú=ŒfÛCºgs´ à°ˆ¥A(L…EÀ´,²ÞõÝñËõš‹véüNರS µÝÕæiŒ s‚EÍÀ>` Øv’)؈œ¦(‰µE"ôÝZë×­ ñÕ»§¯ßÁð½å¡$ôÁý?>L¹›å„l–2é½½ÂarŠ&ÒžgNÛO¡ž« JL*âÒœfºÝ+iô{¬Á:°Íà8ùŸ óöµaª£Š8ÖÈa$…0Ÿ=¦y-ø %Fvæ°WUý¥’bb÷ÔÃÜ- ²<Šä× Uºï1¯ˆÂ¢’ûÄbÞÚ ˆ`REq† ÝîNÍkÆê©WiÁ(b?ÄtÊ|w¤þ¸숸øB;’éG,àÒñÌÅhù»k?ÄÓ;gÜZˆN¹'O•ÒoMW c61Ý¡YÏØ1\§‰=:a¤S‰Ä¾Â°¸["_êFÉT Í:‚pæh`â4ôN¢ Ñþ V"T7š XN©c(£„³z‰Ô*0U 3B:«Åcó79Ó´)÷~ŠJè…Y^˜ñpèš;ÉSý"Ábj€jœ7† -lÆ"3Yé¨>ë]àLÎc.JØ„–¨ÚŠ¹Û”¤Jö <òÎ%⣧nj›,šfå¬Ð\ñ»â‡µ+-§ÙAF( ð<ëÜ(jžTÉŠ‡ªM×4BãsäojÇÞ¬ÈtâHG(Gß=¢ÁM„.A?½_6¶„4 @bÛhÏ– 36q]Ó€Bh€Ô !:ëÏ`‡¹ÙfHQE¦2évá4¹¸}y¯±s‹ é/NmÉù1LS‰ÝO í¢†S;–¿‡$<ÝôÝŽk–vdIljöN>ÈrTÚ@­:ð¢à U+ž•Y6I'™ÅêÞ1P2ÌÞ_JáDq†¯ÂÙZ2”7@0Á•ùgeÎîbk¨l5ëÍb.Æ0Šà$šžKZ³Wûr„àvÐå†nÍô×}Ìæ«+SÔÐ{8¶bêÆŠªQ¯9oÔ=œÅ,¹¿ Ì?~|¶£¬U"0ì1u:Ïmu9-tÑÀœ†– ju¼ûJ#juº¡™äÒ›”+DY 5ÖÍ¡!6²J+¾’zyNm,Äcö½åî¡»ð"¼ôô&ßdÚ5÷§ó™ÙT>°x¶èÌíØfˆÚoä/´Å²9 <0tÍÂGZ«ÈŒ¶(–¼ŠŸ¦­G½Û!9˜“™þlD-ôŽ•÷R³äL>ÓZÚ\®Ðö‰¯Üh‹i™}a6VLÅx 5k®¢â¡mêÏ ZAûqæ*!*­‚w§Ãžfm©r],Z†íF¸>Ð0­u«ÄS{zBb4NàsjheóÓ>Yú à<1¤oÜš½ž&„…%Ñ—!/û{ïœÙÜ”¡¼&¢mðYµÝáv{6;ì^}i•1Ôm‰nµæZkî±Ij~ExÆ'­Âç|²™(?Hoœç¦Œ5[Òô•–"Áä±B‡E(…Y¾&JMÚk‡ÒÜÑ Kkc/–Vº|Ù10¦MÏ›Èuãæ|E=ÌÆ7䬴Znð‡±#g‰ìÃ@a´+?kþBW†fÒѤ“.,-¶_­p©/¬ïxYÕ–0tÓuxà—57õbù»ž˜³'Û´Ó(˜ÎŒÅ¾Ÿ¹i˜íÏ|÷·ï»”Æ@U)D›–+TO½Ñ½xônŠî©;8(yGöȈTî4âi¾8y6ä—òùŸÝ^ÑnÎõhk¼¡’c¾ˆ4¤”d©çd\_U†¾ðˆ$÷`¦}œ§,ÆðW#¼yž²­m|s%5L`7÷Æ# Æ(Á?Y|’…‚Ub_Õ%ÌçªùLf/ß;&PƒŒ¤G}%¦A·©e±bµÕkï˜2nÖ½ó ÖËÓz½Ô+ r¶•Ë&À½{d³û¼9™)y 8»g%R'nàR®)Gð©ÑéÄmÀdûÙô*ô%ö‹i–ñCÓ hûw_Ϻ5we1º]fnu²Ô®Ðf!µ–РI¢¦]Á º,oÐ &ñå`–ôBºî ÅŒä%N³}HèEæúN#VBËËvÍL—;#޲÷µKíÓ­ iaK24¿D˜vXÒ‹j”PRk E.Z ˆB7Àk绹 F©g÷!? ¯ã84ó*ˆr»ý¹C |ÿ8Òs é§ñ¤³#ëd÷¾¤Tá%‰Á;÷v¾»fªŒõY"&4÷ØÍÀdDôŒÈ²Bæ-ÌÚžmøß9Z·ÎJªl˜7—ÑDoÙë¾?ÜüH]ðíö½MOšct6 xm#v|eã·¯!È QËñË삘šA8S\®²×“Ò¤‡ÂC$œ,DzpCÂeÆ*´àôÞŒU|]G‹´Ö¡µ&ØTyƒZ#VLå’bf§îf€4EMqûC5ʸZ•4ä säLΓ(á®@)çGËŸùÛ;TPÓÉo ð-ŠÏ†1ŽÝã¯Bç§gÕCR52ufÛØð±î‘ •qð£+8]N+DÍ+ͳ³?ÛLëq|°GÄ¡—ÄiñçúD.×A/é1}úÞü~iêiö÷*îãÝûòÀ–yÙÓÅ*ª¦itkp>%ÿÑ•ÉÇÅôÍ9ÿÅœ’ø®\]ýð««<ž®®ØC÷ß go¾¬wµþÉﳦɕ㶥AÎÏ· YRWÔŸ~â#NDevAÿ³Wð¢³ZDúf¢/ÏÁ/ŠrÏüV䛾G9 eóx‘¡}q@—ôÓvªg$è¿rÇ`ïÓÄná²|fâku{xä?ÖÌw4aTº6#/÷òÍ;þÅ á*I=Ä"È’IŽ´ýO³'_´ÿV•þµœ~ZGWfS˜“%ßëkB”/]~æ‚4Ažžq‡˜3ÏO§ßÓIâ<Ý÷´ÂÈùë®4šºOŸ]¯.þ‰þqŸ[°endstream endobj 59 0 obj 4450 endobj 63 0 obj <> stream xœYÛnÜF}×Wô ehÞÉvžlÇÂj‘l¼¶‚`a-V§g†/c^<ž oûê|ŠÿqOõ¤,; °¥!»«N:u™wÌs}æÑýoQŸ}û:e»þÌc»³wg¾ü銚=¿Æýâz{¦ÞñY°”‡nÆÙu}æ\þðìüú×3?uyÆ3ÏÙ¢n»{>nσØÙâˆ'g‡¼Í€'¤©~À®Z¸óú‰¾5ðž\°¾ÅyeÏð·ß·tÀ±ayÏ´]ùV? ¯èœ5\Xû ܆oáÕ:‰=sÜSeCï‚Tò¢=È×7f×ü÷Ü4ÖˆŽ‰'O°s®>xëÀÍvØ‹½(îËfÇÞ”¿ rõª9à×7Îíy9·/ª¼ïËBûíz^Ê;zPáGž9¢û£Uöxs\§!‚EÎêæü‰vFé]J>wÉÛDwxê¿ëNä…´<é óü¬0zÊ~nжº¶ªÄ†]žÃmžÅ‘Óvu>°7ˆz³Sv=|™Û«fò²d7YâG‰rt4¬Hbƒç‘â* uº_äcõ€Ï¨ït9C¬z"é‹SÝ$ú08í){ùA]sG£¤+N6¢}Ÿƒ“¯ºÒ‚÷¾¬%ÑNôù)ê…âôó®½?÷=G e¿p/Æ|ãsù‰á‘ÓC»ƒ_{°äYµk;˜Wk÷¸—Mî-óÓs#/ò3L‚§ rSŒÌ)ò\‡Îx>ö’¨{$݆2¸»B(µ#+&$ë±ÊC%$|L¸;÷pIÂ̵÷>‚—qBÆ2ô¡§6–¾™bº^jbiêüïº8~³’9Èá yWŸˆp¯\vµ• \ž†&p@Âúœ[Ô@“ ’ï=æ™RIìJ²DŸvû»4Á¦·‹34s> ^Qá \db“‹Â—fú!§­ë¼Ù°ªl„D÷XVNR&ˆ^#àå»J(Ùˆ2™×b]™G‘£y£Š Šl˜e„al仨oú2{VÎðZz¾µšj&‰väôÃd5:Õ4›ž"Kʃ`ý©¾k«›sÉYÏ‘ªŽ²nWAà åUžÔGŽP߈¼+öù€îÄ»±ìɳ«ò>A P‚LÅ,Íd”®¶VÇv-ô»œgnþYRïÑÜ .b)1R¼>VâB}Bl¾„\±Hœ0CB¦÷Bšƒi“ç­³A 9 óSDúç 3hF'†-Mùa]•÷‹ƒ‚ħ–­‰e¾ï†¸Ãж_kÚ‚;i:Ñ6㊶ƒ¨*Vâ»Iø_W,tOZ±B7äÑ#Š•ÏMò“Èô=÷¹Ît°Í¯ÛOB¦„=Í7Þ#f¥öý$|PÚÇ®÷ë(umw8ù‰À!7ûb†HvòÑÔC¯˜øÓ³¡¢þn®e<ž´Œê?z^Í3+•žìÛµ½—­ñ#Tº“Z;ê^ãŒçV»òªq¡™”JÖæ/± }{k_Žç‚áü!±ænWx¬ºJkÁþŠÞ´˜ô4ÔQ,íÇ8Úñfuœ‹è¼Ká±ìRœvD‡¡³¦m 5ûrÐélŠ=¥«Ô›bÓÚªzä"2ñ&C”†nj"é+&¦ž%xh½Ëh$É¡~›%faê»Yö€ö (A¦3¤ŸåÐLØbg8ÎäØW2ãYÑTÐHL4>‰ŠJ±¶W•ÁÕ·©Z¿–Õa&XγjÞ–Ä™÷Y[Q’#T²ÞtU(C$…$òÒÏ|@GÝ«¢C¥8ı›³Ã笩Úö¾'Ê£ÁÐr·¥IËv9ùrM]¥Eê«'TâtJôO$¨ÝX‰^cÎéâ,ÊÜl’´eÚi¦y¨ŸÒþ%$˜Ñ‹D‰u%ЏJfY!éÊž-öߟSTîÓ¼¼lõÌÙÖ4Þ Š&ü×ô>± 3•\÷˜(ÊaNîCËÕ½ý…¼q#¶ ¡~àähX‡±éYÆŠH–!Ì)_”Ïû-¸sÁ¨î/Æ />’?ÈüØ5D¸çˆ!rD#bºx”M¾Fü)74/}Uä…aOÑd%Ô }Ð#êVÏGÚ8Hl³‚†@–¡Æ ¬4Ð`Æî€ÜèíR'¯Ð5Цw°~«:é膖| ô£*Ååñ¨ó=¥P&¦7 0TIW“¯©l'ƒ? BèÆž¢®.»T‰äÆ©ñÂà鉮•u$’43"ol§`Ô­Êãe®"p ö¥OzñpaÆB±:žÅ|‚UWYÛL‰·¤ Ó¯°‘£…²ý‡éa’$zŒèa’7§N·Y¨cf¡yJ@«i{$ƒ˜Åal(:¨2‹6Úù€„éÆF¾ºAl;f¥W(I¾m&NÍ…ýÎv^~,04¯·ªÔàU´f¶CqU÷«¦D —0ÛÓÔ(™îeÙŸqM³|–éY¾Q$6‘äfˆj~¹éíDŸKú"°"_1=&½8‘؉•ž²Å"ú 0dEº¨ÿß³õú!HjÝ‹ŒŒâ`âL’*j¯ßKU§Àg}.Jm•þ[«KxdÉï—ý0€›IÄ{óáçTòé•V ö„/U¨ÄöÚ>ÒW´tóÐ+ÿbA¼`¥îW¦b`“!â*tÔ¬¼æäw͆=5ì:rûð¸ê¨ìœôT—z/ ¶uVצ«mZ˜Þ´ƒÑhiW'>6æ<]¬ÍnXGvV¥ÞH®ÍéËîÆQs5¤%%$¨”\²ú2Í…FúÍ~ Œc³z¿2"ì{Rs€§sšêÑlðÏ ‹#Z†á(Dcæ¶G𢗗€]<Ôhx¿šu·0+Õøi0ôÚ²hߣ”› 21¤¼S;oÈŒÜ|BPKÅ;>T´ÇÜÊúS,T£/w*rÈI¸ë…3T "·,ýõ º˜ÌîÀ阫~m:’n>tew%Øñ/ÀOf ­î·B‰å´çóÛ$ØaJŽ„l±c`K›‡ã¾•sëФ¢´ŠN6†ãô‹là< n™•€Ï¦ T³`7PR'ʸ5l'Ñå&ùÄ €‰XdÓ£¡²x”sR¬uæ¹ÙlÇ¢¿url†©¡mÜP.Ä{`‡*´z©ó¶N˜q©xf¦àÚ¹$^R¨Ñª¯NˆLCóm,  €MúªEÙ %+´(ÿ™\ˆ£ÞVEök·ÕfÞÝfvíèäCNKˆ áÛËî@Ñ*ŽÜ(™AjZÉkTD¶ -v¨?2Üö®u®—™¡U=5Ò,¶“MÐÙi‰0vÀ»›‰Ò¢pf€yjïUÕœnøJÕ xfÇô0Φe+­vTæj4(/ɵËÁW>ßexQ¨&Û.}ÖBúK|AÜ(g}Œ¾>Ÿd9RË*ßQÛù±#m0I| ¥Ö ½ÄM§q¶¡ä®ÌE:Þ«ëzæ&qÈM³:@ZŽÈ~r#œ…Ü4sò‹& 呦%ìÛ·›)Òz¹)ÕwŒ¤Ë’ƒÚmÝ8q͆N ñfSªÕú\ùL9ˆ|;2·Íz‘nkúÌèÆ—Úeê’«“Ê_-ŸýÌM§¯ð.N âqÛÅ$:ïíòX2ƒØ C&h1m¨[iÆúNt«Å]I@£Ž+óù]<™ëDkò2§¨óØT=ëÒaˆªQOdú©ÌÀ0çO;ˆéË )]ùƒ‰K¯ê‘‚¶Ò®ÊZ÷r¾Œ‰í2†Æ 99¤ä_ر©PÝ’úïs©®º‰U§û)$È®´›ÅºœGŠ˜kª ±ùn~û•Vh¶ ,C`tÂió/šZ”Ëú,wÒeqÊG0ºöØjI â©Q³R-»eö -v[‘ê¯éãlóìбÀó3Õ ‚‘vÅåûô»—×gÿÄŸÿs6Ôendstream endobj 64 0 obj 3579 endobj 68 0 obj <> stream xœ•ZëŽÛF²þ?OÑXÀV¢Éæ}ð:qâ]'αÇð3 „¢Zw$R!)Ë:Ïà}”}ÇóUõ…”<^ï‰/Ãfwu]¾úªŠ¿‹ÀE@¿ÌŸÕþæé›Llú›@ln~¿ ù¡0T{ñç[,Èé·ëýN(2)²"òóBÜîo¼¯žÍnÿqf~‘9Ü®nÂ(ö³PÜžnî¼÷/^þüÝ÷oî½ð~&^ìÊY˜x§OÍJu‚^ýûí_n¢BúæÍ‹å´ïÓ7! ä ‰°ˆñ׬‹(åÕo¿þîÍËÛ_õJ+(.BI °8g9¼Û­§m»SâÐÖÍ Úµ¶u/†¶Ý þSlÕî ™øpÜ5ª+—õ®jÕ‹¾ÅZEgD¾Ì±qu#ÓÈO¡-ô¹¢‡=¥ŸÉ°ÐèxÉÇ—X*ñé#o’øy™%fG,Q+_üØÒYøi!íæ'>y›%|@èC öáû0¦g6+òØÁOÌÎÝ\¬Ì2©÷ˆ`êu É;“„/ùq„×ÙµÕõ¢lôŽQ^øy$­¾ï¼NÍdâAyjÅæ ìd]#ð£Dït¢}öÇ~¾6ÔÂÊMrÛëo/EÇæÙ¨ßÜlÖžÄp±ü1uZj¯®¯Wý·72ßÑõE¯ªc§àëá4+àöI”x%~:öjô«9l^•ô£þÓê^ÍY#t~HÇÀ»¥qZ)c¿H3#q¹E ü4 ŠQíÐä·§zØŠ’ÏÒÖȰs–;ïç…¦êÝ ×fa¢Ï¶ñ~YyþOZ‘ZU©9ÛyçåÔÏýÓ;ˆò ÊAl‡áÐÿééÓÕi«ÔNu³$&åÄž_µû§Zk‹C×nºrË—gŽ8Ÿ5²Èr?•EÑS`ßT†±Vú­ Ô~Ûw+¨uNîÛ~À_D¿/q½CÙqX—bWv³0÷ƒ0K½ pF[ z ‚"gK­´gº ’IæÇÅePŸEY¯¸D¥úÛôõ¦Q+²¼ÚÕûº)»ccÈ4å¨qP$e®ÃQ­Ž¹‰õþPV,õæøŒ© ^ÊŒå½ï¾ŽŸ‹L§fW+:^œ„â`¥#C8aQ8èÁÂ]ˆf´BpŸÆábvÓcŒšM£q–}1FiÕ£“‹^†(Ö§€Ü‰ ˜óa1$…¼ŒÒ{Àã`Tõ¹y4”vƒòpØ5Î(¨ ™y§Zm!&Öïêþ¡Äø¢nøù§àxØ••2AÓI$Þw5T8UÀ„ÒDÎZuä¯ÓýÏ ¤¸ºÙp@!¬TÃrSÞ[a3+ð#o²[.™ 9‚òØÏŹ= ¨¥êÉYÌØ%§#J±õñ"IŽ®×CcŽÄ¢KsÜyÛãÙÓä•0)\^1ÖzÉÀr*ÇSb?t9àÎÃKñÁíRvµÎÌH¸Y¨©p¨c}»W׺ºÏÚŠ"Þq˳hZ±Weƒ ÛíŒÅBŸq~ºQ\–ûÕå¼Â„sºÀ;öã-B?‹óIö,ØK5–;‹ ¬oRkñˆ"à6c2<”»óÿ)Q†esP"ýØ®Wµ‡ó%±’!% FL¡(ÈŽÚ;<œËœ°šC)ô¾ª;U mG¡ä®4Ú·«zÁ7áÚQ`ÅìÂÞ'„T[dOá/Î`\Ka¾wöÀüj0¿ù„õ Ç@al<^·Ýž#·aÁûšý,ÔTûDݳA§ ›‡©‘@õUÕ0ü•ÊbX8²ùcèŽÀü5GͪmžˆùFä"±c}Ãe@dbϡģuìZŒ:Ë€5!PGÌê3µè_Óí”:¾5K?nbÒTÃÜ{‰ìÛ 3eõÀÌ(ˆ3ïoË^Tm3tˆ«ö*ó¦¹Ly!Aç_gßn˜ˆ¡íTî›ÚÊP.+6KÁs{Wó@&_Fᨳ$ÊõMõuŒìçÚÆ›ÇÃM*»ýÕ%Â$ñ'œTo‰ËˆO£3?Ï3·Æë‘Øe×1-vߖ͆sCݱÂÁ\šº«ä­eIúU;Èòíåt!ÅÄ…÷ñÐö”"‰0éË€Xú¡œ„ ´Ç2r2Eâ û/wj/î=’µSDv ‹éà•uÛhþe×v¼¿#„š¶Q÷3f6ăȊd™óåZ›/fçI`5qrŽÔv€l`޲܂ò:´àf3#xHįêöØ[¯Ý—¡À3rÕê,]6º|E‰»\q6tULyÖ5*2/“‰…cº™/§(‹ƒ¥ÍÁAhË”åz€ÿXxÑפ3À^Ã>8ˆR]½6pIJ®Ú‘´jŠ´Àc€ÿ° CëG‚+Ñ.€Í:¥Ob;Ã]òÔ{¶ëÛ9i]—9Jüë_ØBrfC20å?xOÝ<ˆö0s€ÖôÇj ôïUÿ.¦/¹?"i×›P¥,pEÎtüß#Ð6îÏûe‹:Ž#†ŽÒ×+eð«îl®â{‚¶”pe–øôT ÕÓCÙ÷§•qRª_1ƒÕz};y¤¤Ü(.ús?(”4÷Þ®~˜=¡šÞ«)²º½×Sf’» Ô«‡˹Л¿`ºúéø\×9Wÿ`CåãmyA™‘jP(:p/' NA!“Ü›¦ÜÞÏ">5õ à kе" ¥GUÝ &F*hÛ貟&#HXoÚ ·crÛ“Yb‚§#=aüOÈ Ð¶há?FksMsA6 ©K™ËH™Àeñ3˜tŠÀËcrZÇ“”<]ø8tTL 6°ü¨*Cr—‘ƒÜ{VºJKÈö>ˆÉ“iù›ùSé7,ÁIE¢z"Ì岑a­:Ûí {ÑžÎá§äáPûRw( ?Ö%'xnÈIKp1eº’ıNpn)C<[ãÞiˆÍú¦"E®G¢º4®ðsËX¬!9¨n3'Gױ픃§Íe6+zî4ˬ˜<óÞƒ'tê÷#Ê…xº P8Ê N5ÃÞe&Á¨£ü+yÍë @ä~š°Ÿ:_‘¨ºã"êfÅ––óº‚æ&æô,T Aö‹lêuSÔ=ë²-§¶7C˜<6½-ë¾\qñGÔ‚j¨”2×̆DO¥ùè%Ô§ ¶-ܸW >ºœ –J<¡/QñͱœÓ=Åp>XïŸðsr kˆšÑ§l]ÃîtÝ˃K¶ø…Vchäèæb¸Èˆ™KòFTt¸4û§v”O ¨]¯]ì24\ñLÁ±iÚg´DÀUƒñýI.†­âȯñbËÕÅÚ[¨±EF3ÉIyްř®»àT+°¡«jaN1Ђf f˜¤\úZÆ “ U&zÓkçöo§y"é:é df@¨Q6-‘‘Uo«Ð» ¡b´mÝÿ°0‘gÎá¡rXÁ \»¸ª»ŸŸ7'dìî¨@ þ2©É…2'5]éR‡X+Ô¼7&ÅwMýQ¨=ð‚åÆC{  |\rÙæ~„kk¦ I4m>kåŸ7·å…feJ+×úÌÒ¦º¥þza¡:?§;ø8°.bTxöþ÷³95`¬cÈ‚#Bõ+Sç«©’¤ërÙÂùòÕ`‚(ù¡%¹ï燂nº–ïôÛ ×ñÕ²7Ä*’Ñ9½÷ÞÏbÓdà<âmœY©Ã´ Â ê«fmúÑ×ZàžéÁ]!ìtàÖ^ÍLÈ:Ž>zào—ýHOÌ&ßè.Mº¨‹ï2×ÇA ÙÐÕÕÂòoBqîöf^fè½¾ÐM¶êúS(úÊ œV»åŸßMÉ`P6¼~x{5£öu02¿š…ÓÞ!ÜTãФÆY–TäP.f§ƒù\ ÷¥ßÒæÁ-Á7¡³fª-gNÙjË7óWÈo%9ª,S½«@jCĹDp=Çñ‹)=.Yù‚ú(Ü7Å-Òøú›%”rfëÔZB p‘U¯k¦æ¸_ê ×Tú–càr•ºF ¶%l»¡žÒzø!}Iö9ºD)P)~d2>"ýlÒ°u!õ&594]ø#é|Ç<Ä|=´æO]ìn©©6Ì<²§Ää°ã¦ä€äÏ`4<Õ… \ȆTC;^éͨ„î§^•9î<9°^AøN¿ê3¼Ñô->!Oqu—¯‡Í´Q”\ nH—e“øì<§mÖ\k# ÷:§HêÒð4×_F|žS$¢gK„©vÑN\W¶`5æ{„zO=˦²ÔGwõ—DB‡šxNµmÌá)S:™…~ž¹~ÓEg6´íÁ;\øótez¼ˆç˜?Y»˜w´kà±ÈÕÎÌìüœb„Ší:áô£Ë²RFéu[Õô”¯jÊjšp W.ß‘Âh¸ 鯈ÿëÝʰ:ú€Š›k6O>Ž+¦‚aPOß™´9ätxþôùÿh{•ã«z¢ôqlZ3*TâºÉ-^£Îòº­à&Ô,«÷eGÓðV;ÿs 'YL„ilj—èË^qÙÓúÒÄwøæ»Â4Û¦_aujêØ#C½ó>–„šsÛ?b¦2† ܰ%ddÊgÖ|´ƒUŠêSúd ?’Îå.ì–»/¸¨#¾ý–ËÝr&︞›±¬þ‘&B³Ñqm"0š´Öé+´Ä~KXò›H’]iÊn©Ëî$V×Ó.f4™vÝyÜ?êݧ‘ŸÏ=.„p€ îðÃ}nf4 ”1^HßÌêÊ‹(ÜÒ 1ck·šJæ}©Šbéß~û’°/×J7ØXi² ñîÐæ"Þ3WZð0F«“>¬Acýrt„ð²$N¦ó©à«AaÑ™?;tBa®RÁÐG†’~öýíÍÿâ×ÿž|q?endstream endobj 69 0 obj 4876 endobj 73 0 obj <> stream xœZÛ’ãÆ‘}ï¯@´\5!Ü/šGhe)<²ìõôÊÓa4Q$á ‡CÃèSü>™YU(Ò=’C ͈(TeååäÉLüì…Aä…ôþss¸ûê/…·›îBow÷ó]Ä=ýÇæàý÷#”ôÃãöNÞ‰¼"öŠ* ÊÊ{<ÜùßÿðÍêñïwQTeUbÁcs%iPDÞãùîÿ×ïßüøûïþòäGO+ïû®^E™þÔ7jôèÕÿüŸ»¤ŠýæÕrÚwØ«òÖINÏà MKÚØŸ/G5½öFuƹíwÞÐ{u×y÷¿ûݽwf‘â((3Ù—Þ+ø½áÔ5^§êÆ›ü;x‡º§ÕqPÑŠÍ]‰«e…‘ç²¥‡!=ˆ¢ * ý{ÝMÊ;S;·,&TšÑ¢'ÙE”}¹ b¨'•ú,H3Þ㾞iY’Q”F·òNuÛ@èÓt„TÝÃ&€~žd°{ ÐWÞ?ÿ¹•–A\X9Àx^ <À·,¹1-˳Nã8(ÂbQ`D”‘ŽŽ‚d¹½êŽ 'Õ²òÏ*0Ø,¶(#åQ û§þ›­üÌ>{cäo«TçmGÅápšv{a«hôz%kÅÄ:˜ò<þ×;7˜q⥿ÔÌeÊ42´Awü2] DA•›ë~³Y ‡‹€öcð&,*a¶£¢ ÒÄlþO߸ÀÚÒ;ÒöÃÿ}wï7y¨@-’˜À‹€±ÁªŸ–KŽ4»±,ù;Ó•C w‚n†éIÜ·ø‡zÆ`)ˆƒñ/xÛZ Ü„óZ3‹L€X Ex¸widU& éÈe”æZ©ta¾b‹­“*EÚ¸ÍÇEP…™¥•^z«‡8· nvc=è¢ðEMÌÎSW¨ô3×_òç[7n¥³¡÷f#ÁQ ‡©e©®-(±kÖ©SZ•'fÛ=ZÞѺaˆ_Z(·ñ¢®;xy_ßæ£B§é ™ÿ*%Á9E*éu´“¶\±”Zl8.æ3¯)¨P-‹ÄûN»C$ÕUTä7F•TO íYí…éQjýЂdÆþ“&D‘T.®°ÿˆº<*ø½ëÒ2 )KåW Ó7JyGM€¬¸, ;/yŽ› *~~ÿR»àŸ¥í4PNQóY!æk4l‡ê†Å ïÙ3ï¿€nZ‚¨5’¨fä¿™½³­;M£$dj¥¼Ð”8¡L“ÅáJãpäM;%†Y=¨ñ|ª‰ë=À¦l…ªôA§švT›™i7ùŒŠ( ¨é¼Køú“¯9Nðš'üF=³@(¬ƒ<7ÐpÚIc~]º¹pŸÞ}Z]€íT·]zÌãtI+¦„N KÁ?Ôbˆ4×K­PìUÁBeÊÌiu8€Åkå…±®†"›üßù‡U½Åaæ''Qmkøýi:ÕË¿ÉÉíÄã!ù’sey©à¾0¹\ÎMBý,xs%œ0µÆì.;‹BÛƒ³%û*ñ˜h飢«€ó ::w)¨€·ËlYö¬VQ&fÂé–/âsm(~Àg¬¿ÌºÙæN³©Üð?ÎO¾$ Eu!oõ´zÐÊ©P†ÛËÐKÅU‹žÓãqTÓé l]êG`Äšµ¸¸ÞÇYJy¶@†›Ï¨ ¢LšÏBcÚÙ4d}Jër‡Õ™ŒZyÇz&Ò2!¾ey.ö@íiØ—Ú¹vŠ-ôYLr‡”CÊz©gßÞ“¿´­Düô|Qø1•hlLMoµš®4ƒšz‰3’E¦8aä6Ôæ«Îmj§8tS)o]fÿ çART7ÜGCÿk«l[Gàû<Ò$ó8œ¤f†ÁgdåÅ\«L7ótwêšF-"Óz‡4 £dg=&Ьœ€TÃ×ãX_d>!]tES£Wˆ%¸ybʬX{ ªÞy³N¿Öœš‚Ÿ»úÍ5ê×c«¿ „ä˜ÏD–ÆEËyÍŽVFæŸæO½x*éàãwT ¯ô¬K´²6'ýz… `Š£«Xé†áýÄý [·Ÿ6‹Ç¾ïFªVéÀj®ß‹A2J•Ñž)ûÚ=-?/ÃêF#ˆÑ é/ðÛÕ<¨ÒØ Õ媛…v”0 “踊¥,„/gHZ¡ŸÖ±¶Œ)tëF ¿êp x£ÑQ¾LœKE {0ï NÃÝV'.Ç=!*(:Ù#5ˆ»…šSª`ãJDŽâ¼ôu¹w”PÎÐð80ÉÀm©3L#„–!›ŒÏ<,(µÍ¥¢ÿ®‚™xå…0_9[(2gI¯†Ÿ[h㺵É(bI7©)Íî »ÆœÅ ,òƒetÅóïQYV¤’¶‘ +KÂj×ã“Ê!†ÒÁŒX­»ú¢Æk}fQ Ù«N’ePn¬÷ÃDe¶ òç¶xƒRƒ<½¢çL¬$doGŽD¯‚ïìûöçÌFCl,C!¶¿¾n†£–èj=£0f¯Ý ¶5šÌ8w=<¨&Ž/ÆÔÇ_»8ªGÛÔ³„í8àÚ¨´óRo¿÷Ѐ)Þj2`(³Ë”Qèÿú;N¶ÂYr—³˜Ù% æLŸ~KÌ0ǧNÑækjPö§Ã³Ò”KŸå1R‡¡ËG%Ü >a€®ë¸.DHwFÐʃÁñ[{_o†îtèå(@›L¥¤M“á.‰S¤…Ô£4 #L3!ì!hœòÐ…dS$väy™\®å©y#¶Ԧ½ímÎs;kVvÖä qì̬p(ÀT;6žV%—ŒB2,üï[ý›žÈ¼—©u|cKòÉ_Ñà‘’¿Í=а´MM¤ Î)zh€£ªßë¶š‘hµéN|2Tï}ò¿†Þ©‰LèD½Œ¢¨”4ì]i›[ô‘‰ýÌÁ !03L QÙÊí'ððtê†å‚Ö ŸqoùD ˆZ"YºzÓàzwf HÇéy¦81äyVt1Cf©Óƒ4åQÊ~ê¤÷°9Ëè¥ËUiõ[—ƒÛšúJýõ%ˆñ·”¼äLê¥}ûö'¾¦yðä›Öµ¯{IQ¦$¦MŽT‘ÉXa¤AZnüj•²”Ô£,Én:?M]˜sT þ¥ n§7O%¦Ánr(ù< (ÒÄ6Î#É8ëâ½EÎÇ<î1^-Ý߈ú¶$}3ët”E©ÀOéNóZ7Eö÷~3ÂÊÏÔ?ëÏíÄú¸Snskô²¹srsgnS‹Ò]唼&Ý&Ÿ06ySÙU—â¢?¹ "›±ýúòÚL°à+©©uóä%‚‰lhY¢Ï£+XýÕõ»HÕ ;÷ŸyYÅÌ®´È3u²ÅÍõõÚ¥ÊCíîÀ;¡c-F™¢pHÖÒzŽKR²£¨¬XºÏ#’'[jе2(¢˜,3^ÄE”àM/Ý­=9ŽãPøS]‡ékïõæOo¥œã尿ҷ¤¿:Â'EþJåT/³ŸŒ:½æ¾½öx£ÐQI~WþóôÕß®ïœçC(ƒloQú7.¥ 53n˜&6uî¡E¸$ s*^G@K— ºJ¬Ä¿%RáË4+Ëc’˜vÎ_˜•¼t c‚FO=³Ôÿ@]SK|õTƒ.Hߪ™l§¾uçüÑòñÕŸ~üZÒ—C°'ú–ÏÆ‡Ùr±mò_õ‘Â…šiHWÏ„™\[3öˆO9w‘Û#ìJ88ª«_©R©½Ÿ¥™[$¦ xaŽlfß2û:Ž^F¥Ì³*ç3‘(¡ß¾{¼û_üó/ŽxHendstream endobj 74 0 obj 4778 endobj 78 0 obj <> stream xœ…W]oÛ6}÷¯ úˆ‘)i}YŠ&h‡`ÙÅìA±iK›,y"•Ôû íÞ½¤(ËÉŠ"˜äý8÷Üs¯ÿ!1e$ÆŸáïr;;¿MÉÆÌb²™ý3cî –[òn2ü`±žù7Œ¤œ¤¹ YNÛYtu}qºøkÆRšgy« MY<Ïî£ÏW}yû±‡SrU§LFÏ_›•î>ýsñËLäœ/®£Ý¹HÁVNæBá9§9OÑpôéö£9ÿt{m(¹ªjÝ[mðAžÓ4I˜7Ód¸^5˺_U͆˜]±Ô†Íê¼íˆ- YµÍ ¾¬/!IEÈ&²K<ŒÝ@—¨|8(z£É®kk½5d æ¾x5“”gq¸å³=²/ÀŒŽÏìh=£CÈOfꕊ?Üó9ÑÖêíÎÀˆè®#mƒ S­4i×dYôèì-fu³r÷:í¢)+k\ÐX|åë¨ÐÔ‘I*UàÉ~ÂNã4²hÈ£&þeF!3¾Û¹5aŒ&’euäó´Õ+²î;¬°÷ŒU‰d,p¨špˆ¥˜ñ±ºXa’›¯6MÛa#Œ5eª芾Sߺ‹²7_È2fœ8w^ëΡDà Lc,§\uPÞrm}ÀFÒ„¥ü…»¨¨±™ZSÙꈼ‰obŸÏ“(¸>g€G2š‡è¨QG'‘/¦™ôQ¦¨Ép棰}×¶·˜²òñÐà _]á[­„’º„˜’ 7jÌ…e‡\=ä»{o•ŽuÔ5·»º2¶Z’RƒküÏ ´?ÙCƒ‚>£#N=”*§yè.»™:iKô–LУœb¿Æ±ÛCbÐo:ÔÒ7^öD,€µÕp•×¢»ïÀ5Hñ@"šÆV_¡› H¸_–äq?L ž€i™ýÏ´Š½šSÞÈ8¸+7q#€mÙ6G‰sEUÌ~œ¸ÑõþÈ3Ë&c!:3•Éåè;j·Ú %)@ÔOŽ,Èbžm71 R6ŽH]ÔÞ3(!>“AŽÊ³é{´R* RÃr, üÚ®×nƒYblÌŸ`¼eC†ÁmmvzYa‡‡~˜ÖÕߎv ?TÊЄžTá³!ÐÈ×2§™ ’$Ó!ä. …§µ&µ³(Ð4;<>Ý/ŒA±¨÷¦òݰÃ9ò4~=ëyµÞƒrZüÞ¼ÆGÆ ÈîlUÃĬ¬ïZk%P3æ\ÝF'XO„Æ#‡î¡b§B1çydŠÞÙsuÂ¥0Ü2zÝCÕÊZöÛ¢ÜK]ïÜš„ßû«»Ú-g8§½Tħ$ŒÁq ºqŒ Ú’çìus€HÂÅÔxh¬ÃIHû)Cˆ’{¬'áó2ÔÝsûhÛµ°éà”EI åE9ñ8¿e¸TCËà›ìö'#ÑÝå%¹¸¾»ñ÷ª-Ô¡*"‘ƒÎh·µx¢% “ÇD{Ö0Dg°½X»3?Ÿ¯žK­k/+ ä&MÆBÒe»=ÿ6YËÀÊ]Χ"hý〠ÔF…-;j{b`[­AÜjX•ŒtH9å)p0ïTÓW!óž× Dú·A¾98yp6g4öS²y)ïâ°´wÅDkRqP¹°rq\¹^L¬-ÒòÃÍ)èIÌd}^œº/6‰Šn.‡)Ü2Go~­˜f _€&CöU! ×À…òð;m‚~ÂÑÈ#=ßuãVå—IÌ,`}œ4 Â&lŽÉžÅaJÒÁœLÜJñ‚«\ˆ`¾^|šîq\‰0nnýðÂ8èË}ôX–#š,zI¸ ä³Gƒ> /Contents 5 0 R >> endobj 16 0 obj <> /Contents 17 0 R >> endobj 21 0 obj <> /Contents 22 0 R >> endobj 27 0 obj <> /Contents 28 0 R >> endobj 32 0 obj <> /Contents 33 0 R >> endobj 37 0 obj <> /Contents 38 0 R >> endobj 42 0 obj <> /Contents 43 0 R >> endobj 47 0 obj <> /Contents 48 0 R >> endobj 52 0 obj <> /Contents 53 0 R >> endobj 57 0 obj <> /Contents 58 0 R >> endobj 62 0 obj <> /Contents 63 0 R >> endobj 67 0 obj <> /Contents 68 0 R >> endobj 72 0 obj <> /Contents 73 0 R >> endobj 77 0 obj <> /Contents 78 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 16 0 R 21 0 R 27 0 R 32 0 R 37 0 R 42 0 R 47 0 R 52 0 R 57 0 R 62 0 R 67 0 R 72 0 R 77 0 R ] /Count 14 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 14 0 obj <> endobj 15 0 obj <> endobj 19 0 obj <> endobj 20 0 obj <> endobj 25 0 obj <> endobj 26 0 obj <> endobj 30 0 obj <> endobj 31 0 obj <> endobj 35 0 obj <> endobj 36 0 obj <> endobj 40 0 obj <> endobj 41 0 obj <> endobj 45 0 obj <> endobj 46 0 obj <> endobj 50 0 obj <> endobj 51 0 obj <> endobj 55 0 obj <> endobj 56 0 obj <> endobj 60 0 obj <> endobj 61 0 obj <> endobj 65 0 obj <> endobj 66 0 obj <> endobj 70 0 obj <> endobj 71 0 obj <> endobj 75 0 obj <> endobj 76 0 obj <> endobj 80 0 obj <> endobj 81 0 obj <> endobj 12 0 obj <> endobj 85 0 obj <> endobj 10 0 obj <> endobj 86 0 obj <> endobj 24 0 obj <> endobj 87 0 obj <> endobj 8 0 obj <> endobj 88 0 obj <> endobj 13 0 obj <> endobj 82 0 obj <>stream xœXwtWºa4žÐ±H!«q6¡B „ÒèÅ4 8`¸7¹È–eIVﺒU]%[¶qo؃1¦Û!ôÞR @B²Ùì¦,Éç:»ïŠpNöýñþyGGçŒF£;s¿ï×>±ˆáË5:*E3kmîÞô”¸À‰™ÌdóÒ0æ/AhŠû?ø›á"À¨ 0j¸ï%îfÜxØ2ŠÇÃY¬·Â·Oߺyûk3g¾¾<3K"LIJÎ {cî¼a±’°çß„­HÈIIÊ›ŠòÒ3³ ¹S±¢œ°Í™‚½aÜÿ¿Oý¹Øÿoy‚ ÞXš¹:eôÏc$c×}4.}܃ñòñC–…”†L6=L8?áÌáDM\3Q1Ñ=ñÀÄ‹°p Æîg&úYÌ'^Îf‡Þ­¸9‹9ÏÍ&Ñ¡!Ó»ˆ§VÅiy2¸ÉíÐ:@-¨,ôøÚú!› ³H?šdÕX5@Ë rÍ:=%ƒ–à!,çÀ°ô0*eaLšÞ?C]·-ŸO í`öÀ8[W+U2@it.Û^Y´Ÿî‡±ìÐFG•½ºìÅŽ¬}ñëÖoDó_å_†&Û6•ȸ@Æ“·”êè-z‹ Mž‰~fß&{ážêÃWÎ~süX Ê=*‰RŸªM§w£·Ù¡Åv“BýbB™¬µ§Öÿí5þ³-3ƒ~Öà+ƒ/sP¼ŒìÓ—è@.Pè•rš‚ÞáFÀiê:ƒ”ò@­×sÚEy‘O<`(WWîúy¹Ò|©X–Ÿ—#ÎçjTj•F½s‹ M"Š¥šl®Aª7x§ÔS[îò–yi8.¹ŒÞvIì2PÀjÃÚÀ5uÞà•nSxv ,æÂ÷à¶M5‡Êx¸`ª*fv«þ¬{ï18{@¼*Vôjär ^¦œÙöäÒ…Æþ¥‹]Àê~dÿB¾2s¨!qóÒ´é…Ó‰Û„{“¾ÿô­ÆÇ}×éý݇5fpޤ‡ùa?ë4Æ$p:àNv©•©õb *[žcwqœ3P(E¡”ƒfApÖÏŸúåkZZ6o~¤àmÀCAënÉpäQ8úÞçôѾó —À7àøÖ"DP-T2/b1c¿:ÃLãÔX«­~ñ€2ÑIˆ›»P¼¤`½z—\¹Ç‚k±·<8Fê®.óÝñß¡kÆ@Á©p6|.¸·»wEøÎ´·#鯭k!¼B³ÍÄ·h¶ˆ ½xÛæÊl°¬ÎX¸gÃÞM;Û•).¯nk‡›nÓõWúŽ™ðÎAóu‹yƒ‚àÄÁñœóú2-ÈÆÚÈ•Dêô[ÔøyœÁððkóÝ3ß_ï‡Ã¤(¸‘OÑ*>j&áº޳ºÜÕúÁ1EKN_rý:ð@Ãö¢ Õ«#6-¼¨]ùÅu¥¿ïÀ[+ó •58ãmH/#ÏéË÷Å 5ä?»¯t³V¸/c>ÊÜ1áÙÂ=b^¢tµú@mÉ-ÚWRÒ»ï݃½–r‹ðŽX,û .=Ï£³é0!$f¥Aä7p¯À‰=a¡Z7ÏÄS‚4K²å”s5E…¸¢sÛ›–‹”®2cbò0¦øYpôÄðßÁ#wÛÎÔ7û€ ص[ê6øÕä­hiʯÊÌÍ*Èʦc÷ÄEÊâäIÜ“P`²-ShÌË”šg² wÍ<¼?§¿Ìyðà{íŠu:`°¨i‹˜-Ú*3oRá—T1¯×äûC ëæ‘;“B­ûáTŽÍg{IÏn/Å ÂèÇr’®«)7ù&?8{êμC1tB¯¬4P­UþöM‰ïñ½dèK~H³å¤F®7-ÐØòø—n¡Ü&¼4fÏš´ª=Ý[éѾdAí¤ïÞ"8øŒá'é`ÛX'à° ÁèÁœ»4GªÎ<5fÈãÝåŽÅ¬Kzƺ¬Õ+{wÒÇ£of=ÁÊ»‡úà&®ïLyÉE;–£JYðI=¥:—ÑÕˆt‚¼åy+Œ¥R$JP~„â,»'Á±}p§÷éžÞsõ—ÀEp:«i—Wè9vW˜¸c`³ªþÖ‚}ÌÎ;dÃÏVÀ/žÓ\¨×›,Z=?þà Ñi¡V§*`f«‰ºE.G fÅhÒòÔ©ºt ¦òªdõGZ¾=ÏW¸v¬—Éd€§Ñ»J­Xíôcøý€ ÐÏ?î†XxÝá2r@W¢™ À$ÖfíB‹¸¨“<·—¯«½BÚÔ[]ù«Ø™"$~æ-ìÄ#UaÙ,Ƭ*Æ(’–Í)^YŒ¦T†Uï®}òœú/~û±º  “jÉ®äÊy2§²BÆ/U:´@ bÂѰåKÓÓ¸:ø²þ„â–ø'`ÓÐY´&™qƒ2ÕðÌ üÌB?fóýÑI¡W½ø–~k»ÅivåñJR}è%û,û|®-Þ¦õàçðÕî¿ê(ö·7ü Îå6¢¶,›ÉxnPä©oÀá´;à_à¢Ûp¸@5‹ªBüT ‡Æ+ç{ œ* {R¶¡Iè­4ø”[Œ1f0™µ>|¿éšê©ê*/tî•Ù¥œŒÑfR%I—f0•Ye~Ö²¾~fVuˆïŒ¾9)´‡‰‡Ã8™™ii*ð´z§Ëß —ôÂèÂ"«ÍæÑr7êL&ÕNmGFÕlY<4 …£ù+;c/\;Ô Ç=¦óÞ6k ÍÏ(Q6tí«|r›Þ78mæê ÞŠF#V/¥B{²rR¤““D GÎtüxø<Ý5p¤å éÙCÕ0ãúX ÷Ë 8lpç¬Ùa" 1«t¹f½YgÁo.ziÈÌ6çÞôã0°.ƒo\ÛqlÍÊí±hØ þq¸ÉÝЗÜhM†a™†‚ñ¨Šs¸.uÛÚÃ6m öäa3O/(®9Ûô÷îÛôá»=G±™3'Á~æo/Ó„ª“‘ÿ']gð\-v&/ÏJÛ-â%KcõóµDè®sÛ«œU4ËlzÎ;ŒBëgþ…—ØTμÊ))t[‹ÁAP)óo­_z¥‚ ÓÉäù™‰¹™JEžH¥U`¸ë UC (‘T*Ê®’4]À á5¸²è+plà ÐG5 k¹²‘Ì­ö+ø•*—ÈA\Òûo¢¿Š!Å-øj \T(#i¶˜€h-‰úmjƒEa’ ¡ÚÏÐU¬¦‡P}#þü '*"^´P›Sºo|Ùþõ™º±©«¢ P5eZ¥Ál0jh¬Ç•S.ß×௬ïÝݶÍ@ah*šûú©¨ooŸlºû Vç[Ï3áïJ¾C¢¯†ÔQŒšÖÊÈc¦}*µÆ½Äl4©2“Šûò•þJx» ÍíâЊíûp³’ûÉÐ!¶dF3ˆ3”*Ûö§&­vjœ øl¥žæ@Ù¹gŽ=,a«:ÊŒ¯ )7`£Êgâ`'j½Z+”Zë.ñ6Ãmp8]ó™ÿ昉³]•d×QÒàÓf— ä¹Å$ß¶K©¶[âÇ.0-DhÆŠ®=¯nùá ­Š6€Ü¤}’Úî“oç£Eð§É\ž’0Ð믠%s’s뺾8_¸tßÐØQÙ`ÈEߨRHèžÁ´@vÊÈ~C©$%Æ{žÅdÁœ24Ž‹â#½)#{~Ee<9ô&7MÐ*Ÿ¹=®×v;vûPZèwVA’YÌ ­‚Ò¡^v _e@œhwœDáU3¡†Õüæ_ ‚¿AgyDºl7E‰ûO—ÛÊÜ-tƒΨúåxÈëÔ}ˆ^EóÐ"4sñ©-÷®ß=xùc>Ê€s8m_ݺ{PUe9éùIé:19Aòf^ JZ™·²Î>e–> b2gs‚yqï,›:;è …=™Ca<ü&¼b¾ ¾<ãWô"îH*ç³¾ÈYˆˆASÃgÑQïnŒ_¨·v…¬ïúàôOÑg>ÿ¤ó&æ)lFqU̧-0¿š…¦]fV_ jgÂ8_“ó‡‰ÂR£öžRëòØ­¶BmwZíÀIUI|yy2Inr[vÏWWÿ7tóoÀ›lÈ"-lDðŽkgUæ6h1WLFÚ µ€#]V]SYQÝ™XÿáÎxÑ®$¾ N¼K0“šCþ1íuvÀ6ƒ-?Á©8÷ëÊ4 §2‰"zïÏTfö¯÷ A;(¶¹‹:O­Ü:ý>s7ø\ñu7ëh< >¦þ¾ä$z‰¬$\ÉqV•¸°cujüu’bˆá¹»vg§Kãµ€P†#€t[ WÁmʪCܧ[ïÁ™gS?úo&y³‘4ƒMë̪H-JÀš÷þ¬íU‚l:"N"9@áVVʧ‡ãã]ÔªKýC|üè|Ì¡™uüÝÅÙ^PN•×Ô•ÚlÀRÈ÷˜‹-Å€ ýé›o?¿ç3ùôÕô12ô7t=áXÍb³ZŠL^ï)û³ðr[#ãÞ'¦óÂ>§Ï[É/«8Ø‚ƒmè/p:3™ÓQ™“¤Ü“ŸB‹bÓE)€J5ô~ÓÿÙEú¿‡ÜƒŸÞ ˜SB`È]£T>rÝEÅÞs¾tã·•·A-Õ•U¾"M͇£˜(ƒc“<^‰"¸ÎZc­PæD9N³QnÈ °ròº]pvi[×''>½r®º¥J…¥ŒŽBqŠ8‹)y¡¥Ù>YñöúGgŸº?àf‹1¶/x9» žü³¡™{××Z¶¿¥µ±â衾]z½ˆ[(#»õK‘Împ*qÞSrtÏm$ÛˆCÂä ÞàÖÛ1$ŠlEEg`÷¢ŽEwÙp:‰J˜o0J]-€º0ñƒ×ÖE£ñ­Õ.¤Q³—ùÎÏê»…äSõZµZ*-Pk¥ÕºÜE…^Wí¨°ÚØ¶àÇð¶É6%?ßoÂ59eñ˜püך¤úüh%W¶IŸÄT¢WÜÔ»¿éA??9ÊÉ‹ÒÓ*óëjjsë²=‘´3C­à?é1ÿhRè"&™Iætá‰7—”çi " ÊÂ<7zד—êHŸüÊÒU¯m-Ï8»Žv}ù¾|¯´\æÖôî(Í{¨%Q‘KßÚpýx>²yøb[ ÊÁzåª).òãtTn¬Ó‘Öë›ñœüè!$/Š:ç~CÏ{¢)öw¾ûÀåMŠœ*~µÐj[óÌ»ýÌwí¬ÁÑ騑܋fWOB¢Õ_7óЫCµ²m9²µl‡¼ÁoºŒ6ÐJpÑ÷Cš1pO“7Z„[ð0g–Ò><Ìa;ÈüêgýôuРó¹6Ÿ4`$ €,{ÚNôbûºÕh mî½ÞÞ‰Û°œö_õ–]uSÏÒöe}q`@Sâ„(݆¢¸ÄRl{©×Ÿ¬Â 8éþu8ã0ÿ>ìì èó9¬Ï¸«~ÖÁ»A0Žå„/ÒjEX Îwa©£‚¶Úñ´n¥lÁp&s'€ñ„?0~Ô¯—q0ÒÒˆ?TkRãiMÇKôå·œhkøþb`TzF&ö‰øë]¸ëBÏàJÌ&£Á`0ê¥bÊbå¨urŒ££Øn÷9÷á€a·:l^àâíÖ§ŠÅº‚þŽ´Ø«Ð°º{e§A%µ?w_ÊÆ•kÑ”9ü˜`²mUåþT:‚C»‡v»§eΜd43NôQ¦ˆ¦n“Gáåm'ú~|º P¥.L!@#âÐË´6Ã(Wì ´œë?~üZß•c‡UìÑàð¡6ˆéH$UÇ›¤@i)(“Õõn½u’ïpá~Ý’øGúY¿ñÍÚ #OŠux’êråYhÓÐpn3ÕâÀÃx!t••žràidÁæ"k‡g-A?îff<»ÄÆJ<Ÿþ§RÉ‚[“GS¢²ç—Ì97TÆ­$¡ÙÁvdžv°ý$<Ã|V¼ÈÓY‚ûWˆY¢« © iºÒuκeRèSøÂ#ôשû˦„-ÛøÆVüåe|·j˜²Ü‚raëæ³÷±<2pÜ“»?_œZø˜~;‡!²D6S‹7G¼ûî–/ú]ÿÂiÎ{·¤µ ›ºÖyè?´ÿ¡˜ë³ÒÄbyx¨‚AP ƒBŽÁ |8)ôË_~ठ³Ó3j…-µûšš…u:ôê?áß8é9Â4Á¾œ¦Àéamzàçƒ/úYp³†óeoÏiÐOu ›S3Dâl‰SU)å—ËñP¤Ù¹™ÛS0õðP?XXÏb& Žã¸êÙh)‰>ü½Ÿ #Hüi ™&õT:°{i¸`p±«¾ÈÕdå| ›gÌ%ÀQdà Ìµ0e]‚Y0óÊ„YkÉ€µÅíƒË{ j2ìö/_fØ·^ ÂÓgG/Ë{-E ÐtåGÒ4IºT!T¡°’çwaçwíiu7:|V;×€ÃPÈ5âl­6 Yæ l°3Ȧ§å]þæÚÎ&ßAœ’Jõj“ÅŒ#…Ng6%ôJkk}¾Úî½ ·DåÄ'ó÷ƈcÓ§P H]ûÏzV¢Ž.‹ —’ðÃÁ~6Š$ñ§~²Õ«‘À6…Þü}±>K£M·`ì=„QçY°ºq!Iùz6Ì"1 qóYõ0(è‹8¡0 ·¿¡¥·?·ë f wúÎiCc~_¾I2c—°ÇH*˜˜\JÖŒ¸7²¦xÔ(‚øpg+ endstream endobj 11 0 obj <> endobj 83 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 9 0 obj <> endobj 84 0 obj <>stream xœyyXS׺þŽ!{ï:U¡ÑDl¢¶Õ:V«ÖyžPQdA™ç9„Œ’•„†@€0Ïó ˆNଵÎÖ–ÚѶžÓzìéÚœEïsW°÷œû»÷<÷ß°Ù;këýÞïýÞo…E8Œ!X,ÖøCaQA ÆDDÛ¯ç3Î,fúæ]ö6døÇªa%‡Œ'Àx6ïP>}¶Í‘ÑM†÷ކɓkåOË<÷ƒž,Xðá–˜ØÔø°ÐÄË–,]>#0uÆŸwfl J ‰ž1ÿ‘¸/,*0)aÆè{g IŠ ˆÿïÿû×jÿëá³)ÚksŒ÷–Ø­qÛâ·'ìHÜ™´+ywJÀQ Kê±½âãû‚ö»†„ s ?áéåytÉRɲŒ–¯øxÆÊ™«f­~ï“÷Íkf¯›»~^Ëçû,Ðû~h8²p‘ÿb‚˜Eì'Vï®Ä'ÄûÄb6q˜C¸s‰CÄ<Âø€ð æžÄ‹ØL|Hx[ˆ…Äab+±ˆð!¶‹‰íÄb±”ØIì">"vˉ=Ä Â…ø˜ØK¬$ö«ˆMÄd‘8B8‰Ä;—˜BL%XCð 61p œ !!¦$! hBH¼EÔc‰™Ä8b-1žˆ"Öˆhb=1‘x›ØHL"|qÒñÇ‚ˆ‡¬˜1NcüÇÜcoc:¬p¨áLãˆ8ÏÉpò5µ‘ê¢ù´}ê-‡·¬c׎ç>®o¼Ãxõø/&ì› ›HO ŸxíímoWNršôídŸÉ;~æäâTøÎœw ß¹Ç]À}:%hJåTöÔ S÷M­ž:ÈÛÇÓñø üd~%ÿçi!ÓšùΙÎç§{O—MÿüÝËï~-p¬HFÁ=aÍ ùŒæwg†ÎTμ0ëØ,Ó¬êY—g=˜õ'ƒ2èÕÍÌ,c {ظ~Fe~èd`nòRHt|D¾Í‘§ùhù"xØFù¤Xê-Æ"S¡°¾ÅV²{%Ö¤|/ÎðÐÑ"˜KÈ`>R°Ò¨Ž3‘Ée ÷"ëó!¸uˆ]:†ZIocZ!h£a uúd…¥Ðgª"w Q¥Ý-O;œEKàq+uؤ°èÎÐ0•úÑÿÒ¦#‘â=;O)•ÁS¦ð”ðŔ٘§/t]žä°é)«BæEîhx ÞŽËð|.J‘´Å*$ÊÔ¨ÄA^Àà¾ç '@”Ys›õuzž ]Q7³J%ABÈBËyh)r_6S“镉w.µQ®Ùâ\P ¬Öêö>8Îãý„f´x•D ¤¦)Ãt™@¡“Û8k£JO_’‰ñ´QË ²ÝczPpL¾úMMŹQŒ¥½ÌߺX˜|ìa‚ñä¦Ã$N2©NN“§€t 1JL‡K¼s}Áj°*rï¡m{ƒ4†FG!M‡>óKß³+‚ÔÒÍ[wF­|àVv´ãЙÈït á®†³/÷'ï4EXcl»íˆ¡(¥lb&^q|8“žOu*4¡(.Ô”’õò|Ý .¥œDám•ÊÎpÜ÷ÐΆ“¶};ßÍ?á¿ð1¥6¸'‡Ê‰ùiTž>ïžn1+}…#¡ðP(]Õ´ÓI¸ˆiä6\jë{pfzKàä…ÆÞ¸Å÷`[Ã(ÌíÌWí¬×¯²ØÅS`; ið[óµK7Û¿/ÁwÑOÜ.îø±Úл€F•"ò©*7ãOÊm–Ë7jhx¹ÁmÌÏ=ñõ´°Ó‚'îÝ+"¸ò_¯èòå€>&Dz3ä*3¹ŽUõ¦ ±á³ŽëW•w /ìø!b£Ùhò­e?\¬9Ý+Dx}·Ô´m™´*Š(w‹Ê¬í¡™)…ž³}É ™2ezRj¸<D‚Øü[DCò p›†cÏßÿêZcø.ÁDbºÒ ó:X}Åf~„ë¸1¤ÏL¿xôžŽŽ%ß3êô “†.¢†´…òÂÕt%”$’òO¤ò•Z-‚ñ¤¾!;»ÐÐã¢-“/£«É,øg¤NDÞ×Xd†-v$´[dÒ-˜\L;5>Ç¢µªŒõhˆmšUVr§!­H;HÃ$ªéÄÙºœ<²@`•X4…€®²–Ô5'—…Ä$mñþ@i nI!R·TœÎ"¬P@Wç¥ù ‘‘ÒzªÕ. L™óÿÏ–`‡L)ÖŠ¥«qȳGC6ëô4œþ„¼Ò}¬TlÐàzh¶QŒÒ"Ý}FÃÙÔºb©åü"¾²B^Ƭ¨tÂðÖ”’É÷ˆñÚÚñ*Q†–’æülÞ‘“W°h+íÔT×Öd–9?¹>p÷lBóþ6!"nÄ”Hª@-¿»±¶ïrCøÒJ;G¥]Ìï]¬&H23^²‡½áï\”›J>Ñäf6Ðèc*bìf´r.$á¾ë¾ï=#è9s½ö¸Ί:B¢‹ãª÷Ñ•d á$‘ê”TY2P‚4cªÙÏê›ë‡¹çƒÅd.:úAíÆK®Â[Û_Á1àk'µvµÒП2\-°\Φ'ÂFe?3¾‰uS7—ñàÎ4™¯5jVF…E‹*µ’,½Ö¨¥Ï£ äʆ£ƒg:ªú›²‚¤¸´ô$À–Ô^ÂÎ_©7½ót/l+cýþ ^zŶM6rcŽÜ¢»GÃ@x yâ¥+ÖÙsÔh£þ¼Ã¸RúûùùÍXäEÔcu¾R¿‰FèV³sg4Ó£«Ø«o€q,c}6·aêœåjÈÃU®î FËÄÔµ,‹xÓHNTªˆMŠ”GúxDË !|ŠæH©SXSõ>42QkO{Ýoï,®­ôôpVQÙÚ³emçŠø£ôUnꕽcŸµ‘« Ò"í{䆇…–/8¾³"ê«u® rÅÊ,{|Ò2fm‹‰Ãà"¡„lʲ*(µÊLå”ä¶fã§vJ¨Jm®²Â :£Ÿx–È\Y0\‹¥뿊÷=RXƒ 3à›)¯¸ à_y¥'Œ¦2ü j"㪼|p€áU9^úÎ{† —Ùw‹+–Ê5@'ªŠz…ГýšzIURÛQ›+ n:ì’hK©ª*/«ÈÖ™tf¡6O— ÌtmSE×™ÚhwÁ> -Ü—š~4()EÂq »ôú_íí.ï¿*p*ô0•¦t;·€rKk¾…cuŽÒ(’åñÒØŒd@‡Æ´ô³)ý•ÞøV÷¿\œ„3°»˜+Y¹™¸±'%FòBÛÐ   ôóí ÛP;沦@nØü†ËŠ7Ñj£Ö›äº4ÜOÕ”ÿ}Öãõç·ƒ>ÈÔÑ: P€QG5`£<õÒü%/‘yð t½s³8÷މoCv¨ìþò#+ 6NG¬d$H)ŽìEï@/Þ—p¼­¶ÞÚlà[Ñ2 Õ ÍW)Ë“â#5jyª,%ÓT¦j³EªbÜw­…9 zœ»c’<ªË}Dïó‰VG*UáY| œm¥¢¦BsNaQ¹ð)|û{4#[mжªÌpíh…61㮳>‚)ß°áÂáu\!P›î#ãGgpÒ¨½äº+/=@8RLE…?ƒ¼Wp |NÚðbÞ)‡ÎSmýuÕJQ¹ )²bØB#¶ÏžÕž~5£=±“ù¥ÌÞ=à);û[ÿm#k¥NÃÍœxÒwÖÑ8Äͤw’ë F]ÍDQ†û……O²GíKôs@Œ½bqŧ§eêÔY*á|T(˜£.Ê,²S»Ôjî1`x¥TMf‰"W I¤ãYbõ:“²Î»8H@Zâ>q¤$>Y$Å*šŽKª95; Ð "Q|xc|Ͼ‹pöE!¶36äWùvªßc8õ¬êÇlf\ÂõÙ’pЋ]>‡Ôë‹wŸµ*ƒò…9I¹Ñ¥â À¯)·U^Úvjåa¯”@¡·Ì°†Fܧ‹ ûdWqc› ¶ÒV×0HOüÇ„? ÊêeJ±}mÇɇDq#”Æ8è°ˆü"³@aÀú5ŸÒΔ‰WÛ9)ǜ̖”kÿF3s)˜=rŠSDÂ<æ.gÄ{”¸kÿl·[²eEÚQ)7ܳÞ7a$]A3­Å| ¹©Ù© ¥òY|$ aóÇŠ~¡²ÐXN)™ûY‘õš†ÙF>àH˜ vã¶4­ŽUû¦`Y—pe:5ÈÄe—^Ð'dn`SᛦØe÷ˆ¹zÈt{ž2Pˆ–PAM±vóE-³Í,ô΃å}©£ìT‹p•çösЂ+\ RÉ• qJœ2Ð+Ý?‡“ Ã™.œöõâZV”¥ÛÁr´ƒõQïT'Ѱ§.¹ˆü\S(6ΤÑwÔ—qÐÙŠ2º|鑽ÿµé”]¬0n%L%i|]XòÔlÇFù)Œn‚T‹ù®âúl8½Gë£/§v¨š´×hx•̸©¬oŠj;Rî ¼ojP˜o`ìV°šF‚{+ õÓÃAHœ 'ðCnÁ“–ö«à*¨Š)\>*âmÌ´±Z°½XI6ücx¹¡éØø-lZ|á pÀåÛãß`è §ãÆï¯ÑÏ ]>]Ù¶Ð!} /µ-âÂáÆ…®òíÉžéñâøÄÄÐP¿Tpø•†4zõ…ÿ ¼ª{yâÝÙs¦â" ßXÅYM0 Žõ7l*®Ù«èmì*m …ÊèRAqœEY‚}biie›Í~ÏX¿8aœ_Fˆn ½:â t›ÔnT*¶ÚÇÞB+µÚ¨(ixN¤Þ8Åò.x¶õË+˜f·÷Xjdä¥ëÿ”RUúÕF®Å-Ú.¥»©m‰®<çó{ª®4µ]·À iGlý±Þåu 1UJ°ÉÚÊ­5›k¡ó5ß÷ç»z#*Eª7$ Fåà2¼^ Ã;Mu¬º»0íqm› gxÜÎõT2SÌI¹¼¸ün«‹6m]ìRt;\—œ"Wdeò““Ô Ü@“ 'R¶xÆ…ƒ`Úã±ÿÏŸÔœèt4–4pÍ·{S6âæðÜ y ”5·Öæ¶eٴꬵÍuÖVpÔk*¥M4RL㶨ž¨Ïú»fYÈ ÇgÙÁúÞÊ£¡õ[à…Õ® ûàeJc •ÇgJãÇÚE:[oÀ¾ƒîÉÍ8*‰À’ªÉ8¨Â Š´RLZüy5u¢¯¡¤ ÐgªC¶ ÑaJ»5]qPƒ ¥ì³~óªõê”ᬠϵqƒŒ)ùÑ-(æð Sõ…³àÐ#k«ê^Y³g¥^D>ÈÈÿgbÓ•Õ8± £=ÒbwöÞÔ%LGW9p9âÃ<çÖävÁÉGz'„ˆGâBÕ ´v‹ß=ðÊñÉ«‡¦:}ŠB¥•ÜeRåÙT¦->Ä‘`±,ú|À¯O$”vSºrGíôt^ÂMLŒ‰®Hªk¨¨¨¯O¬ˆÆ“ßyi[RƒºÃÊ?{¥¿NuúqÕ–L:MOÊTÈÅÎJ ÎçÒNÍEÁÁ¹áÎÀ_™<Áš^7èàzïxÿ±ê <™)ÄÓ»¼l^º÷"œè-H$P(§‚tr±é-EVçP’iSá•$ÝÎþæéë/Ý@¼{ÂY—zÁEúâ‰ök'OˆBZEqÅ®xBÂ[GÑ-Ðetû?ŒnÿtgŽp5ƽ A27»|šôVƒÕ¾íÊ<1ÎíÛØ¯HQ+¥RÜÁ”fqyj¥47­ÄTqRDgâÅÞ®¢êZa[SÅð”vúÕkxÿ©ÌË,hÆ~ÈËÆ]-³àjdr/Px‚+W ]EªázÎÈURÖsªÈJÈ*/”¾0’EêV¤+WÚ¥ô䟖fQë‹!¶y ”YÉ}€û¤v>t¡à ´?[cÔ³ø¹J£hèôtµ\ ’Àh+éoŒ´œC ¡¯¾N†µÅ7´Øþ•Rº‚L éé2© ½‹&ò˜UT¦á¸<:ý „eç|¡>Oo?|È“ùG’)GVÖVŨ¸ö2Lëõ+øG/{ØÝÞ$"ò±ÆšbxŸF•Ø¡GÅúì‰Ü¶‚ÃU±§R›Tíà: ïN3ŸÛ§™6õôÏ9ç&…6=[ ×CÖÃÖ;‚ªy}à1 ‹(ÃoEÏòÞ˜õ—!vù¨°’.FE¾î’ýÔ Óà•¬ØŠ³˜Cè-z좚ò¥¾Â‘8Jç.•îͤG[Ùð„2Öð^{˜"òbf©Ä€4U¬< ÍaóÐø}øƒŒ `僲¢¼&ƒ è íçM6uÏF=Ë n¤g%a<3Ðü´ à4v)Ã6œ^?ëùt±ÿÚYâ­¤—>­@×EÃV róÍæêÊž’V@÷V„bEˆ¢´• 7»®'Z)7 -ÖÞ ¡‰jèi*=èË¥±«„(„ÒºªUÔø¡+gˆ0)¬ “)8öø•õ¼â¸ R/‡Õº?+[µ‡~H© ¢0…‡ý Ôòæ ´&/ÍGˆr(­›Lz7¥l}Ã?VÙaÀN眦TbAŠ:Vƒ&£xˆT•fåj³ùéåj(U•ùì0”‰¨Ëºüô–5Í«y3P+zŸ¯*Í=Ÿ«(Ê9—ÑŠ¨skjûBè>ÒbGj³.Yñ’Ï¡Õ\Ùð¼­¿ ï|¾½?2Û^Ãqöa²“ S°\ì ÷ÛöÓ^-A}­U•-MI¶`•J§S 4ZÐ:C“Û\Ûz±Ã~Ø$­v¬aUý fC3þô!rÀ-Q½ИfDŸrk÷?—0Ξ’¶Ö‹p –À™hª +Ž;t»£ ä?cÅ ÿßáqvŽy.-µáI8¸°çl8v ¬·’ë¸@wšf^R´s —ŽµÊŒWyž$Bˆm ÖE,Ý Ã;ó½}‹}¸·þ!ÞEÚ—zÄT>`Á™ø.Wf > Pùêø(ƒ„káÖo_t>Oø¿|òø½CžIÇ‚a’ñÖr ¯ë/­MwýÕ¥ƒ+×Y¼r™mG8rf5þ zÂrV7,gÃÍÌ1î&W×M]Þ¿zåÞc×Á £µ1ß_q„Ÿ= º‡õ.„_rA¥¶2ýzb‡ØNì¶gSLй*X€=´YŒ•M"MíIºûèiM÷iá©îêpô§õÅ4&Wˆ,Gm¸Ü9UÝ~aÚ.yû‹#BQ1ØÖï·fòºœlºè[½G÷„HBãã„QøÖŽzJ8÷³ÛÈ“OÖ?ÆÚËDÂ4îlæ€?‰nàì-h åôëc¸æ‰vÞà" Uðgû—ÒvæòSdî²á.æs.ô"K€QoÌíø–—n–¤¤«“‘ˆ…”:-f‰–¯ÎÖæ6uªd' îßæÒ öo\›’f®ˆDT%å%:F*êKxôå½Úsç„'O–_À=Qßá³þ½+ÑØòÑ‹:Æ¡ÕòfÇfoä"Ry@´Ù ë] Ð4°¼ö£ïÿ ×°œôü'<¬s·|ŽÞòOQ¹ká<Òpi Q'÷ë3[p…9¾oÛGî?ÂÅçrëʬÂòâÆ¼V»[4â7f”1÷°»’ޤ+š[’Ñ}ÛVxIχQ$:<ò‚s“„¡Ã³8¸xÒc.czN€[¹''¬| ˆß/ª O‰òËÝ`Ù(ÈsÍ9lˆÊCϼ†•˜…ÛSCseyCC|UÔ(Iê†'Ö9^z´íŒùôУ©NaCq¹ÐÒ îÐ_nœƒXŸì\²ÛýÛbÓ·ˆµ*9zû´žì„$ÿøÖ߇F¾¤¾Ï½ïYÜèÝ~~»7x <¿YÞ=xZàôøÌcî²>p‰8Ù}ýNÿö}qÇvøa öáðûx ýÌ®±ÔPhÈ+~”wÔÓ¢ÒÄQj¢¸hié|š7åÿ¸‹7•=ŒC«áö`:^´Ý9óúÑU8 @g®^ßBSиes3šxïH\>"º:¾¾±¦ª¡1®&JˆÃÿúßh˜¬þ¯ñØó”ͬc²¸M…Õµ®Ì§¯‡¹P.ª˜ôð¸°Ø”cà(ð-í ®©|vŒF­ÔB½Ç©„ßh šB^ >¡Ê¢—·|M=°4ZÚê›ëlÝà4hS5ËÊãºcËÑøOi¨£†”'J>¦Ñ®EÜ•—DUà¸ØÒòiÝŠ^r_({Á®àu»æÏÁ×0Ù\4ÎK-M7I?Y&¥åKlr<ÿÏ·o[]–öê Ûï[Þ9Õiçïh&÷Ó–ž+à }.´Ã/$1)Là”^!j7›õúS¨Á¤zçÜuFDL°{°°ƒyÂuŠý4Õõo ~ +S5@KKq ­®jP—9^}ã«o>‚q5S|¾^ŠÉ83Ð[hòºS^÷O¶·¶ Ï_h~žÐw‚:w ÌÜÎÆÿƒñ;‚|„ǣŘ1Á 5êžµ÷ k»êJ¿ã'y»€c ÉœPF;µ|U'3E:#j&‡œ¶?x³çdYk³°ÿ|Óçà(ÒZ4¥¥*[V=èÕæî*ôúŠwštzï«_™anNŠQ¤ Pâ‘~àHØ@‡&T· 8_ýýK8ëšÉ ÓäŠdM}Ö¯«pü-8í‹id¦pGô»=‰¦9¼ùÃÞ|?}Í‚;:Ùg¶qo7Ÿ¼Š¡=ÚéšQ!ê0çØq50ÚkxL†/ûè,—YK8fjd ¬ã¼OÁA€‘]•ì}wÌÓ¸!o:|dëòй£ýøöùßÌîö©Iê°óÖ\i‹}p[ñü ~+ü²öjݵ†¶{£ÇÚ£†±Ü[8ZêÏU¡ÏsvÚÆ}p¦¡º½ï³¯[ð-ß ~ùÑ«ÀÓqžMò4Þç.µ¡u«vlsÀ,ÙêØ}±{#ƒ·ÀÆg¡´ŽmŽè ½ðÝFGHÁ Ÿ1º¦: o½Ï]ê%Û‰‡­ h|nyÑöÓåá™3·j`i_ § ·Ñs\슓YÍú½Ixš9ÛIePR·¤ ð‚дÐ0Oìu7ÑNs]:Ÿé=U{²Eà4äŸÓ}Úù¯_ábæÂÕè=øÚ‹üÑÇh1òD‡àr4¿{¦°÷¥­cVsë´ÖDíq­·ø@¼/í´2$%:)Ö98±éü…Ò³-º¦Ö²ªÑóÄQXÔŒ;WŸ®W-ˆSÇÉ#T¢L1PТb±­¼ÔVž“eÑ d­ªÐI›)sVyFeJM¿:²D^Š­K‘µ¢FRàoÏ ·Äg˜xgêlæ^sgŽ%ÔЕÒâ$‰X“ ˆJHJ”«2y5T-œÂ)K+NI‘HRÙ¢œdA~¨)m2*¨<¥8¢-¥Jž‹ç¤©$9Þ&;“.lW5(m²/0>M}$Ý/C,qtr¡¬²8Ïd+Ô7›L¹æüÜììö*»J %ÕÃyÕ¬o±aÿðdn5 ùc†T¯ ÂôR«®^Né› šõvº`Iö½Å‚†[lh€\³ Æ Ø[0ÆÜB10ÖnÁÎc—>³¯fýuîb72+¸wÐ#R»K)?¤Ã;ñlYáÏ©—À¨Õ»Ó¨„ÒmWgìÕü×ÊBÝMZ)`V½MßÏË4SEdb ²´‡ÔµgwšŠ {ºN‚:P*¯µÅÚOxÊ­Å•=Þµë7ˆ;"Œ T«×ÐÛíS©´lXPÆJÇÕElçÜ!Qêðv\HF»:Â%XüŽ~‰ÅïT¨À©<â_âwôŠß›ýÎj‚Óhk‚®xà}ÖÄ|ÌýÝ"µëUÊýÿ5|˜¤ûWD?@Wô5¥ó–¤yÙïDX)÷le8ow»CºV™%Wó>LI4Π4JL´“oALtN¼óp$!æxÔQåñÌè­$üq r%uýº_+Ï÷~°d”ÆÒN‘1¶ÂôJç\lÞL9ÿ-ÇpÝ#v šÊ‡!Ã($þ9Õ¢+’èCè?–Sº…"Ün¨ŸCë¬N¨cwÂ|® Ô]Ǫ`ÄÍ‘u×Þ'ÿò¿û¢ýÀŠw–Åd"÷ìˆÚ›ú'ذË>j` Gñž(-b<ò¡_Ù1öËqÆñãŸfŸ@ÿ £‘] endstream endobj 89 0 obj <>stream 2019-01-21T18:35:32-05:00 2019-01-21T18:35:32-05:00 groff version 1.22.3 Untitled endstream endobj 2 0 obj <>endobj xref 0 90 0000000000 65535 f 0000056348 00000 n 0000083500 00000 n 0000056197 00000 n 0000053931 00000 n 0000000015 00000 n 0000004734 00000 n 0000056413 00000 n 0000058955 00000 n 0000072875 00000 n 0000058102 00000 n 0000065891 00000 n 0000057536 00000 n 0000059713 00000 n 0000056454 00000 n 0000056484 00000 n 0000054091 00000 n 0000004754 00000 n 0000009960 00000 n 0000056536 00000 n 0000056566 00000 n 0000054253 00000 n 0000009981 00000 n 0000014043 00000 n 0000058770 00000 n 0000056607 00000 n 0000056637 00000 n 0000054415 00000 n 0000014064 00000 n 0000017775 00000 n 0000056700 00000 n 0000056730 00000 n 0000054577 00000 n 0000017796 00000 n 0000021089 00000 n 0000056782 00000 n 0000056812 00000 n 0000054739 00000 n 0000021110 00000 n 0000023768 00000 n 0000056864 00000 n 0000056894 00000 n 0000054901 00000 n 0000023789 00000 n 0000026957 00000 n 0000056946 00000 n 0000056976 00000 n 0000055063 00000 n 0000026978 00000 n 0000029988 00000 n 0000057028 00000 n 0000057058 00000 n 0000055225 00000 n 0000030009 00000 n 0000034030 00000 n 0000057110 00000 n 0000057140 00000 n 0000055387 00000 n 0000034051 00000 n 0000038573 00000 n 0000057181 00000 n 0000057211 00000 n 0000055549 00000 n 0000038594 00000 n 0000042245 00000 n 0000057252 00000 n 0000057282 00000 n 0000055711 00000 n 0000042266 00000 n 0000047214 00000 n 0000057312 00000 n 0000057342 00000 n 0000055873 00000 n 0000047235 00000 n 0000052085 00000 n 0000057394 00000 n 0000057424 00000 n 0000056035 00000 n 0000052106 00000 n 0000053910 00000 n 0000057454 00000 n 0000057484 00000 n 0000060108 00000 n 0000066349 00000 n 0000073479 00000 n 0000058003 00000 n 0000058672 00000 n 0000058848 00000 n 0000059567 00000 n 0000082077 00000 n trailer << /Size 90 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 83654 %%EOF flawfinder-2.0.10/flawfinder.ps0000755400514740010010000031500213421453503017257 0ustar dwheelerDomain Users%!PS-Adobe-3.0 %%Creator: groff version 1.22.3 %%CreationDate: Mon Jan 21 18:35:31 2019 %%DocumentNeededResources: font Times-Roman %%+ font Times-Bold %%+ font Times-Italic %%+ font Symbol %%DocumentSuppliedResources: procset grops 1.22 3 %%Pages: 14 %%PageOrder: Ascend %%DocumentMedia: Default 595 842 0 () () %%Orientation: Portrait %%EndComments %%BeginDefaults %%PageMedia: Default %%EndDefaults %%BeginProlog %%BeginResource: procset grops 1.22 3 %!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 DEFS/BPhook known{DEFS begin BPhook end}if 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 2 index/UniqueID ne and {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 mark }bind def /PEND{ cleartomark countdictstack CNT sub{end}repeat level1 restore }bind def end def /setpacking where{ pop setpacking }if %%EndResource %%EndProlog %%BeginSetup %%BeginFeature: *PageSize Default << /PageSize [ 595 842 ] /ImagingBBox null >> setpagedevice %%EndFeature %%IncludeResource: font Times-Roman %%IncludeResource: font Times-Bold %%IncludeResource: font Times-Italic %%IncludeResource: font Symbol grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL 841.89 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 5.559(][)C F2(\255\255columns)-5.559 E F0(|)A F2A F0 5.559(][)C F2 -5.559 E F0 5.558(][)C F2(\255\255dataonly)-5.558 E F0(|)A F2A F0 5.558(][)C F2(\255\255html)-5.558 E F0(|)A F2A F0 5.558(][)C F2(\255\255immediate)-5.558 E F0(|)A F2(-i)A F0 5.558(][)C F2 (\255\255single-)-5.558 E(line)108 208.8 Q 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 F2 A 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 F2 A 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 l\ ooking 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<83>108 652.8 Q(// Fla)144 652.8 Q(w\214nder: ignore)-.15 E<83>108 669.6 Q (/* Fla)144 669.6 Q(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 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E(1)206.225 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 2.5(lo).15 G(ption to help do that.)-2.5 E(Fla)108 648 Q (w\214nder is released under the GNU GPL license v)-.15 E (ersion 2 or later \(GPLv2+\).)-.15 E(Fla)108 664.8 Q .046(w\214nder w) -.15 F .046(orks similarly to another program, ITS4, which is not fully\ open source softw)-.1 F .047(are \(as de\214ned in)-.1 F .188 (the Open Source De\214nition\) nor free softw)108 676.8 R .187 (are \(as de\214ned by the Free Softw)-.1 F .187(are F)-.1 F 2.687 (oundation\). The)-.15 F .187(author of)2.687 F(Fla)108 688.8 Q 1.222 (w\214nder has ne)-.15 F -.15(ve)-.25 G 3.722(rs).15 G 1.222(een ITS4') -3.722 F 3.722(ss)-.55 G 1.222(ource code.)-3.722 F(Fla)6.222 E 1.222 (w\214nder is similar in man)-.15 F 3.723(yw)-.15 G 1.223(ays to RA) -3.823 F 1.223(TS, if you are)-1.11 F -.1(fa)108 700.8 S(miliar with RA) .1 E(TS.)-1.11 E(Fla)72 768 Q 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E (2)206.225 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.749(sab)-.55 G .249 (rief e)-2.749 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 .862 (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 .937(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 .873 (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 .874(ould probably start by opening a te) -.1 F .874(xt windo)-.15 F(w)-.25 E .162(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 .615 (At this point, you will see a lar)108 213.6 R .616 (ge number of entries.)-.18 F .616 (Each entry has a \214lename, a colon, a line number)5.616 F 3.116(,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.781<798d>-.05 G -.15(aw)-2.781 G .281 (\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 .282(l, sho).15 F .282(wing the riski-)-.25 F .071 (est items \214rst; if you ha)108 249.6 R .371 -.15(ve l)-.2 H .071 (imited time, it').15 F 2.571(sp)-.55 G .07(robably best to start w) -2.571 F .07(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.099(use the \255\255minle)108 273.6 R -.15(ve)-.25 G 3.599(lo).15 G 3.599(ption. If)-3.599 F(you')3.599 E 1.099(re getting an e)-.5 F 1.098 (xtraordinary number of f)-.15 F 1.098(alse positi)-.1 F -.15(ve)-.25 G 3.598(sb).15 G 1.098(ecause v)-3.598 F(ariable)-.25 E .672 (names look lik)108 285.6 R 3.172(ed)-.1 G .672 (angerous function names, use the \255F option to remo)-3.172 F .973 -.15(ve r)-.15 H .673(eports about them.).15 F .673(If you don')5.673 F (t)-.18 E 4.367 (understand the error message, please see documents such as the)108 297.6 R/F2 10/Times-Italic@0 SF(Secur)7.196 E 6.866(eP)-.37 G -1.7 -.45 (ro g)-6.866 H -.15(ra).45 G 4.366(mming HO).15 F(WT)-.5 E(O)-.18 E/F3 10/Symbol SF108 309.6 Q F0(https://dwheeler)A(.com/secure-programs) -.55 E F3A F0 4.072(at https://dwheeler)6.572 F 4.072 (.com/secure-programs which pro)-.55 F 4.072(vides more)-.15 F (information on writing secure programs.)108 321.6 Q .722 (Once you identify the problem and understand it, you can \214x it.)108 338.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 350.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 362.4 Q(ferent vulnerability)-.25 E(.) -.65 E .516(If you')108 379.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 391.2 Q(fending line a comment lik)-.25 E(e)-.1 E(/* Fla)146.5 403.2 Q (w\214nder: ignore */)-.15 E(to k)108 415.2 Q(eep them from sho)-.1 E (wing up in the output.)-.25 E .397(Once you')108 432 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 444 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 456 Q 2.5(et)-.1 G(his:)-2.5 E<8d61>144 468 Q (w\214nder \255\255inputs xyzzy)-.15 E(Fla)108 484.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 496.8 Q(Fla)108 513.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(prettier displays\).)108 525.6 Q(The ne)5 E(xt section describes those options in more detail.) -.15 E F1(OPTIONS)72 554.4 Q F0(Fla)108 566.4 Q .187(w\214nder has a nu\ mber of options, which can be grouped into options that control its o) -.15 F .187(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 .691(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 .119(2013 Edition\) section `)108 602.4 R .119(`Utility Con)-.74 F -.15(ve)-.4 G(ntions').15 E 2.618('. Fla)-.74 F .118 (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.003('a)-.74 G(nd)-3.003 E F2 .503(GNU Coding Standar) 3.003 F(ds)-.37 E F0 -.74(``)3.003 G .502 (Standards for Command Line Interf).74 F(aces')-.1 E 3.002('. Long)-.74 F .502(option ar)3.002 F(gu-)-.18 E .456(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 .229 (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.728 E F0 .228(be accessed using long)2.728 F(option con)108 662.4 Q -.15(ve)-.4 G (ntions.).15 E/F4 10/Times-Bold@0 SF(Documentation)87 691.2 Q (\255\255help)108 703.2 Q F0(Fla)72 768 Q 165.545(w\214nder 4)-.15 F (Apr 2018)2.5 E(3)206.225 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)168 84 Q 2.5(wu)-.25 G(sage \(help\) information.)-2.5 E F1 108 112.8 Q(ersion)-.1 E F0(Sho)168 112.8 Q(ws \(just\) the v) -.25 E(ersion number and e)-.15 E(xits.)-.15 E F1(\255\255listrules)108 141.6 Q F0 2.074(List the terms \(tok)168 141.6 R 2.074 (ens\) that trigger further e)-.1 F 2.075(xamination, their def)-.15 F 2.075(ault risk le)-.1 F -.15(ve)-.25 G 2.075(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 .066 (are primarily names of potentially-dangerous functions.)168 165.6 R .067(Note that the reported risk le)5.067 F -.15(ve)-.25 G 2.567(la).15 G(nd)-2.567 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)168 242.4 Q 2.674(wt)-.25 G .174(he use of symbolic links; normally symbolic links are skipped.) -2.674 F(Don')5.173 E 2.673(tu)-.18 G .173(se this option)-2.673 F .354 (if you')168 254.4 R .354(re analyzing code by others; attack)-.5 F .355 (ers could do man)-.1 F 2.855(yt)-.15 G .355 (hings to cause problems for an)-2.855 F 1.084 (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 .429(uld cause \215a).1 F .429 (w\214nder to run `)-.15 F(`fore)-.74 E -.15(ve)-.25 G(r').15 E 2.929 ('. Another)-.74 F .428(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.956(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.219 (v/zero or C:\\mystuf)-.25 F 3.719(f\\com1\). Note)-.25 F 1.218 (that for \215a)3.719 F 1.218(w\214nder v)-.15 F 1.218 (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.017(yn)-.15 G 1.517(ormally include v)-4.017 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.516(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.296(Ignored. Historically)168 444 R 2.796 (this disabled follo)5.296 F 2.796(wing symbolic links; this beha)-.25 F 2.797(vior is no)-.2 F 5.297(wt)-.25 G(he)-5.297 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 .228 (Examine the selected \214les or directories, b)168 501.6 R .227 (ut only report hits in lines that are added or modi-)-.2 F .567 (\214ed as described in the gi)168 513.6 R -.15(ve)-.25 G 3.067(np).15 G .568(atch \214le.)-3.067 F .568 (The patch \214le must be in a recognized uni\214ed dif)5.568 F(f)-.25 E 2.294(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.293 (f", or "git dif)-.25 F 4.793(f[)-.25 G(commit]"\).)-4.793 E(Fla)168 537.6 Q .833(w\214nder assumes that the patch has already been applied \ to the \214les.)-.15 F .833(The patch \214le can)5.833 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.731(ni).15 G 2.731(nt)-2.731 G .231(he patch \214le are used to deter\ mine which lines were changed, so if you ha)-2.731 F .532 -.15(ve m)-.2 H(odi-).15 E .498(\214ed the \214les since the patch \214le w)168 573.6 R .498(as created, re)-.1 F .497(generate the patch \214le \214rst.)-.15 F(Be)5.497 E -.1(wa)-.25 G .497(re that the).1 F .397 (\214le names of the ne)168 585.6 R 2.897<778c>-.25 G .397(les gi)-2.897 F -.15(ve)-.25 G 2.897(ni).15 G 2.897(nt)-2.897 G .398 (he patch \214le must match e)-2.897 F(xactly)-.15 E 2.898(,i)-.65 G .398(ncluding upper/lo)-2.898 F(wer)-.25 E .045 (case, path pre\214x, and directory separator \(\\ vs. /\).)168 597.6 R .045(Only uni\214ed dif)5.045 F 2.544(ff)-.25 G .044 (ormat is accepted \(GNU)-2.544 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 .043(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.528 E F0 2.528(,b)C .028(ecause \215a)-2.528 F .027 (w\214nder will then try to treat the \214le as a source \214le.)-.15 F .027(This will often w)5.027 F(ork,)-.1 E -.2(bu)168 657.6 S 3.348(tt).2 G .849(he line numbers will be relati)-3.348 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 .163 (the source code.)168 669.6 R .163(Note that you)5.163 F F1(must)2.663 E F0 .162(also pro)2.662 F .162 (vide the actual \214les to analyze, and not just the)-.15 F .422 (patch \214le; when using)168 681.6 R F12.922 E F0 .423 (\214les are only reported if the)2.923 F 2.923(ya)-.15 G .423 (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 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E(4) 206.225 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)144 112.8 Q 2.5(wo)-.25 G(nly functions that obtain data\ from 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)144 158.4 R -.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 .437(Do not include hits that are lik)144 216 R .437 (ely to be f)-.1 F .438(alse positi)-.1 F -.15(ve)-.25 G 2.938 (s. Currently).15 F 2.938(,t)-.65 G .438(his means that function names) -2.938 F .992(are ignored if the)144 228 R(y')-.15 E .992(re not follo) -.5 F .991(wed by "\(", and that declarations of character arrays aren') -.25 F 3.491(tn)-.18 G(oted.)-3.491 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.839(ordinary v) 144 252 R 4.339(ariable. This)-.25 F(isn')4.339 E 4.339(tt)-.18 G 1.839 (he def)-4.339 F 1.838(ault, because this also increases the lik)-.1 F 1.838(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)144 321.6 Q -.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 .413(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 .412 (or e)-.15 F .412(xample, to)-.15 F 1.753 (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.254(xC)-.15 G (WE-120')-4.254 E 4.254('. These)-.74 F 1.754(option \215ag)4.254 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)168 472.8 Q 4.024(wt)-.25 G 1.524(he column number \(as well as the \214le \ name and line number\) of each hit; this is)-4.024 F(sho)168 484.8 Q .609(wn after the line number by adding a colon and the column number i\ n the line \(the \214rst)-.25 F .562 (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.374 (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.375(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)168 566.4 Q 4.25 (wc)-.25 G(onte)-4.25 E 1.75(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.749(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)168 607.2 R .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 .023(wed by 0)-.25 F .857(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.314 (\255\255quiet and \255\255dataonly)168 643.2 R 6.314(.T)-.65 G 1.314 (he headers are mostly self-e)-6.314 F(xplanatory)-.15 E 6.313(.")-.65 G 1.313(File" is the \214lename,)-6.313 F .164("Line" is the line number) 168 655.2 R 2.664(,")-.4 G .164 (Column" is the column \(starting from 1\), "Le)-2.664 F -.15(ve)-.25 G .165(l" is the risk le).15 F -.15(ve)-.25 G(l).15 E .42 (\(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 .419(Name" is the name of the)-2.919 F 1.252 (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 .335 (one or more CWEs, "Conte)168 703.2 R .335 (xt" is the source code line triggering the hit, and "Fingerprint" is) -.15 F .047(the SHA-256 hash of the conte)168 715.2 R .046 (xt once its leading and trailing whitespace ha)-.15 F .346 -.15(ve b) -.2 H .046(een remo).15 F -.15(ve)-.15 G(d).15 E 1.054(\(the \214ngerpr\ int may help detect and eliminate later duplications\).)168 727.2 R 1.055(If you use Python3, the)6.055 F(Fla)72 768 Q 165.545(w\214nder 4) -.15 F(Apr 2018)2.5 E(5)206.225 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')168 129.6 Q 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)168 175.2 S (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')168 220.8 Q 2.5(tj)-.18 G(ust w)-2.5 E (ait until the end\).)-.1 E F1(\255\255singleline)108 249.6 Q(-S)108 266.4 Q F0 1.267(Display as single line of te)168 266.4 R 1.267 (xt output for each hit.)-.15 F 1.267 (Useful for interacting with compilation)6.267 F(tools.)168 278.4 Q F1 (\255\255omittime)108 307.2 Q F0 .82(Omit timing information.)168 307.2 R .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 319.2 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 348 Q 108 364.8 Q F0(Don')168 364.8 Q 3.153(td)-.18 G .652 (isplay status information \(i.e., which \214les are being e)-3.153 F .652(xamined\) while the analysis is)-.15 F(going on.)168 376.8 Q F1 108 405.6 Q(or)-.18 E(-le)-.37 E -.1(ve)-.15 G(l=LEVEL).1 E F0 1.48(Return a nonzero \(f)168 417.6 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 429.6 Q .204(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.791(uous inte)168 441.6 R 1.792(gration script, especially if you mark kno)-.15 F 1.792 (wn-okay lines as "\215a)-.25 F 1.792(w\214nder: ignore".)-.15 F 1.233 (Usually you w)168 453.6 R 1.233(ant le)-.1 F -.15(ve)-.25 G 3.733(lt) .15 G 3.733(ob)-3.733 G 3.733(ef)-3.733 G 1.232 (airly high, such as 4 or 5.)-3.833 F 1.232(By def)6.232 F 1.232 (ault, \215a)-.1 F 1.232(w\214nder returns 0)-.15 F (\(true\) on a successful run.)168 465.6 Q F1(Hitlist Management)87 494.4 Q108 506.4 Q -.1(ve)-.25 G(hitlist=).1 E/F2 10 /Times-Italic@0 SF(F)A F0(Sa)168 518.4 Q .3 -.15(ve a)-.2 H (ll resulting hits \(the "hitlist"\) to F).15 E(.)-.8 E F1 (\255\255loadhitlist=)108 547.2 Q F2(F)A F0 .44 (Load the hitlist from F instead of analyzing source programs.)168 559.2 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 571.2 R 2.707(These are internally implemented using)7.707 F(Python')168 583.2 Q 3.708(s")-.55 G 1.208(pickle" f)-3.708 F(acility)-.1 E 3.708(,w)-.65 G 1.208(hich trusts the input.)-3.708 F 1.209 (Note that stored hitlists often cannot be)6.208 F 2.652 (read when using an older v)168 595.2 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.652(as used b)-.1 F(ut) -.2 E<8d61>168 607.2 Q 1.435(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.436(oaded by running \215a)-3.936 F 1.436(w\214nder with)-.15 F(Python 2.)168 619.2 Q F1(\255\255diffhitlist=)108 648 Q F2(F)A F0(Sho) 168 660 Q 3.54(wo)-.25 G 1.039(nly hits \(loaded or analyzed\) not in F) -3.54 F 6.039(.F)-.8 G -.1(wa)-2.5 G 3.539(sp).1 G 1.039 (resumably created pre)-3.539 F 1.039(viously using)-.25 F168 672 Q -.15(ve)-.2 G 2.865(hitlist. W).15 F .365(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.366 E .668(the \255\255loadhitlist option is not pro)168 684 R .668 (vided, this will sho)-.15 F 3.168(wt)-.25 G .668 (he hits in the analyzed source code)-3.168 F .143 (\214les that were not pre)168 696 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.644(wt) -.25 G(he)-2.644 E .095(hits in the loaded hitlist not in F)168 708 R 5.094(.T)-.8 G .094(he dif)-5.094 F .094(ference algorithm is conserv) -.25 F(ati)-.25 E -.15(ve)-.25 G 2.594(;h).15 G .094(its are only con-) -2.594 F .683(sidered the `)168 720 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(Fla)72 768 Q 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E(6)206.225 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(name, and risk le)168 84 Q -.15 (ve)-.25 G(l.).15 E/F1 10/Times-Bold@0 SF(Character Encoding)87 112.8 Q F0(Fla)108 124.8 Q .871(w\214nder presumes that the character encoding \ your system uses is also the character encoding used by)-.15 F 1.355 (your source \214les.)108 136.8 R(Ev)6.355 E 1.355(en if this isn')-.15 F 3.856(tc)-.18 G 1.356(orrect, if you run \215a)-3.856 F 1.356 (w\214nder with Python 2 these non-conformities)-.15 F (often do not impact processing in practice.)108 148.8 Q(Ho)108 172.8 Q (we)-.25 E -.15(ve)-.25 G 1.328 -.4(r, i).15 H 3.028(fy).4 G .528 (ou run \215a)-3.028 F .528 (w\214nder with Python 3, this can be a problem.)-.15 F .528(Python 3 w) 5.528 F .528(ants the w)-.1 F .527(orld to al)-.1 F -.1(wa)-.1 G(ys).1 E 1.464(use encodings perfectly correctly)108 184.8 R 3.964(,e)-.65 G -.15 (ve)-4.214 G 1.464(rywhere, e).15 F -.15(ve)-.25 G 3.964(nt).15 G 1.464 (hough the w)-3.964 F 1.464(orld often doesn')-.1 F 3.965(tc)-.18 G 1.465(are what Python 3)-3.965 F -.1(wa)108 196.8 S 2.845(nts. This).1 F .345(is a problem e)2.845 F -.15(ve)-.25 G 2.845(ni).15 G 2.845(ft) -2.845 G .345(he non-conforming te)-2.845 F .345 (xt is in comments or strings \(where it often doesn')-.15 F(t)-.18 E 2.986(matter\). Python)108 208.8 R 2.986(3f)2.986 G .486(ails to pro) -3.086 F .486(vide useful b)-.15 F .486 (uilt-ins to deal with the messiness of the real w)-.2 F .487 (orld, so it')-.1 F 2.987(sn)-.55 G(on-)-2.987 E(tri)108 220.8 Q (vial to deal with this problem without depending on e)-.25 E (xternal libraries \(which we')-.15 E(re trying to a)-.5 E -.2(vo)-.2 G (id\).).2 E 2.5(As)108 244.8 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 10/Times-Italic@0 SF(UnicodeDecodeErr)108 268.8 Q (or: 'utf-8' codec can')-.45 E 2.5(td)-.3 G (ecode byte ... in position ...: in)-2.5 E(valid continuation byte)-.4 E F0(If this happens to you, there are se)108 292.8 Q -.15(ve)-.25 G (ral options.).15 E .463(The \214rst option is to con)108 316.8 R -.15 (ve)-.4 G .462 (rt the encoding of the \214les to be analyzed so that it').15 F 2.962 (sas)-.55 G .462(ingle encoding \(usually)-2.962 F 1.128 (the system encoding\).)108 328.8 R -.15(Fo)6.128 G 3.628(re).15 G 1.128 (xample, the program "icon)-3.778 F 1.128(v" can be used to con)-.4 F -.15(ve)-.4 G 1.128(rt encodings.).15 F 1.128(This w)6.128 F(orks)-.1 E .258(well if some \214les ha)108 340.8 R .558 -.15(ve o)-.2 H .258 (ne encoding, and some ha).15 F .558 -.15(ve a)-.2 H(nother).15 E 2.758 (,b)-.4 G .258(ut the)-2.958 F 2.758(ya)-.15 G .258 (re consistent within a single \214le.)-2.758 F(If)5.257 E .07 (the \214les ha)108 352.8 R .37 -.15(ve e)-.2 H .07 (ncoding errors, you').15 F .07(ll ha)-.1 F .37 -.15(ve t)-.2 H 2.57 <6f8c>.15 G 2.57(xt)-2.57 G 2.57(hem. I)-2.57 F .07 (strongly recommend using the UTF-8 encoding for)2.57 F (all source code and in the system itself; if you do that, man)108 364.8 Q 2.5(yp)-.15 G(roblems disappear)-2.5 E(.)-.55 E .366 (The second option is to tell \215a)108 388.8 R .366 (w\214nder what the encoding of the \214les is.)-.15 F .366 (E.G., you can set the LANG en)5.366 F(vi-)-.4 E .549(ronment v)108 400.8 R 3.049(ariable. Y)-.25 F .549 (ou can set PYTHONIOENCODING to the encoding you w)-1.1 F .55 (ant your output to be in, if)-.1 F(that')108 412.8 Q 2.5(sd)-.55 G(if) -2.5 E 2.5(ferent. This)-.25 F(in theory w)2.5 E(ould w)-.1 E(ork, b)-.1 E(ut I ha)-.2 E -.15(ve)-.2 G(n').15 E 2.5(th)-.18 G (ad much success with this.)-2.5 E(The third option is to run \215a)108 436.8 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/F3 10.95/Times-Bold@0 SF (EXAMPLES)72 465.6 Q F0 .226(Here are v)108 477.6 R .226(arious e)-.25 F .226(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 .225(xamples sho)-.15 F 2.725(wv) -.25 G .225(arious simple command-)-2.975 F 1.273(line options.)108 489.6 R(Fla)6.273 E 1.273(w\214nder is designed to w)-.15 F 1.274 (ork well with te)-.1 F 1.274(xt editors and inte)-.15 F 1.274 (grated de)-.15 F -.15(ve)-.25 G 1.274(lopment en).15 F(viron-)-.4 E (ments, so the ne)108 501.6 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 F1(Simple command-line options)87 530.4 Q(\215aw\214nder /usr/sr)108 542.4 Q(c/linux-3.16)-.18 E F0 1.705 (Examine all the C/C++ \214les in the directory /usr/src/linux-3.16 and\ all its subdirectories)168 554.4 R(\(recursi)168 566.4 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 578.4 Q F1 (\215aw\214nder \255\255minle)108 607.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 619.2 R -.15(ve)-.25 G .153(ly\); only).15 F (report vulnerabilities le)168 631.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 F1(\215aw\214nder \255\255inputs mydir)108 660 Q F0 1.03(E\ xamine all the C/C++ \214les in mydir and its subdirectories \(recursi) 168 672 R -.15(ve)-.25 G 1.03(ly\), and report func-).15 F (tions that tak)168 684 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(Fla)72 768 Q 165.545 (w\214nder 4)-.15 F(Apr 2018)2.5 E(7)206.225 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/F1 10/Times-Bold@0 SF (\215aw\214nder \255\255ne)108 84 Q -.1(ve)-.15 G(rignor).1 E 2.5(em) -.18 G(ydir)-2.5 E F0 .3(Examine all the C/C++ \214les in the directory\ mydir and its subdirectories, including e)168 96 R -.15(ve)-.25 G 2.8 (nt).15 G(he)-2.8 E(hits mark)168 108 Q (ed for ignoring in the code comments.)-.1 E F1 (\215aw\214nder \255\255csv .)108 136.8 Q F0 .252 (Examine the current directory do)168 148.8 R .253(wn \(recursi)-.25 F -.15(ve)-.25 G .253(ly\), and report all hits in CSV format.).15 F .253 (This is)5.253 F 1.395(the recommended form if you w)168 160.8 R 1.395 (ant to further process \215a)-.1 F 1.394 (w\214nder output using other tools)-.15 F (\(such as data correlation tools\).)168 172.8 Q F1 (\215aw\214nder \255QD mydir)108 201.6 Q F0 .092 (Examine mydir and report only the actual results \(remo)168 213.6 R .093(ving the header and footer of the out-)-.15 F 3.062(put\). This)168 225.6 R .561(form may be useful if the output will be piped into other \ tools for further analy-)3.062 F .341 (sis, though CSV format is probably the better choice in that case.)168 237.6 R .342(The \255C \(\255\255columns\) and)5.342 F (\255S \(\255\255singleline\) options can also be useful if you')168 249.6 Q(re piping the data into other tools.)-.5 E F1 (\215aw\214nder \255QDSC mydir)108 278.4 Q F0 .554(Examine mydir)168 290.4 R 3.054(,r)-.4 G .554 (eporting only the actual results \(no header or footer\).)-3.054 F .553 (Each hit is reported)5.553 F 1.119 (on one line, and column numbers are reported.)168 302.4 R 1.12 (This can be a useful command if you are)6.119 F(feeding \215a)168 314.4 Q(w\214nder output to other tools.)-.15 E F1 (\215aw\214nder \255\255quiet \255\255html \255\255context mydir > r)108 343.2 Q(esults.html)-.18 E F0 1.185(Examine all the C/C++ \214les in th\ e directory mydir and its subdirectories, and produce an)168 355.2 R .277(HTML formatted v)168 367.2 R .277(ersion of the results.)-.15 F .278(Source code management systems \(such as Source-)5.277 F -.15(Fo) 168 379.2 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 408 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 420 R 5.406 (.D)-.65 G(on')-5.406 E 2.906(tr)-.18 G .406 (eport on the status of processing,)-2.906 F(and sa)168 432 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 460.8 Q -.1(ve)-.25 G(d.hits *.[ch]).1 E F0 .324 (Examine all .c and .h \214les in the current directory)168 472.8 R 2.825(,a)-.65 G .325(nd sho)-2.825 F 2.825(wa)-.25 G .625 -.15(ny h) -2.825 H .325(its that weren').15 F 2.825(ta)-.18 G .325(lready in) -2.825 F .921(the \214le sa)168 484.8 R -.15(ve)-.2 G 3.421 (d.hits. This).15 F .921(can be used to sho)3.421 F 3.421(wo)-.25 G .921 (nly the `)-3.421 F(`ne)-.74 E(w')-.25 E 3.42('v)-.74 G .92 (ulnerabilities in a modi\214ed)-3.42 F(program, if sa)168 496.8 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 525.6 Q(ecent.patch .)-.18 E F0 .641 (Examine the current directory recursi)168 537.6 R -.15(ve)-.25 G(ly).15 E 3.141(,b)-.65 G .642(ut only report lines that were changed or added) -3.341 F(in the already-applied patch\214le named)168 549.6 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 578.4 Q(egex "CWE-120|CWE-126" sr)-.18 E (c/)-.18 E F0(Examine directory)168 590.4 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 619.2 Q -.1(vo)-.4 G(king fr).1 E(om vim)-.18 E F0 .178(The te) 108 631.2 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 643.2 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 .322(First, you need to in)108 660 R -.2(vo)-.4 G .522 -.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 .323(ays to do this.)-2.922 F .323(The \214rst w)5.323 F(ay)-.1 E .218 (is to start \215a)108 672 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(run\) vim, and then in)108 684 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 700.8 S 3.071 (rt).15 G .571(he \214rst w)-3.071 F(ay)-.1 E 3.071(,r)-.65 G .572 (un \215a)-3.071 F .572(w\214nder and store its output in some FLA)-.15 F .572(WFILE \(say "\215a)-.9 F .572(w\214le"\), then in)-.15 F -.2(vo) -.4 G .772 -.1(ke v).2 H(im).1 E .486(using its -q option, lik)108 712.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.017(be done a le)108 724.8 R 1.017(gion of w)-.15 F 3.517(ays. One)-.1 F 1.017(is to in)3.517 F -.2 (vo)-.4 G 1.218 -.1(ke \215).2 H -.15(aw).1 G 1.018 (\214nder using a shell command, ":!\215a).15 F(w\214nder)-.15 E 1.018 (-command >)-.2 F(Fla)72 768 Q 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E (8)206.225 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(FLA)108 84 Q .252 (WFILE", then follo)-.9 F 2.752(wt)-.25 G .251 (hat with the command ":cf FLA)-2.752 F 2.751(WFILE". Another)-.9 F -.1 (wa)2.751 G 2.751(yi).1 G 2.751(st)-2.751 G 2.751(os)-2.751 G .251 (tore the \215a)-2.751 F(w\214nder)-.15 E(command in your mak)108 96 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 112.8 R .417 (w\214nder to run.)-.15 F 2.917(Ap)5.417 G .418 (lausible command, which places each hit)-2.917 F(in its o)108 124.8 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 141.6 Q F0 -1.1(Yo)108 170.4 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 .011(":cN" displays the pre)108 182.4 R .011 (vious hit, and ":cr" re)-.25 F .012(winds back to the \214rst hit.)-.25 F .012(":copen" will open a windo)5.012 F 2.512(wt)-.25 G 2.512(os) -2.512 G(ho)-2.512 E(w)-.25 E .203 (the current list of hits, called the "quick\214x windo)108 194.4 R .202 (w"; ":cclose" will close the quick\214x windo)-.25 F 4.002 -.65(w. I) -.25 H 2.702(ft).65 G .202(he b)-2.702 F(uf)-.2 E(fer)-.25 E .25 (in the used windo)108 206.4 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 218.4 Q 2.588(es)-.1 G .088(ure the windo)-2.588 F 2.588(wc)-.25 G .088 (ontains a b)-2.588 F(uf)-.2 E .087 (fer which can be abandoned before trying to jump to a ne)-.25 F 2.587 <778c>-.25 G .087(le, say by)-2.587 F(sa)108 230.4 Q (ving the \214le; this pre)-.2 E -.15(ve)-.25 G (nts accidental data loss.).15 E F1(In)87 259.2 Q -.1(vo)-.4 G(king fr) .1 E(om emacs)-.18 E F0 .269(The te)108 271.2 R .269(xt editor / operat\ ing system emacs includes "grep mode" and "compile mode" mechanisms tha\ t w)-.15 F(ork)-.1 E .825(well with \215a)108 283.2 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 295.2 Q 2.5(yp)-.15 G (roblems you \214nd.)-2.5 E 1.426(First, you need to in)108 312 R -.2 (vo)-.4 G 1.626 -.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.427 G 3.927(uc)1.1 G 1.427(an use "grep mode" or)-3.927 F 2.646 ("compile mode" to create this list.)108 324 R 2.645 (Often "grep mode" is more con)7.645 F -.15(ve)-.4 G 2.645 (nient; it lea).15 F -.15(ve)-.2 G 5.145(sc).15 G 2.645(ompile mode) -5.145 F .537(untouched so you can easily recompile once you')108 336 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 .537(ant to jump to)-.1 F .51(the e)108 348 R .51 (xact column position of a hit, compile mode may be more con)-.15 F -.15 (ve)-.4 G .509(nient because emacs can use the col-).15 F (umn output of \215a)108 360 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.064 -.8(To u)108 376.8 T .465(se grep mode, enter the command "M-x grep" and then enter the need\ ed \215a).8 F .465(w\214nder command.)-.15 F 2.065 -.8(To u)5.465 H(se) .8 E 1.307(compile mode, enter the command "M-x compile" and enter the \ needed \215a)108 388.8 R 1.307(w\214nder command.)-.15 F 1.307 (This is a)6.307 F(meta-k)108 400.8 Q .436 -.15(ey c)-.1 H .136 (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.637(\). As).15 F 1.016(with all emacs commands, you')108 412.8 R 1.016 (ll need to press RETURN after typing "grep" or "compile".)-.1 F 1.015 (So on man)6.015 F(y)-.15 E(systems, the grep mode is in)108 424.8 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 441.6 S 3.563(ut)1.1 G 1.063(hen need to enter a command, remo)-3.563 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.064(plausible com-)-2.499 F(mand is:)108 453.6 Q F1 (\215aw\214nder \255SQDC .)108 470.4 Q F0 .135(This command mak)108 487.2 R .135(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 .134(The quiet and)5.134 F .546(dataonly options remo)108 499.2 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 511.2 Q(ws.)-.15 E 1.312(Once you')108 528 R 1.612 -.15(ve i)-.5 H -1.9 -.4 (nv o).15 H -.1(ke).4 G 3.812<648d>.1 G -.15(aw)-3.812 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.311(The command C-x \222)6.311 F 1.247 (\(Control-x backtick\) visits the source code location for the ne)108 540 R 1.247(xt w)-.15 F 1.248(arning message.)-.1 F 1.248 (C-u C-x \222 \(control-u)6.248 F .808 (control-x backtick\) restarts from the be)108 552 R 3.307(ginning. Y) -.15 F .807(ou can visit the source for an)-1.1 F 3.307(yp)-.15 G .807 (articular error message)-3.307 F 1.64(by mo)108 564 R 1.64 (ving to that hit message in the *compilation* b)-.15 F(uf)-.2 E 1.641 (fer or *grep* b)-.25 F(uf)-.2 E 1.641(fer and typing the return k)-.25 F -.15(ey)-.1 G(.)-.5 E(\(T)108 576 Q 2.853 (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.852 (ou can also click the)-1.1 F(Mouse-2 b)108 588 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 .237(If you w)108 604.8 R .237 (ant to use grep mode to jump to speci\214c columns of a hit, you')-.1 F .238(ll need to specially con\214gure emacs)-.1 F 1.279(to do this.)108 616.8 R 2.879 -.8(To d)6.279 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.278 (riable tells Emacs ho).25 F 3.778(wt)-.25 G(o)-3.778 E .348 (parse output of a "grep" command, similar to the v)108 628.8 R .349 (ariable "compilation-error)-.25 F(-re)-.2 E(ge)-.15 E .349 (xp-alist" which lists v)-.15 F(ari-)-.25 E (ous formats of compilation error messages.)108 640.8 Q F1(In)87 669.6 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 681.6 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(Fla)72 768 Q 165.545(w\214nder 4)-.15 F (Apr 2018)2.5 E(9)206.225 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/F1 10.95/Times-Bold@0 SF (COMMON WEAKNESS ENUMERA)72 84 Q(TION \(CWE\))-1.04 E F0 1.218 (The Common W)108 96 R 1.218(eakness Enumeration \(CWE\) is `)-.8 F 1.218(`a formal list or dictionary of common softw)-.74 F 1.217 (are weak-)-.1 F .211(nesses that can occur in softw)108 108 R(are')-.1 E 2.711(sa)-.55 G .212 (rchitecture, design, code or implementation that can lead to e)-2.711 F (xploitable)-.15 E 1.186(security vulnerabilities...)108 120 R 1.186 (created to serv)6.186 F 3.686(ea)-.15 G 3.685(sac)-3.686 G 1.185 (ommon language for describing softw)-3.685 F 1.185(are security weak-) -.1 F(nesses')108 132 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 148.8 Q .422(w\214nder supports the CWE and is of)-.15 F .422 (\214cially CWE-Compatible.)-.25 F .423 (Hit descriptions typically include a rele-)5.422 F -.25(va)108 160.8 S .763(nt Common W).25 F .763(eakness Enumeration \(CWE\) identi\214er in\ parentheses where there is kno)-.8 F .762(wn to be a rele-)-.25 F -.25 (va)108 172.8 S .067(nt CWE.).25 F -.15(Fo)5.067 G 2.567(re).15 G .067 (xample, man)-2.717 F 2.567(yo)-.15 G 2.567(ft)-2.567 G .067(he b)-2.567 F(uf)-.2 E(fer)-.25 E .068 (-related hits mention CWE-120, the CWE identi\214er for `)-.2 F(`b)-.74 E(uf)-.2 E(fer)-.25 E(cop)108 184.8 Q 2.536(yw)-.1 G .036 (ithout checking size of input')-2.536 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 196.8 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 208.8 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 225.6 R 3.186<778d>-.25 G -.15(aw)-3.186 G .686 (\214nder handles them.).15 F .685(If the)5.685 F .393 (same entry maps to multiple CWEs simultaneously)108 237.6 R 2.894(,a) -.65 G .394(ll the CWE mappings are listed as separated by com-)-2.894 F 3.377(mas. This)108 249.6 R .876 (often occurs with CWE-20, Improper Input V)3.377 F .876 (alidation; thus the report "CWE-676, CWE-120")-1.11 F .052(maps to tw) 108 261.6 R 2.552(oC)-.1 G 2.552(WEs. In)-2.552 F .053(addition, \215a) 2.552 F .053(w\214nder pro)-.15 F .053 (vides additional information for those who are are interested)-.15 F .494(in the CWE/SANS top 25 list 2011 \(https://cwe.mitre.or)108 273.6 R .493(g/top25/\) when mappings are not directly to them.)-.18 F(Man)108 285.6 Q 3.594(yp)-.15 G 1.094(eople will w)-3.594 F 1.095(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 297.6 S(r\215o).15 E 2.721 (w\). The)-.25 F .221(challenge is that some \215a)2.721 F .22 (w\214nder hits map to a more general CWE that w)-.15 F .22 (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 309.6 R 3.949(item. T)108 321.6 R 3.949(or)-.8 G(esolv)-3.949 E 3.949(et)-.15 G 1.449(his, in some cases \215a)-3.949 F 1.449 (w\214nder will list a sequence of CWEs in the format "more-gen-)-.15 F 1.796 (eral/more-speci\214c", where the CWE actually being mapped is follo)108 333.6 R 1.797(wed by a "!".)-.25 F 1.797(This is al)6.797 F -.1(wa)-.1 G 1.797(ys done).1 F(whene)108 345.6 Q -.15(ve)-.25 G 3.269(ra\215).15 G 1.068 -.15(aw i)-3.269 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.768 E .356("CWE-11\ 9!/CWE-120" means that the vulnerability is mapped to CWE-119 and that \ CWE-120 is a subset)108 357.6 R .834(of CWE-119.)108 369.6 R .833(In co\ ntrast, "CWE-362/CWE-367!" means that the hit is mapped to CWE-367, a s\ ubset of)5.834 F 2.578(CWE-362. Note)108 381.6 R .078 (that this is a subtle syntax change from \215a)2.578 F .078 (w\214nder v)-.15 F .078(ersion 1.31; in \215a)-.15 F .079(w\214nder v) -.15 F .079(ersion 1.31,)-.15 F 1.241 (the form "more-general:more-speci\214c" meant what is no)108 393.6 R 3.741(wl)-.25 G 1.241(isted as "more-general!/more-speci\214c", while) -3.741 F .006 ("more-general/more-speci\214c" meant "more-general/more-speci\214c!".) 108 405.6 R -.8(To)5.006 G .007(ols can handle both the v).8 F .007 (ersion 1.31)-.15 F .689(and the current format, if the)108 417.6 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 429.6 Q (These mapping mechanisms simplify searching for certain CWEs.)5 E .77 (CWE v)108 446.4 R .77(ersion 2.7 \(released June 23, 2014\) w)-.15 F .771(as used for the mapping.)-.1 F .771 (The current CWE mappings select)5.771 F .213 (the most speci\214c CWE the tool can determine.)108 458.4 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 470.4 R 1.017(tion\), b)108 482.4 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 494.4 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 .967(than the mappings currently implemented.)108 506.4 R .966(This also means that it is unlik)5.966 F .966 (ely to need much updating for)-.1 F 1.688(map currenc)108 518.4 R 1.688 (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.189(lt).15 G 1.689(hat CWE)-4.189 F 1.96(changes w)108 530.4 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 542.4 Q .103(w-cwes", so there is con\214dence that this list is correct.)-.25 F .104(Please report CWE mapping problems as b)5.104 F .104(ugs if)-.2 F (you \214nd an)108 554.4 Q -.65(y.)-.15 G(Fla)108 571.2 Q .708 (w\214nder may f)-.15 F .708(ail to \214nd a vulnerability)-.1 F 3.208 (,e)-.65 G -.15(ve)-3.458 G 3.208(ni).15 G 3.207<668d>-3.208 G -.15(aw) -3.207 G .707(\214nder co).15 F -.15(ve)-.15 G .707 (rs one of these CWE weaknesses.).15 F(That)5.707 E .814(said, \215a)108 583.2 R .815 (w\214nder does \214nd vulnerabilities listed by the CWEs it co)-.15 F -.15(ve)-.15 G .815(rs, and it will not report lines without).15 F 2.027 (those vulnerabilities in man)108 595.2 R 4.527(yc)-.15 G 4.527 (ases. Thus,)-4.527 F 2.027(as required for an)4.527 F 4.527(yt)-.15 G 2.026(ool intending to be CWE compatible,)-4.527 F<8d61>108 607.2 Q 2.212(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.213 (alse ne)-.1 F -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G 4.713(sl).15 G 2.213(ess than 100%.)-4.713 F(Fla)108 619.2 Q .281(w\214nder almost al) -.15 F -.1(wa)-.1 G .281(ys reports whene).1 F -.15(ve)-.25 G 2.781(ri) .15 G 2.781<748c>-2.781 G .28 (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 631.2 Q(ail \(see B)-.1 E(UGS belo)-.1 E(w\).)-.25 E (Fla)108 648 Q .206(w\214nder can report on the follo)-.15 F .206 (wing CWEs \(these are the CWEs that \215a)-.25 F .207(w\214nder co)-.15 F -.15(ve)-.15 G .207(rs; `).15 F(`*')-.74 E 2.707('m)-.74 G .207 (arks those)-2.707 F(in the CWE/SANS top 25 list\):)108 660 Q<83>108 676.8 Q(CWE-20: Improper Input V)118 676.8 Q(alidation)-1.11 E<83>108 693.6 Q(CWE-22: Improper Limitation of a P)118 693.6 Q (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<83>108 710.4 Q .365(CWE-78:\ Improper Neutralization of Special Elements used in an OS Command \(`) 118 710.4 R .364(`OS Command Injec-)-.74 F(tion')118 722.4 Q('\)*)-.74 E (Fla)72 768 Q 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E(10)201.225 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<83>108 84 Q 1.991(CWE-119: Imp\ roper Restriction of Operations within the Bounds of a Memory Buf)118 84 R 1.991(fer \(a parent of)-.25 F(CWE-120*, so this is sho)118 96 Q (wn as CWE-119!/CWE-120\))-.25 E<83>108 112.8 Q(CWE-120: Buf)118 112.8 Q (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 <83>108 129.6 Q(CWE-126: Buf)118 129.6 Q(fer Ov)-.25 E(er)-.15 E(-read) -.2 E<83>108 146.4 Q(CWE-134: Uncontrolled F)118 146.4 Q(ormat String*) -.15 E<83>108 163.2 Q(CWE-190: Inte)118 163.2 Q(ger Ov)-.15 E(er\215o) -.15 E 2.5(wo)-.25 G 2.5(rW)-2.5 G(raparound*)-2.5 E<83>108 180 Q (CWE-250: Ex)118 180 Q(ecution with Unnecessary Pri)-.15 E(vile)-.25 E (ges)-.15 E<83>108 196.8 Q(CWE-327: Use of a Brok)118 196.8 Q (en or Risk)-.1 E 2.5(yC)-.15 G(ryptographic Algorithm*)-2.5 E<83>108 213.6 Q .407(CWE-362: Concurrent Ex)118 213.6 R .407 (ecution using Shared Resource with Improper Synchronization \(`)-.15 F .407(`Race Condi-)-.74 F(tion')118 225.6 Q('\))-.74 E<83>108 242.4 Q (CWE-377: Insecure T)118 242.4 Q(emporary File)-.7 E<83>108 259.2 Q (CWE-676: Use of Potentially Dangerous Function*)118 259.2 Q<83>108 276 Q(CWE-732: Incorrect Permission Assignment for Critical Resource*)118 276 Q<83>108 292.8 Q .595(CWE-785: Use of P)118 292.8 R .596 (ath Manipulation Function without Maximum-sized Buf)-.15 F .596 (fer \(child of CWE-120*, so)-.25 F(this is sho)118 304.8 Q (wn as CWE-120/CWE-785\))-.25 E<83>108 321.6 Q (CWE-807: Reliance on Untrusted Inputs in a Security Decision*)118 321.6 Q<83>108 338.4 Q (CWE-829: Inclusion of Functionality from Untrusted Control Sphere*)118 338.4 Q -1.1(Yo)108 355.2 S 2.582(uc)1.1 G .081 (an select a speci\214c subset of CWEs to report by using the `)-2.582 F <60adad7265>-.74 E(ge)-.15 E(x')-.15 E 2.581('\()-.74 G .081 (-e\) option.)-2.581 F .081(This option accepts)5.081 F 3.991(ar)108 367.2 S -.15(eg)-3.991 G 1.491(ular e).15 F 1.491 (xpression, so you can select multiple CWEs, e.g., `)-.15 F<60adad7265> -.74 E(ge)-.15 E 3.992(x")-.15 G(CWE-120|CWE-126"')-3.992 E 3.992('. If) -.74 F(you)3.992 E .024(select multiple CWEs with `)108 379.2 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 391.2 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 408 R -.15(ve)-.25 G 2.999(do).15 G 2.999 (naU)-2.999 G(nix-lik)-2.999 E 2.999(es)-.1 G(ys-)-2.999 E .894 (tem using the `)108 420 R<60adad7265>-.74 E(ge)-.15 E(x')-.15 E 3.394 ('a)-.74 G .894(ka `)-3.394 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 .893(gular e)-.15 F .893(xpression format.)-.15 F -.15(Fo)5.893 G 3.393(re).15 G(xample,) -3.543 E -.74(``)108 432 S<8d61>.74 E .955 (w\214nder -e $\(cat \214le1\)')-.15 F 3.455('w)-.74 G .956 (ould report only hits that matched the pattern in `)-3.555 F(`\214le1') -.74 E 3.456('. If)-.74 F .956(\214le1 contained)3.456 F -.74(``)108 444 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.581(Al)108 460.8 S .081 (ist of all CWE security elements \(the signatures/patterns that \215a) -2.581 F .08(w\214nder looks for\) can be found by using)-.15 F .448 (the `)108 472.8 R(`\255\255listrules')-.74 E 2.948('o)-.74 G 2.948 (ption. Each)-2.948 F .449(line lists the signature tok)2.949 F .449 (en \(typically a function name\) that may lead to a)-.1 F .917 (hit, the def)108 484.8 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.916 G 3.416(rm).15 G(ost)-3.416 E .727 (purposes this is also enough if you w)108 496.8 R .727 (ant to see what CWE security elements map to which CWEs, or the)-.1 F (re)108 508.8 Q -.15(ve)-.25 G 3.506(rse. F).15 F 1.006(or e)-.15 F 1.006(xample, to see the most of the signatures \(function names\) that\ map to CWE-327, without)-.15 F .164(seeing the def)108 520.8 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 532.8 S 3.088(uc)1.1 G .588(an also see the tok) -3.088 F .588(ens without a CWE mapping this w)-.1 F .588 (ay by running `)-.1 F(`\215a)-.74 E .587 (w\214nder -D --listrules | grep)-.15 F .676(-v CWE-')108 544.8 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 .091 (from CWE security elements to CWE identi\214ers.)108 556.8 R .09 (It does not include the re\214nements that \215a)5.091 F .09 (w\214nder applies)-.15 F(\(e.g., by e)108 568.8 Q (xamining function parameters\).)-.15 E 1.135(If you w)108 585.6 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 597.6 Q 1.179 (w\214nder source code \(included in the distrib)-.15 F 1.179 (ution\) is the best place for that information.)-.2 F 1.178 (This detailed)6.178 F 1.459 (information is primarily of interest to those fe)108 609.6 R 3.959(wp) -.25 G 1.459(eople who are trying to re\214ne the CWE mappings of)-3.959 F<8d61>108 621.6 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 .991(ments to the respecti)108 633.6 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 .992(ataset de\214nes most) -3.492 F .359(rules, with reference to a function that may mak)108 645.6 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 .358(an search the dataset for func-)-2.859 F .043 (tion names to see what CWE it generates by def)108 657.6 R .044 (ault; if \214rst parameter is not `)-.1 F(`normal')-.74 E 2.544('t)-.74 G .044(hen that is the name)-2.544 F .64 (of a re\214ning Python method that may select dif)108 669.6 R .64 (ferent CWEs \(depending on additional information\).)-.25 F(Con-)5.64 E -.15(ve)108 681.6 S(rsely).15 E 3.191(,y)-.65 G .691 (ou can search for `)-3.191 F(`CWE-number')-.74 E 3.191('a)-.74 G .692 (nd \214nd what security elements \(signatures or patterns\) refer) -3.191 F .595(to that CWE identi\214er)108 693.6 R 5.595(.F)-.55 G .595 (or most people, this is much more than the)-5.745 F 3.095(yn)-.15 G .594(eed; most people just w)-3.095 F .594(ant to scan)-.1 F (their source code to quickly \214nd problems.)108 705.6 Q(Fla)72 768 Q 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E(11)201.225 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/F1 10.95/Times-Bold@0 SF (SECURITY)72 84 Q F0 .781 (The whole point of this tool is to help \214nd vulnerabilities so the) 108 96 R 3.282(yc)-.15 G .782(an be \214x)-3.282 F 3.282(ed. Ho)-.15 F (we)-.25 E -.15(ve)-.25 G 1.582 -.4(r, d).15 H -2.15 -.25(ev e).4 H .782 (lopers and).25 F(re)108 108 Q(vie)-.25 E .352(wers must kno)-.25 F 2.852(wh)-.25 G .852 -.25(ow t)-2.852 H 2.852(od).25 G -2.15 -.25(ev e) -2.852 H .352(lop secure softw).25 F .352 (are to use this tool, because otherwise,)-.1 F/F2 10/Times-Italic@0 SF 2.851(af)2.851 G .351(ool with a tool)-2.851 F(is still a fool)108 120 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 136.8 R .214 (ger softw)-.18 F .214(are de)-.1 F -.15(ve)-.25 G .214 (lopment process designed to eliminate or).15 F .228 (reduce the impact of vulnerabilities.)108 148.8 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 .227(lop secure softw).25 F(are,)-.1 E(and the)108 160.8 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 177.6 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.424(fu)-.25 G(sing)-4.424 E(human re)108 189.6 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 206.4 S 2.859(us)1.1 G .359 (hould al)-2.859 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 .344(\214ed by a de)108 218.4 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.845(tn)-.18 G(ecess-)-2.845 E .807(ily trust a de)108 230.4 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 .806(he \214les while you')-3.306 F(re)-.5 E .538 (analyzing them, the attack)108 242.4 R .538(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 .539(nt the e).15 F .539(xposure of a)-.15 F .078(securi\ ty problem \(or create the impression of a problem where there is none\ \).)108 254.4 R .077(If you')5.077 F .077(re w)-.5 F .077 (orried about mali-)-.1 F 1.017(cious programmers you should do this an) 108 266.4 R(yw)-.15 E(ay)-.1 E 3.517(,b)-.65 G 1.018 (ecause after analysis you')-3.517 F 1.018(ll need to v)-.1 F 1.018 (erify that the code)-.15 F -2.15 -.25(ev e)108 278.4 T .711 (ntually run is the code you analyzed.).25 F .711 (Also, do not use the \255\255allo)5.711 F .71 (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 290.4 Q .725 (Source code management systems \(lik)108 307.2 R 3.225(eG)-.1 G .725 (itHub, SourceF)-3.225 F(or)-.15 E .725(ge, and Sa)-.18 F -.25(va)-.2 G .726(nnah\) de\214nitely f).25 F .726(all into this cate-)-.1 F .11 (gory; if you')108 319.2 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 331.2 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 348 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.608 (open other kinds of \214les, e)108 360 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.607 (This counters attack)6.607 F 1.607(ers who insert)-.1 F .363 (unusual \214le types into the source code.)108 372 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.863(tb)-.18 G(e) -2.863 E .48(modi\214ed by an attack)108 384 R .479 (er during the analysis, as recommended abo)-.1 F -.15(ve)-.15 G 5.479 (.T).15 G .479(his protection also doesn')-5.479 F 2.979(tw)-.18 G .479 (ork on)-3.079 F(Cygwin platforms, unfortunately)108 396 Q(.)-.65 E .788 (Cygwin systems \(Unix emulation on top of W)108 412.8 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 .789(w\214nder is used to)-.15 F 1.054(analyze programs that the analyst cannot trust.)108 424.8 R 1.053 (The problem is due to a design \215a)6.053 F 3.553(wi)-.15 G 3.553(nW) -3.553 G(indo)-3.953 E 1.053(ws \(that it)-.25 F .998 (inherits from MS-DOS\).)108 436.8 R .998(On W)5.998 F(indo)-.4 E .998 (ws and MS-DOS, certain \214lenames \(e.g., `)-.25 F(`com1')-.74 E .999 ('\) are automatically)-.74 F .686(treated by the operating system as t\ he names of peripherals, and this is true e)108 448.8 R -.15(ve)-.25 G 3.186(nw).15 G .685(hen a full pathname is)-3.186 F(gi)108 460.8 Q -.15 (ve)-.25 G 2.974(n. Y).15 F .474(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 .475(w\214nder deals with this by checking)-.15 F .867(what a \ \214lesystem object is, and then only opening directories and re)108 472.8 R .867(gular \214les \(and symlinks if enabled\).)-.15 F (Unfortunately)108 484.8 Q 2.519(,t)-.65 G .019(his doesn')-2.519 F 2.519(tw)-.18 G .019(ork on Cygwin; on at least some v)-2.619 F .02 (ersions of Cygwin on some v)-.15 F .02(ersions of W)-.15 F(in-)-.4 E (do)108 496.8 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.648(to delete or rename an)108 508.8 R 4.148<798c>-.15 G 1.649(lenames that are interpreted as de) -4.148 F 1.649(vice names before performing the analysis.)-.25 F 4.706 (These so-called `)108 520.8 R(`reserv)-.74 E 4.706(ed names')-.15 F 7.206('a)-.74 G 4.705(re CON, PRN, A)-7.206 F 4.705 (UX, CLOCK$, NUL, COM1-COM9, and)-.55 F 1.797 (LPT1-LPT9, optionally follo)108 532.8 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.298(yc)-.15 G(ase)-4.298 E(\(W)108 544.8 Q(indo)-.4 E (ws is case-insensiti)-.25 E -.15(ve)-.25 G(\).).15 E(Do)108 561.6 Q F2 (not)2.809 E F0 .308(load or dif)2.809 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.918 (and the pickle module is not intended to be secure ag)108 573.6 R 1.919 (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 585.6 R .218(xt this restric-)-.15 F (tion is not a problem.)108 597.6 Q F1 -.11(BU)72 626.4 S(GS).11 E F0 (Fla)108 638.4 Q .398(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 650.4 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 .054 (rate, and is the underlying cause of most of the b)108 662.4 R .055 (ugs listed here.)-.2 F .055(On the positi)5.055 F .355 -.15(ve s)-.25 H .055(ide, \215a).15 F .055(w\214nder doesn')-.15 F 2.555(tg)-.18 G(et) -2.555 E .17(confused by man)108 674.4 R 2.67(yc)-.15 G .169 (omplicated preprocessor sequences that other tools sometimes chok)-2.67 F 2.669(eo)-.1 G .169(n; \215a)-2.669 F .169(w\214nder can)-.15 F (often handle code that cannot link, and sometimes cannot e)108 686.4 Q -.15(ve)-.25 G 2.5(nc).15 G(ompile or b)-2.5 E(uild.)-.2 E(Fla)108 703.2 Q .86(w\214nder is currently limited to C/C++.)-.15 F .861 (In addition, when analyzing C++ it focuses primarily on the C)5.86 F .49(subset of C++.)108 715.2 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 .275(is a char array)108 727.2 R 5.275 (.T)-.65 G .275(hat is because \215a)-5.275 F .275(w\214nder doesn')-.15 F 2.776(th)-.18 G -2.25 -.2(av e)-2.776 H .276 (type information, and ">>" is safe with man)2.976 F 2.776(yo)-.15 G (ther)-2.776 E(Fla)72 768 Q 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E (12)201.225 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 .448 (types; reporting on all ">>" w)108 84 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.947(sd)-.55 G .447 (esigned so that adding)-2.947 F (support for other languages should be easy where its te)108 96 Q (xt-based approach can usefully apply)-.15 E(.)-.65 E(Fla)108 112.8 Q .812(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 .186 (de\214ned as `)108 124.8 R(`hits')-.74 E 2.686('i)-.74 G 2.686(ni) -2.686 G .186(ts database, and will often trigger on de\214nitions \(as\ well as uses\) of functions with the)-2.686 F .997(same name.)108 136.8 R .997(This is typically not a problem for C code.)5.997 F .998 (In C code, a function with the same name as a)5.998 F .496 (common library routine name often indicates that the de)108 148.8 R -.15(ve)-.25 G .495(loper is simply re).15 F .495 (writing a common library rou-)-.25 F .071(tine with the same interf)108 160.8 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.858(ad)108 172.8 S(if)-2.858 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 184.8 Q .406(written routines will be vulnerable to the same ki\ nds of misuse, and thus, reusing these rules is a reason-)-.25 F .187 (able approach.)108 196.8 R(Ho)5.187 E(we)-.25 E -.15(ve)-.25 G .987 -.4 (r, t).15 H .186 (his can be a much more serious problem in C++ code which hea).4 F .186 (vily uses classes)-.2 F 1.354 (and namespaces, since the same method name may ha)108 208.8 R 1.655 -.15(ve m)-.2 H(an).15 E 3.855(yd)-.15 G(if)-3.855 E 1.355 (ferent meanings.)-.25 F 1.355(The \255\255f)6.355 F(alsepositi)-.1 E -.15(ve)-.25 G 1.189(option can help some)108 220.8 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 232.8 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 249.6 R 2.383(in particular)108 261.6 R 4.883 (,i)-.4 G 4.883(fas)-4.883 G 2.382(tring is opened and then closed mult\ iple times using an #ifdef .. #else construct,)-4.883 F<8d61>108 273.6 Q .072(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 285.6 Q(write those lines.)-.25 E (Thankfully)5 E 2.5(,t)-.65 G(hese are quite rare.)-2.5 E(Fla)108 302.4 Q 2.657(w\214nder reports vulnerabilities re)-.15 F -.05(ga)-.15 G 2.656 (rdless of the parameters of "#if" or "#ifdef".).05 F 5.156(Ac)7.656 G 2.656(onstruct "#if)-5.156 F -1.35(VA)108 314.4 S .721 (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.222(,")-.65 G .722(#ifdef V)-3.222 F(ALUE")-1.35 E .606(will ha)108 326.4 R .906 -.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 .541 (means that \215a)108 338.4 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 .542 (ug, this is)-.2 F(intended beha)108 350.4 Q(vior)-.2 E(.)-.55 E(Fla)108 367.2 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 .841(change this particular situation, b) 108 379.2 R .841 (ut directly using "#if 0" to comment-out code \(other than during deb) -.2 F(ug-)-.2 E .965(ging\) is itself that the remo)108 391.2 R -.25(va) -.15 G 3.465(li).25 G 3.465(sv)-3.465 G .964(ery temporary \(in which c\ ase we should report it\) or an indicator of a)-3.615 F 1.278 (problem with poor code practices.)108 403.2 R 1.278(If you w)6.278 F 1.279(ant to permanently get rid of code, then delete it instead of)-.1 F .683(using "#if 0", since you can al)108 415.2 R -.1(wa)-.1 G .683 (ys see what it w).1 F .683(as using your v)-.1 F .682 (ersion control softw)-.15 F 3.182(are. If)-.1 F .682(you don')3.182 F 3.182(tu)-.18 G(se)-3.182 E -.15(ve)108 427.2 S(rsion control softw).15 E(are, then that')-.1 E 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 444 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 456 Q .978(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 .977(This means it)5.977 F 1.266 (will get confused by patterns lik)108 468 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.767(ts)-.18 G 1.267(eem to be a) -3.767 F(problem; gette)108 480 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 496.8 R 2.2(xt matching; some complicated)-.15 F -.15(ex) 108 508.8 S(pressions can cause it to trigger or not trigger une).15 E (xpectedly)-.15 E(.)-.65 E(Fla)108 525.6 Q .221 (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.722 (ei)-.1 G .222(t\) is not)-2.722 F 2.573(ag)108 537.6 S .072 (ood tool for \214nding intentionally malicious code \(e.g., T)-2.573 F .072(rojan horses\); malicious programmers can easily)-.35 F (insert code that w)108 549.6 Q (ould not be detected by this kind of tool.)-.1 E(Fla)108 566.4 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 .674(to be less ef)108 578.4 R(fecti) -.25 E .974 -.15(ve a)-.25 H .674(nalyzing programs that aren').15 F 3.174(ta)-.18 G .673(pplication-layer code \(e.g., k)-3.174 F .673 (ernel code or self-hosting)-.1 F 2.867(code\). The)108 590.4 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 602.4 Q (ferent from normal.)-.25 E(Fla)108 619.2 Q(w\214nder')-.15 E 3.071(sd) -.55 G(ef)-3.071 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 631.2 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 \214lenames including colon \(:\) are lik)108 643.2 R .708(ely to be misunderstood.)-.1 F .708(This is)5.708 F .175 (especially important if \215a)108 655.2 R(w\214nder')-.15 E 2.675(so) -.55 G .176(utput is being used by other tools, such as \214lters or te) -2.675 F .176(xt editors.)-.15 F .176(If you)5.176 F .449 (are using \215a)108 667.2 R(w\214nder')-.15 E 2.949(so)-.55 G .449(utp\ ut in other tools, consider using its CSV format instead \(which can ha\ ndle this\).)-2.949 F 1.013(If you')108 679.2 R 1.013(re looking at ne) -.5 F 3.513(wc)-.25 G 1.013(ode, e)-3.513 F 1.014 (xamine the \214les for such characters.)-.15 F(It')6.014 E 3.514(si) -.55 G 1.014(ncredibly unwise to ha)-3.514 F 1.314 -.15(ve s)-.2 H(uch) .15 E .842(\214lenames an)108 691.2 R(yw)-.15 E .842(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 .857 (internal data delimeters.)108 703.2 R .857(The colon is often used as \ special characters in \214lesystems: MacOS uses it as a)5.857 F 1.135 (directory separator)108 715.2 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 .541 (uses it to identify special de)108 727.2 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 .542(latforms use the colon to identify)-3.041 F(Fla)72 768 Q 165.545 (w\214nder 4)-.15 F(Apr 2018)2.5 E(13)201.225 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 2.927(URIs/URLs. Filenames)108 84 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 96 Q .3 -.15(ve p)-.2 H(roblems with them.).15 E(Fla)108 112.8 Q(w\214nder is not internation\ alized, so it currently does not support localization.)-.15 E .132 (In general, \215a)108 129.6 R .133(w\214nder attempts to err on the si\ de of caution; it tends to report hits, so that the)-.15 F 2.633(yc)-.15 G .133(an be e)-2.633 F(xam-)-.15 E .398(ined further)108 141.6 R 2.898 (,i)-.4 G .398(nstead of silently ignoring them.)-2.898 F .397 (Thus, \215a)5.397 F .397(w\214nder prefers to ha)-.15 F .697 -.15(ve f) -.2 H .397(alse positi).05 F -.15(ve)-.25 G 2.897(s\().15 G .397 (reports that)-2.897 F .317(turn out to not be problems\) rather than f) 108 153.6 R .318(alse ne)-.1 F -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G 2.818(s\().15 G -.1(fa)-2.818 G .318 (ilures to report security vulnerabilities\).).1 F .318(But this)5.318 F (is a generality; \215a)108 165.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 .062 (Security vulnerabilities might not be identi\214ed as such by \215a)108 182.4 R(w\214nder)-.15 E 2.561(,a)-.4 G .061(nd con)-2.561 F -.15(ve)-.4 G(rsely).15 E 2.561(,s)-.65 G .061(ome hits aren')-2.561 F 2.561(tr)-.18 G(eally)-2.561 E 1.506(security vulnerabilities.)108 194.4 R 1.506(This\ is true for all static security scanners, and is especially true for t\ ools lik)6.506 F(e)-.1 E<8d61>108 206.4 Q .044 (w\214nder that use a simple le)-.15 F .043(xical analysis and pattern \ analysis to identify potential vulnerabilities.)-.15 F .043(Still, it) 5.043 F 1.111(can serv)108 218.4 R 3.611(ea)-.15 G 3.611(sau)-3.611 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.112(nd that') -3.611 F 3.612(st)-.55 G(he)-3.612 E(point of this simple tool.)108 230.4 Q/F1 10.95/Times-Bold@0 SF(SEE ALSO)72 259.2 Q F0 1.345 (See the \215a)108 271.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.174 E 3.844(eP)-.37 G -1.7 -.45(ro g)-3.844 H -.15(ra).45 G(m-).15 E(ming HO) 108 283.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 312 S(THOR).548 E F0(Da)108 324 Q (vid A. Wheeler \(dwheeler@dwheeler)-.2 E(.com\).)-.55 E(Fla)72 768 Q 165.545(w\214nder 4)-.15 F(Apr 2018)2.5 E(14)201.225 E 0 Cg EP %%Trailer end %%EOF flawfinder-2.0.10/flawfinder.spec0000644400514740010010000000234113470413173017566 0ustar dwheelerDomain UsersName: flawfinder Summary: Examines C/C++ source code for security flaws Version: 2.0.10 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.10/flawfinder.yapf0000755400514740010010000000000013137444615017571 0ustar dwheelerDomain Usersflawfinder-2.0.10/flawtest.c0000644400514740010010000000135613406345645016602 0ustar dwheelerDomain Users /* Test flawfinder. This program won't compile or run; that's not necessary for this to be a useful test. */ main() { 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 much better: */ MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0])); } flawfinder-2.0.10/INSTALL.md0000644400514740010010000001146213421443646016231 0ustar dwheelerDomain Users# 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.10/junk.c0000644400514740010010000000023113406345645015707 0ustar dwheelerDomain Users #include main() { char abuf[1000]; FILE *FR = stdin; fscanf(FR, "%2000s", abuf); printf("Result = %s\n", abuf); strcpy(new,old); } flawfinder-2.0.10/makefile0000644400514740010010000002162513470413150016272 0ustar dwheelerDomain Users# Flawfinder. # Released under the General Public License (GPL) version 2 or later. # (C) 2001-2017 David A. Wheeler. # See "release_process.md" for release process, including # how to change version numbers. NAME=flawfinder VERSION=2.0.10 RPM_VERSION=1 VERSIONEDNAME=$(NAME)-$(VERSION) ARCH=noarch SAMPLE_DIR=/usr/src/linux-2.2.16 PYTHON=python PYTHON2=python2 PYTHON3=python3 # 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= 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 $(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 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 -p [a-zA-Z]* ,tempdir rm -f ,tempdir/*.tar.gz rm -f ,tempdir/*.rpm # We don't need both "flawfinder" and "flawfinder.py": rm -f ,tempdir/flawfinder.py 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) chown --reference=. 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 $(SAMPLE_DIR)/*/*.[ch] > /dev/null echo "Lines examined:" wc -l $(SAMPLE_DIR)/*/*.[ch] | tail -2 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: setup.py @echo 'test_007 (setup.py sane)' @test "`$(PYTHON) setup.py --name`" = 'flawfinder' @test "`$(PYTHON) setup.py --license`" = 'GPL-2.0+' @test "`$(PYTHON) setup.py --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 # 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 @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 profile: /usr/lib/python1.5/profile.py ./flawfinder > 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 \ test.c test2.c test-results.txt 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 | 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.10/MANIFEST.in0000644400514740010010000000036713406345645016344 0ustar dwheelerDomain Usersinclude 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.10/no-ending-newline.c0000644400514740010010000000067013406345645020264 0ustar dwheelerDomain Users// 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.10/pylintrc0000644400514740010010000003623513406345645016400 0ustar dwheelerDomain Users[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.10/README.md0000644400514740010010000000572213421441610016047 0ustar dwheelerDomain Users# 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. # 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. # 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.10/release_process.md0000644400514740010010000000311613421455614020274 0ustar dwheelerDomain Users# 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 flawfinder.spec setup.py index.html # in dwheeler.com/flawfinder Then run: ~~~~ make test && make test-is-correct # update version number in tests ~~~~ ## Test it ~~~~ make check # Run tests in Python 2 and 3 ~~~~ ## 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.10/setup.cfg0000644400514740010010000000032113406345645016415 0ustar dwheelerDomain Users[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.10/setup.py0000644400514740010010000000400013470413206016272 0ustar dwheelerDomain Users#!/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.10", # 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', scripts = [ 'flawfinder' ], data_files = [ ('share/man/man1', [ 'flawfinder.1.gz' ]) ], py_modules = [ ], ) flawfinder-2.0.10/sloctest.c0000644400514740010010000000016513406345645016606 0ustar dwheelerDomain Users/* This is a test. Should produce 6 SLOC. */ #include #define HI 10 main() { a = 1; /* hi */ "hi" } flawfinder-2.0.10/test-diff-005.patch0000644400514740010010000000040113406345645020003 0ustar dwheelerDomain Users--- 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.10/test-junk-006.txt0000755400514740010010000001663013504006052017562 0ustar dwheelerDomain Userstest.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:95: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:101: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.10/test-junk-008.txt0000644400514740010010000001663013504006056017565 0ustar dwheelerDomain Userstest.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:95: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:101: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.10/test-patched.c0000644400514740010010000000654213406345645017340 0ustar dwheelerDomain Users/* 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.10/test-preproc.c0000755400514740010010000013070613155107402017371 0ustar dwheelerDomain Users# 1 "test.c" # 1 "" # 1 "" # 1 "test.c" # 1 "/usr/include/stdio.h" 1 3 4 # 29 "/usr/include/stdio.h" 3 4 # 1 "/usr/include/_ansi.h" 1 3 4 # 15 "/usr/include/_ansi.h" 3 4 # 1 "/usr/include/newlib.h" 1 3 4 # 14 "/usr/include/newlib.h" 3 4 # 1 "/usr/include/_newlib_version.h" 1 3 4 # 15 "/usr/include/newlib.h" 2 3 4 # 16 "/usr/include/_ansi.h" 2 3 4 # 1 "/usr/include/sys/config.h" 1 3 4 # 1 "/usr/include/machine/ieeefp.h" 1 3 4 # 5 "/usr/include/sys/config.h" 2 3 4 # 1 "/usr/include/sys/features.h" 1 3 4 # 6 "/usr/include/sys/config.h" 2 3 4 # 233 "/usr/include/sys/config.h" 3 4 # 1 "/usr/include/cygwin/config.h" 1 3 4 # 234 "/usr/include/sys/config.h" 2 3 4 # 17 "/usr/include/_ansi.h" 2 3 4 # 30 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/include/sys/cdefs.h" 1 3 4 # 43 "/usr/include/sys/cdefs.h" 3 4 # 1 "/usr/include/machine/_default_types.h" 1 3 4 # 41 "/usr/include/machine/_default_types.h" 3 4 # 41 "/usr/include/machine/_default_types.h" 3 4 typedef signed char __int8_t; typedef unsigned char __uint8_t; # 55 "/usr/include/machine/_default_types.h" 3 4 typedef short int __int16_t; typedef short unsigned int __uint16_t; # 77 "/usr/include/machine/_default_types.h" 3 4 typedef int __int32_t; typedef unsigned int __uint32_t; # 103 "/usr/include/machine/_default_types.h" 3 4 typedef long int __int64_t; typedef long unsigned int __uint64_t; # 134 "/usr/include/machine/_default_types.h" 3 4 typedef signed char __int_least8_t; typedef unsigned char __uint_least8_t; # 160 "/usr/include/machine/_default_types.h" 3 4 typedef short int __int_least16_t; typedef short unsigned int __uint_least16_t; # 182 "/usr/include/machine/_default_types.h" 3 4 typedef int __int_least32_t; typedef unsigned int __uint_least32_t; # 200 "/usr/include/machine/_default_types.h" 3 4 typedef long int __int_least64_t; typedef long unsigned int __uint_least64_t; # 214 "/usr/include/machine/_default_types.h" 3 4 typedef long int __intmax_t; typedef long unsigned int __uintmax_t; typedef long int __intptr_t; typedef long unsigned int __uintptr_t; # 44 "/usr/include/sys/cdefs.h" 2 3 4 # 1 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 1 3 4 # 216 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 3 4 typedef long unsigned int size_t; # 46 "/usr/include/sys/cdefs.h" 2 3 4 # 36 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 1 3 4 # 149 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 3 4 typedef long int ptrdiff_t; # 328 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 3 4 typedef short unsigned int wchar_t; # 426 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 3 4 typedef struct { long long __max_align_ll __attribute__((__aligned__(__alignof__(long long)))); long double __max_align_ld __attribute__((__aligned__(__alignof__(long double)))); } max_align_t; # 37 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stdarg.h" 1 3 4 # 40 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stdarg.h" 3 4 typedef __builtin_va_list __gnuc_va_list; # 41 "/usr/include/stdio.h" 2 3 4 typedef __gnuc_va_list va_list; # 60 "/usr/include/stdio.h" 3 4 # 1 "/usr/include/sys/reent.h" 1 3 4 # 13 "/usr/include/sys/reent.h" 3 4 # 1 "/usr/include/_ansi.h" 1 3 4 # 14 "/usr/include/sys/reent.h" 2 3 4 # 1 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 1 3 4 # 15 "/usr/include/sys/reent.h" 2 3 4 # 1 "/usr/include/sys/_types.h" 1 3 4 # 24 "/usr/include/sys/_types.h" 3 4 # 1 "/usr/include/machine/_types.h" 1 3 4 # 17 "/usr/include/machine/_types.h" 3 4 typedef __int64_t __blkcnt_t; typedef __int32_t __blksize_t; typedef __uint32_t __dev_t; typedef unsigned long __fsblkcnt_t; typedef unsigned long __fsfilcnt_t; typedef __uint32_t __uid_t; typedef __uint32_t __gid_t; typedef __uint64_t __ino_t; typedef long long __key_t; typedef __uint16_t __sa_family_t; typedef int __socklen_t; # 25 "/usr/include/sys/_types.h" 2 3 4 # 1 "/usr/include/sys/lock.h" 1 3 4 # 12 "/usr/include/sys/lock.h" 3 4 typedef void *_LOCK_T; # 42 "/usr/include/sys/lock.h" 3 4 void __cygwin_lock_init(_LOCK_T *); void __cygwin_lock_init_recursive(_LOCK_T *); void __cygwin_lock_fini(_LOCK_T *); void __cygwin_lock_lock(_LOCK_T *); int __cygwin_lock_trylock(_LOCK_T *); void __cygwin_lock_unlock(_LOCK_T *); # 26 "/usr/include/sys/_types.h" 2 3 4 # 44 "/usr/include/sys/_types.h" 3 4 typedef long _off_t; typedef int __pid_t; # 65 "/usr/include/sys/_types.h" 3 4 typedef __uint32_t __id_t; # 88 "/usr/include/sys/_types.h" 3 4 typedef __uint32_t __mode_t; __extension__ typedef long long _off64_t; typedef _off_t __off_t; typedef _off64_t __loff_t; # 114 "/usr/include/sys/_types.h" 3 4 typedef long _fpos_t; typedef _off64_t _fpos64_t; # 129 "/usr/include/sys/_types.h" 3 4 typedef long unsigned int __size_t; # 145 "/usr/include/sys/_types.h" 3 4 typedef long signed int _ssize_t; # 156 "/usr/include/sys/_types.h" 3 4 typedef _ssize_t __ssize_t; # 1 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 1 3 4 # 357 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 3 4 typedef unsigned int wint_t; # 160 "/usr/include/sys/_types.h" 2 3 4 typedef struct { int __count; union { wint_t __wch; unsigned char __wchb[4]; } __value; } _mbstate_t; typedef _LOCK_T _flock_t; typedef void *_iconv_t; typedef unsigned long __clock_t; typedef long __time_t; typedef unsigned long __clockid_t; typedef unsigned long __timer_t; # 203 "/usr/include/sys/_types.h" 3 4 typedef unsigned short __nlink_t; typedef long __suseconds_t; typedef unsigned long __useconds_t; typedef __builtin_va_list __va_list; # 16 "/usr/include/sys/reent.h" 2 3 4 # 25 "/usr/include/sys/reent.h" 3 4 typedef unsigned int __ULong; # 38 "/usr/include/sys/reent.h" 3 4 struct _reent; struct __locale_t; struct _Bigint { struct _Bigint *_next; int _k, _maxwds, _sign, _wds; __ULong _x[1]; }; struct __tm { int __tm_sec; int __tm_min; int __tm_hour; int __tm_mday; int __tm_mon; int __tm_year; int __tm_wday; int __tm_yday; int __tm_isdst; }; struct _on_exit_args { void * _fnargs[32]; void * _dso_handle[32]; __ULong _fntypes; __ULong _is_cxa; }; # 93 "/usr/include/sys/reent.h" 3 4 struct _atexit { struct _atexit *_next; int _ind; void (*_fns[32])(void); struct _on_exit_args _on_exit_args; }; # 117 "/usr/include/sys/reent.h" 3 4 struct __sbuf { unsigned char *_base; int _size; }; # 181 "/usr/include/sys/reent.h" 3 4 struct __sFILE { unsigned char *_p; int _r; int _w; short _flags; short _file; struct __sbuf _bf; int _lbfsize; void * _cookie; _ssize_t (__attribute__((__cdecl__)) * _read) (struct _reent *, void *, char *, size_t) ; _ssize_t (__attribute__((__cdecl__)) * _write) (struct _reent *, void *, const char *, size_t) ; _fpos_t (__attribute__((__cdecl__)) * _seek) (struct _reent *, void *, _fpos_t, int); int (__attribute__((__cdecl__)) * _close) (struct _reent *, void *); struct __sbuf _ub; unsigned char *_up; int _ur; unsigned char _ubuf[3]; unsigned char _nbuf[1]; struct __sbuf _lb; int _blksize; _off_t _offset; struct _reent *_data; _flock_t _lock; _mbstate_t _mbstate; int _flags2; }; # 239 "/usr/include/sys/reent.h" 3 4 struct __sFILE64 { unsigned char *_p; int _r; int _w; short _flags; short _file; struct __sbuf _bf; int _lbfsize; struct _reent *_data; void * _cookie; _ssize_t (__attribute__((__cdecl__)) * _read) (struct _reent *, void *, char *, size_t) ; _ssize_t (__attribute__((__cdecl__)) * _write) (struct _reent *, void *, const char *, size_t) ; _fpos_t (__attribute__((__cdecl__)) * _seek) (struct _reent *, void *, _fpos_t, int); int (__attribute__((__cdecl__)) * _close) (struct _reent *, void *); struct __sbuf _ub; unsigned char *_up; int _ur; unsigned char _ubuf[3]; unsigned char _nbuf[1]; struct __sbuf _lb; int _blksize; int _flags2; _off64_t _offset; _fpos64_t (__attribute__((__cdecl__)) * _seek64) (struct _reent *, void *, _fpos64_t, int); _flock_t _lock; _mbstate_t _mbstate; }; typedef struct __sFILE64 __FILE; struct _glue { struct _glue *_next; int _niobs; __FILE *_iobs; }; # 319 "/usr/include/sys/reent.h" 3 4 struct _rand48 { unsigned short _seed[3]; unsigned short _mult[3]; unsigned short _add; }; # 569 "/usr/include/sys/reent.h" 3 4 struct _reent { int _errno; __FILE *_stdin, *_stdout, *_stderr; int _inc; char _emergency[25]; int _unspecified_locale_info; struct __locale_t *_locale; int __sdidinit; void (__attribute__((__cdecl__)) * __cleanup) (struct _reent *); struct _Bigint *_result; int _result_k; struct _Bigint *_p5s; struct _Bigint **_freelist; int _cvtlen; char *_cvtbuf; union { struct { unsigned int _unused_rand; char * _strtok_last; char _asctime_buf[26]; struct __tm _localtime_buf; int _gamma_signgam; __extension__ unsigned long long _rand_next; struct _rand48 _r48; _mbstate_t _mblen_state; _mbstate_t _mbtowc_state; _mbstate_t _wctomb_state; char _l64a_buf[8]; char _signal_buf[24]; int _getdate_err; _mbstate_t _mbrlen_state; _mbstate_t _mbrtowc_state; _mbstate_t _mbsrtowcs_state; _mbstate_t _wcrtomb_state; _mbstate_t _wcsrtombs_state; int _h_errno; } _reent; struct { unsigned char * _nextf[30]; unsigned int _nmalloc[30]; } _unused; } _new; struct _atexit *_atexit; struct _atexit _atexit0; void (**(_sig_func))(int); struct _glue __sglue; __FILE __sf[3]; }; # 775 "/usr/include/sys/reent.h" 3 4 extern struct _reent *_impure_ptr ; extern struct _reent *const _global_impure_ptr ; void _reclaim_reent (struct _reent *); struct _reent * __attribute__((__cdecl__)) __getreent (void); # 61 "/usr/include/stdio.h" 2 3 4 # 1 "/usr/include/sys/types.h" 1 3 4 # 28 "/usr/include/sys/types.h" 3 4 typedef __uint8_t u_int8_t; typedef __uint16_t u_int16_t; typedef __uint32_t u_int32_t; typedef __uint64_t u_int64_t; typedef int register_t; # 62 "/usr/include/sys/types.h" 3 4 # 1 "/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/stddef.h" 1 3 4 # 63 "/usr/include/sys/types.h" 2 3 4 # 1 "/usr/include/sys/_stdint.h" 1 3 4 # 20 "/usr/include/sys/_stdint.h" 3 4 typedef __int8_t int8_t ; typedef __uint8_t uint8_t ; typedef __int16_t int16_t ; typedef __uint16_t uint16_t ; typedef __int32_t int32_t ; typedef __uint32_t uint32_t ; typedef __int64_t int64_t ; typedef __uint64_t uint64_t ; typedef __intmax_t intmax_t; typedef __uintmax_t uintmax_t; typedef __intptr_t intptr_t; typedef __uintptr_t uintptr_t; # 65 "/usr/include/sys/types.h" 2 3 4 # 1 "/usr/include/machine/endian.h" 1 3 4 # 1 "/usr/include/machine/_endian.h" 1 3 4 # 14 "/usr/include/machine/_endian.h" 3 4 # 1 "/usr/include/bits/endian.h" 1 3 4 # 15 "/usr/include/machine/_endian.h" 2 3 4 # 23 "/usr/include/machine/_endian.h" 3 4 static __inline__ __uint32_t __ntohl(__uint32_t); static __inline__ __uint16_t __ntohs(__uint16_t); static __inline__ __uint32_t __ntohl(__uint32_t _x) { __asm__("bswap %0" : "=r" (_x) : "0" (_x)); return _x; } static __inline__ __uint16_t __ntohs(__uint16_t _x) { __asm__("xchgb %b0,%h0" : "=Q" (_x) : "0" (_x)); return _x; } # 7 "/usr/include/machine/endian.h" 2 3 4 # 68 "/usr/include/sys/types.h" 2 3 4 # 1 "/usr/include/sys/select.h" 1 3 4 # 25 "/usr/include/sys/select.h" 3 4 # 1 "/usr/include/sys/_sigset.h" 1 3 4 # 41 "/usr/include/sys/_sigset.h" 3 4 typedef unsigned long __sigset_t; # 26 "/usr/include/sys/select.h" 2 3 4 # 1 "/usr/include/sys/_timeval.h" 1 3 4 # 35 "/usr/include/sys/_timeval.h" 3 4 typedef __suseconds_t suseconds_t; typedef long time_t; # 52 "/usr/include/sys/_timeval.h" 3 4 struct timeval { time_t tv_sec; suseconds_t tv_usec; }; # 27 "/usr/include/sys/select.h" 2 3 4 # 1 "/usr/include/sys/timespec.h" 1 3 4 # 38 "/usr/include/sys/timespec.h" 3 4 # 1 "/usr/include/sys/_timespec.h" 1 3 4 # 45 "/usr/include/sys/_timespec.h" 3 4 struct timespec { time_t tv_sec; long tv_nsec; }; # 39 "/usr/include/sys/timespec.h" 2 3 4 # 58 "/usr/include/sys/timespec.h" 3 4 struct itimerspec { struct timespec it_interval; struct timespec it_value; }; # 28 "/usr/include/sys/select.h" 2 3 4 typedef __sigset_t sigset_t; # 45 "/usr/include/sys/select.h" 3 4 typedef unsigned long fd_mask; typedef struct _types_fd_set { fd_mask fds_bits[(((64)+(((sizeof (fd_mask) * 8))-1))/((sizeof (fd_mask) * 8)))]; } _types_fd_set; # 71 "/usr/include/sys/select.h" 3 4 int select (int __n, _types_fd_set *__readfds, _types_fd_set *__writefds, _types_fd_set *__exceptfds, struct timeval *__timeout) ; int pselect (int __n, _types_fd_set *__readfds, _types_fd_set *__writefds, _types_fd_set *__exceptfds, const struct timespec *__timeout, const sigset_t *__set) ; # 69 "/usr/include/sys/types.h" 2 3 4 typedef __uint32_t in_addr_t; typedef __uint16_t in_port_t; # 87 "/usr/include/sys/types.h" 3 4 typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; typedef __blkcnt_t blkcnt_t; typedef __blksize_t blksize_t; typedef unsigned long clock_t; # 135 "/usr/include/sys/types.h" 3 4 typedef long daddr_t; typedef char * caddr_t; typedef __fsblkcnt_t fsblkcnt_t; typedef __fsfilcnt_t fsfilcnt_t; typedef __id_t id_t; typedef __ino_t ino_t; # 173 "/usr/include/sys/types.h" 3 4 typedef __off_t off_t; typedef __dev_t dev_t; typedef __uid_t uid_t; typedef __gid_t gid_t; typedef __pid_t pid_t; typedef __key_t key_t; typedef _ssize_t ssize_t; typedef __mode_t mode_t; typedef __nlink_t nlink_t; typedef __clockid_t clockid_t; typedef __timer_t timer_t; typedef __useconds_t useconds_t; # 236 "/usr/include/sys/types.h" 3 4 typedef __int64_t sbintime_t; # 1 "/usr/include/sys/_pthreadtypes.h" 1 3 4 # 15 "/usr/include/sys/_pthreadtypes.h" 3 4 typedef struct __pthread_t {char __dummy;} *pthread_t; typedef struct __pthread_mutex_t {char __dummy;} *pthread_mutex_t; typedef struct __pthread_key_t {char __dummy;} *pthread_key_t; typedef struct __pthread_attr_t {char __dummy;} *pthread_attr_t; typedef struct __pthread_mutexattr_t {char __dummy;} *pthread_mutexattr_t; typedef struct __pthread_condattr_t {char __dummy;} *pthread_condattr_t; typedef struct __pthread_cond_t {char __dummy;} *pthread_cond_t; typedef struct __pthread_barrierattr_t {char __dummy;} *pthread_barrierattr_t; typedef struct __pthread_barrier_t {char __dummy;} *pthread_barrier_t; typedef struct { pthread_mutex_t mutex; int state; } pthread_once_t; typedef struct __pthread_spinlock_t {char __dummy;} *pthread_spinlock_t; typedef struct __pthread_rwlock_t {char __dummy;} *pthread_rwlock_t; typedef struct __pthread_rwlockattr_t {char __dummy;} *pthread_rwlockattr_t; # 240 "/usr/include/sys/types.h" 2 3 4 # 1 "/usr/include/machine/types.h" 1 3 4 # 19 "/usr/include/machine/types.h" 3 4 # 1 "/usr/include/endian.h" 1 3 4 # 38 "/usr/include/endian.h" 3 4 # 1 "/usr/include/bits/byteswap.h" 1 3 4 # 16 "/usr/include/bits/byteswap.h" 3 4 static __inline unsigned short __bswap_16 (unsigned short __x) { return (__x >> 8) | (__x << 8); } static __inline unsigned int __bswap_32 (unsigned int __x) { return (__bswap_16 (__x & 0xffff) << 16) | (__bswap_16 (__x >> 16)); } static __inline unsigned long long __bswap_64 (unsigned long long __x) { return (((unsigned long long) __bswap_32 (__x & 0xffffffffull)) << 32) | (__bswap_32 (__x >> 32)); } # 39 "/usr/include/endian.h" 2 3 4 # 20 "/usr/include/machine/types.h" 2 3 4 # 1 "/usr/include/bits/wordsize.h" 1 3 4 # 21 "/usr/include/machine/types.h" 2 3 4 typedef struct timespec timespec_t; typedef struct timespec timestruc_t; typedef __loff_t loff_t; # 46 "/usr/include/machine/types.h" 3 4 struct flock { short l_type; short l_whence; off_t l_start; off_t l_len; pid_t l_pid; }; typedef unsigned long vm_offset_t; typedef unsigned long vm_size_t; typedef void *vm_object_t; typedef char *addr_t; # 1 "/usr/include/sys/sysmacros.h" 1 3 4 # 12 "/usr/include/sys/sysmacros.h" 3 4 # 1 "/usr/include/sys/types.h" 1 3 4 # 13 "/usr/include/sys/sysmacros.h" 2 3 4 static __inline__ int gnu_dev_major(dev_t); static __inline__ int gnu_dev_minor(dev_t); static __inline__ dev_t gnu_dev_makedev(int, int); static __inline__ int gnu_dev_major(dev_t dev) { return (int)(((dev) >> 16) & 0xffff); } static __inline__ int gnu_dev_minor(dev_t dev) { return (int)((dev) & 0xffff); } static __inline__ dev_t gnu_dev_makedev(int maj, int min) { return (((maj) << 16) | ((min) & 0xffff)); } # 81 "/usr/include/machine/types.h" 2 3 4 # 241 "/usr/include/sys/types.h" 2 3 4 # 62 "/usr/include/stdio.h" 2 3 4 typedef __FILE FILE; typedef _fpos64_t fpos_t; # 1 "/usr/include/sys/stdio.h" 1 3 4 # 33 "/usr/include/sys/stdio.h" 3 4 ssize_t __attribute__((__cdecl__)) getline (char **, size_t *, FILE *); ssize_t __attribute__((__cdecl__)) getdelim (char **, size_t *, int, FILE *); # 80 "/usr/include/stdio.h" 2 3 4 # 181 "/usr/include/stdio.h" 3 4 char * __attribute__((__cdecl__)) ctermid (char *); FILE * __attribute__((__cdecl__)) tmpfile (void); char * __attribute__((__cdecl__)) tmpnam (char *); char * __attribute__((__cdecl__)) tempnam (const char *, const char *); int __attribute__((__cdecl__)) fclose (FILE *); int __attribute__((__cdecl__)) fflush (FILE *); FILE * __attribute__((__cdecl__)) freopen (const char *restrict, const char *restrict, FILE *restrict); void __attribute__((__cdecl__)) setbuf (FILE *restrict, char *restrict); int __attribute__((__cdecl__)) setvbuf (FILE *restrict, char *restrict, int, size_t); int __attribute__((__cdecl__)) fprintf (FILE *restrict, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; int __attribute__((__cdecl__)) fscanf (FILE *restrict, const char *restrict, ...) __attribute__ ((__format__ (__scanf__, 2, 3))) ; int __attribute__((__cdecl__)) printf (const char *restrict, ...) __attribute__ ((__format__ (__printf__, 1, 2))) ; int __attribute__((__cdecl__)) scanf (const char *restrict, ...) __attribute__ ((__format__ (__scanf__, 1, 2))) ; int __attribute__((__cdecl__)) sscanf (const char *restrict, const char *restrict, ...) __attribute__ ((__format__ (__scanf__, 2, 3))) ; int __attribute__((__cdecl__)) vfprintf (FILE *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) vprintf (const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 1, 0))) ; int __attribute__((__cdecl__)) vsprintf (char *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) fgetc (FILE *); char * __attribute__((__cdecl__)) fgets (char *restrict, int, FILE *restrict); int __attribute__((__cdecl__)) fputc (int, FILE *); int __attribute__((__cdecl__)) fputs (const char *restrict, FILE *restrict); int __attribute__((__cdecl__)) getc (FILE *); int __attribute__((__cdecl__)) getchar (void); char * __attribute__((__cdecl__)) gets (char *); int __attribute__((__cdecl__)) putc (int, FILE *); int __attribute__((__cdecl__)) putchar (int); int __attribute__((__cdecl__)) puts (const char *); int __attribute__((__cdecl__)) ungetc (int, FILE *); size_t __attribute__((__cdecl__)) fread (void * restrict, size_t _size, size_t _n, FILE *restrict); size_t __attribute__((__cdecl__)) fwrite (const void * restrict , size_t _size, size_t _n, FILE *); int __attribute__((__cdecl__)) fgetpos (FILE *restrict, fpos_t *restrict); int __attribute__((__cdecl__)) fseek (FILE *, long, int); int __attribute__((__cdecl__)) fsetpos (FILE *, const fpos_t *); long __attribute__((__cdecl__)) ftell ( FILE *); void __attribute__((__cdecl__)) rewind (FILE *); void __attribute__((__cdecl__)) clearerr (FILE *); int __attribute__((__cdecl__)) feof (FILE *); int __attribute__((__cdecl__)) ferror (FILE *); void __attribute__((__cdecl__)) perror (const char *); FILE * __attribute__((__cdecl__)) fopen (const char *restrict _name, const char *restrict _type); int __attribute__((__cdecl__)) sprintf (char *restrict, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; int __attribute__((__cdecl__)) remove (const char *); int __attribute__((__cdecl__)) rename (const char *, const char *); # 257 "/usr/include/stdio.h" 3 4 int __attribute__((__cdecl__)) fseeko (FILE *, off_t, int); off_t __attribute__((__cdecl__)) ftello ( FILE *); int __attribute__((__cdecl__)) snprintf (char *restrict, size_t, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) vsnprintf (char *restrict, size_t, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) vfscanf (FILE *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 2, 0))) ; int __attribute__((__cdecl__)) vscanf (const char *, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 1, 0))) ; int __attribute__((__cdecl__)) vsscanf (const char *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 2, 0))) ; # 284 "/usr/include/stdio.h" 3 4 int __attribute__((__cdecl__)) asiprintf (char **, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; char * __attribute__((__cdecl__)) asniprintf (char *, size_t *, const char *, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; char * __attribute__((__cdecl__)) asnprintf (char *restrict, size_t *restrict, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) diprintf (int, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; int __attribute__((__cdecl__)) fiprintf (FILE *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; int __attribute__((__cdecl__)) fiscanf (FILE *, const char *, ...) __attribute__ ((__format__ (__scanf__, 2, 3))) ; int __attribute__((__cdecl__)) iprintf (const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2))) ; int __attribute__((__cdecl__)) iscanf (const char *, ...) __attribute__ ((__format__ (__scanf__, 1, 2))) ; int __attribute__((__cdecl__)) siprintf (char *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; int __attribute__((__cdecl__)) siscanf (const char *, const char *, ...) __attribute__ ((__format__ (__scanf__, 2, 3))) ; int __attribute__((__cdecl__)) sniprintf (char *, size_t, const char *, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) vasiprintf (char **, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; char * __attribute__((__cdecl__)) vasniprintf (char *, size_t *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; char * __attribute__((__cdecl__)) vasnprintf (char *, size_t *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) vdiprintf (int, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) vfiprintf (FILE *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) vfiscanf (FILE *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 2, 0))) ; int __attribute__((__cdecl__)) viprintf (const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 1, 0))) ; int __attribute__((__cdecl__)) viscanf (const char *, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 1, 0))) ; int __attribute__((__cdecl__)) vsiprintf (char *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) vsiscanf (const char *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 2, 0))) ; int __attribute__((__cdecl__)) vsniprintf (char *, size_t, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; # 339 "/usr/include/stdio.h" 3 4 FILE * __attribute__((__cdecl__)) fdopen (int, const char *); int __attribute__((__cdecl__)) fileno (FILE *); int __attribute__((__cdecl__)) pclose (FILE *); FILE * __attribute__((__cdecl__)) popen (const char *, const char *); void __attribute__((__cdecl__)) setbuffer (FILE *, char *, int); int __attribute__((__cdecl__)) setlinebuf (FILE *); int __attribute__((__cdecl__)) getw (FILE *); int __attribute__((__cdecl__)) putw (int, FILE *); int __attribute__((__cdecl__)) getc_unlocked (FILE *); int __attribute__((__cdecl__)) getchar_unlocked (void); void __attribute__((__cdecl__)) flockfile (FILE *); int __attribute__((__cdecl__)) ftrylockfile (FILE *); void __attribute__((__cdecl__)) funlockfile (FILE *); int __attribute__((__cdecl__)) putc_unlocked (int, FILE *); int __attribute__((__cdecl__)) putchar_unlocked (int); # 374 "/usr/include/stdio.h" 3 4 int __attribute__((__cdecl__)) dprintf (int, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; FILE * __attribute__((__cdecl__)) fmemopen (void *restrict, size_t, const char *restrict); FILE * __attribute__((__cdecl__)) open_memstream (char **, size_t *); int __attribute__((__cdecl__)) vdprintf (int, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) renameat (int, const char *, int, const char *); int __attribute__((__cdecl__)) _asiprintf_r (struct _reent *, char **, const char *, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; char * __attribute__((__cdecl__)) _asniprintf_r (struct _reent *, char *, size_t *, const char *, ...) __attribute__ ((__format__ (__printf__, 4, 5))) ; char * __attribute__((__cdecl__)) _asnprintf_r (struct _reent *, char *restrict, size_t *restrict, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 4, 5))) ; int __attribute__((__cdecl__)) _asprintf_r (struct _reent *, char **restrict, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) _diprintf_r (struct _reent *, int, const char *, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) _dprintf_r (struct _reent *, int, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) _fclose_r (struct _reent *, FILE *); int __attribute__((__cdecl__)) _fcloseall_r (struct _reent *); FILE * __attribute__((__cdecl__)) _fdopen_r (struct _reent *, int, const char *); int __attribute__((__cdecl__)) _fflush_r (struct _reent *, FILE *); int __attribute__((__cdecl__)) _fgetc_r (struct _reent *, FILE *); int __attribute__((__cdecl__)) _fgetc_unlocked_r (struct _reent *, FILE *); char * __attribute__((__cdecl__)) _fgets_r (struct _reent *, char *restrict, int, FILE *restrict); char * __attribute__((__cdecl__)) _fgets_unlocked_r (struct _reent *, char *restrict, int, FILE *restrict); int __attribute__((__cdecl__)) _fgetpos_r (struct _reent *, FILE *, fpos_t *); int __attribute__((__cdecl__)) _fsetpos_r (struct _reent *, FILE *, const fpos_t *); int __attribute__((__cdecl__)) _fiprintf_r (struct _reent *, FILE *, const char *, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) _fiscanf_r (struct _reent *, FILE *, const char *, ...) __attribute__ ((__format__ (__scanf__, 3, 4))) ; FILE * __attribute__((__cdecl__)) _fmemopen_r (struct _reent *, void *restrict, size_t, const char *restrict); FILE * __attribute__((__cdecl__)) _fopen_r (struct _reent *, const char *restrict, const char *restrict); FILE * __attribute__((__cdecl__)) _freopen_r (struct _reent *, const char *restrict, const char *restrict, FILE *restrict); int __attribute__((__cdecl__)) _fprintf_r (struct _reent *, FILE *restrict, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) _fpurge_r (struct _reent *, FILE *); int __attribute__((__cdecl__)) _fputc_r (struct _reent *, int, FILE *); int __attribute__((__cdecl__)) _fputc_unlocked_r (struct _reent *, int, FILE *); int __attribute__((__cdecl__)) _fputs_r (struct _reent *, const char *restrict, FILE *restrict); int __attribute__((__cdecl__)) _fputs_unlocked_r (struct _reent *, const char *restrict, FILE *restrict); size_t __attribute__((__cdecl__)) _fread_r (struct _reent *, void * restrict, size_t _size, size_t _n, FILE *restrict); size_t __attribute__((__cdecl__)) _fread_unlocked_r (struct _reent *, void * restrict, size_t _size, size_t _n, FILE *restrict); int __attribute__((__cdecl__)) _fscanf_r (struct _reent *, FILE *restrict, const char *restrict, ...) __attribute__ ((__format__ (__scanf__, 3, 4))) ; int __attribute__((__cdecl__)) _fseek_r (struct _reent *, FILE *, long, int); int __attribute__((__cdecl__)) _fseeko_r (struct _reent *, FILE *, _off_t, int); long __attribute__((__cdecl__)) _ftell_r (struct _reent *, FILE *); _off_t __attribute__((__cdecl__)) _ftello_r (struct _reent *, FILE *); void __attribute__((__cdecl__)) _rewind_r (struct _reent *, FILE *); size_t __attribute__((__cdecl__)) _fwrite_r (struct _reent *, const void * restrict, size_t _size, size_t _n, FILE *restrict); size_t __attribute__((__cdecl__)) _fwrite_unlocked_r (struct _reent *, const void * restrict, size_t _size, size_t _n, FILE *restrict); int __attribute__((__cdecl__)) _getc_r (struct _reent *, FILE *); int __attribute__((__cdecl__)) _getc_unlocked_r (struct _reent *, FILE *); int __attribute__((__cdecl__)) _getchar_r (struct _reent *); int __attribute__((__cdecl__)) _getchar_unlocked_r (struct _reent *); char * __attribute__((__cdecl__)) _gets_r (struct _reent *, char *); int __attribute__((__cdecl__)) _iprintf_r (struct _reent *, const char *, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; int __attribute__((__cdecl__)) _iscanf_r (struct _reent *, const char *, ...) __attribute__ ((__format__ (__scanf__, 2, 3))) ; FILE * __attribute__((__cdecl__)) _open_memstream_r (struct _reent *, char **, size_t *); void __attribute__((__cdecl__)) _perror_r (struct _reent *, const char *); int __attribute__((__cdecl__)) _printf_r (struct _reent *, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 2, 3))) ; int __attribute__((__cdecl__)) _putc_r (struct _reent *, int, FILE *); int __attribute__((__cdecl__)) _putc_unlocked_r (struct _reent *, int, FILE *); int __attribute__((__cdecl__)) _putchar_unlocked_r (struct _reent *, int); int __attribute__((__cdecl__)) _putchar_r (struct _reent *, int); int __attribute__((__cdecl__)) _puts_r (struct _reent *, const char *); int __attribute__((__cdecl__)) _remove_r (struct _reent *, const char *); int __attribute__((__cdecl__)) _rename_r (struct _reent *, const char *_old, const char *_new) ; int __attribute__((__cdecl__)) _scanf_r (struct _reent *, const char *restrict, ...) __attribute__ ((__format__ (__scanf__, 2, 3))) ; int __attribute__((__cdecl__)) _siprintf_r (struct _reent *, char *, const char *, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) _siscanf_r (struct _reent *, const char *, const char *, ...) __attribute__ ((__format__ (__scanf__, 3, 4))) ; int __attribute__((__cdecl__)) _sniprintf_r (struct _reent *, char *, size_t, const char *, ...) __attribute__ ((__format__ (__printf__, 4, 5))) ; int __attribute__((__cdecl__)) _snprintf_r (struct _reent *, char *restrict, size_t, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 4, 5))) ; int __attribute__((__cdecl__)) _sprintf_r (struct _reent *, char *restrict, const char *restrict, ...) __attribute__ ((__format__ (__printf__, 3, 4))) ; int __attribute__((__cdecl__)) _sscanf_r (struct _reent *, const char *restrict, const char *restrict, ...) __attribute__ ((__format__ (__scanf__, 3, 4))) ; char * __attribute__((__cdecl__)) _tempnam_r (struct _reent *, const char *, const char *); FILE * __attribute__((__cdecl__)) _tmpfile_r (struct _reent *); char * __attribute__((__cdecl__)) _tmpnam_r (struct _reent *, char *); int __attribute__((__cdecl__)) _ungetc_r (struct _reent *, int, FILE *); int __attribute__((__cdecl__)) _vasiprintf_r (struct _reent *, char **, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; char * __attribute__((__cdecl__)) _vasniprintf_r (struct _reent*, char *, size_t *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 4, 0))) ; char * __attribute__((__cdecl__)) _vasnprintf_r (struct _reent*, char *, size_t *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 4, 0))) ; int __attribute__((__cdecl__)) _vasprintf_r (struct _reent *, char **, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) _vdiprintf_r (struct _reent *, int, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) _vdprintf_r (struct _reent *, int, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) _vfiprintf_r (struct _reent *, FILE *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) _vfiscanf_r (struct _reent *, FILE *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 3, 0))) ; int __attribute__((__cdecl__)) _vfprintf_r (struct _reent *, FILE *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) _vfscanf_r (struct _reent *, FILE *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 3, 0))) ; int __attribute__((__cdecl__)) _viprintf_r (struct _reent *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) _viscanf_r (struct _reent *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 2, 0))) ; int __attribute__((__cdecl__)) _vprintf_r (struct _reent *, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 2, 0))) ; int __attribute__((__cdecl__)) _vscanf_r (struct _reent *, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 2, 0))) ; int __attribute__((__cdecl__)) _vsiprintf_r (struct _reent *, char *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) _vsiscanf_r (struct _reent *, const char *, const char *, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 3, 0))) ; int __attribute__((__cdecl__)) _vsniprintf_r (struct _reent *, char *, size_t, const char *, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 4, 0))) ; int __attribute__((__cdecl__)) _vsnprintf_r (struct _reent *, char *restrict, size_t, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 4, 0))) ; int __attribute__((__cdecl__)) _vsprintf_r (struct _reent *, char *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__printf__, 3, 0))) ; int __attribute__((__cdecl__)) _vsscanf_r (struct _reent *, const char *restrict, const char *restrict, __gnuc_va_list) __attribute__ ((__format__ (__scanf__, 3, 0))) ; int __attribute__((__cdecl__)) fpurge (FILE *); ssize_t __attribute__((__cdecl__)) __getdelim (char **, size_t *, int, FILE *); ssize_t __attribute__((__cdecl__)) __getline (char **, size_t *, FILE *); void __attribute__((__cdecl__)) clearerr_unlocked (FILE *); int __attribute__((__cdecl__)) feof_unlocked (FILE *); int __attribute__((__cdecl__)) ferror_unlocked (FILE *); int __attribute__((__cdecl__)) fileno_unlocked (FILE *); int __attribute__((__cdecl__)) fflush_unlocked (FILE *); int __attribute__((__cdecl__)) fgetc_unlocked (FILE *); int __attribute__((__cdecl__)) fputc_unlocked (int, FILE *); size_t __attribute__((__cdecl__)) fread_unlocked (void * restrict, size_t _size, size_t _n, FILE *restrict); size_t __attribute__((__cdecl__)) fwrite_unlocked (const void * restrict , size_t _size, size_t _n, FILE *); # 574 "/usr/include/stdio.h" 3 4 int __attribute__((__cdecl__)) __srget_r (struct _reent *, FILE *); int __attribute__((__cdecl__)) __swbuf_r (struct _reent *, int, FILE *); FILE *__attribute__((__cdecl__)) funopen (const void * __cookie, int (*__readfn)(void * __c, char *__buf, size_t __n), int (*__writefn)(void * __c, const char *__buf, size_t __n), _fpos64_t (*__seekfn)(void * __c, _fpos64_t __off, int __whence), int (*__closefn)(void * __c)) ; FILE *__attribute__((__cdecl__)) _funopen_r (struct _reent *, const void * __cookie, int (*__readfn)(void * __c, char *__buf, size_t __n), int (*__writefn)(void * __c, const char *__buf, size_t __n), _fpos64_t (*__seekfn)(void * __c, _fpos64_t __off, int __whence), int (*__closefn)(void * __c)) ; # 664 "/usr/include/stdio.h" 3 4 static __inline__ int __sgetc_r(struct _reent *__ptr, FILE *__p); static __inline__ int __sgetc_r(struct _reent *__ptr, FILE *__p) { int __c = (--(__p)->_r < 0 ? __srget_r(__ptr, __p) : (int)(*(__p)->_p++)); if ((__p->_flags & 0x4000) && (__c == '\r')) { int __c2 = (--(__p)->_r < 0 ? __srget_r(__ptr, __p) : (int)(*(__p)->_p++)); if (__c2 == '\n') __c = __c2; else ungetc(__c2, __p); } return __c; } static __inline__ int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) { if ((_p->_flags & 0x4000) && _c == '\n') __sputc_r (_ptr, '\r', _p); if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) return (*_p->_p++ = _c); else return (__swbuf_r(_ptr, _c, _p)); } # 769 "/usr/include/stdio.h" 3 4 # 5 "test.c" 2 # 8 "test.c" main() { printf("hello\n"); } int demo(char *a, char *b) { strcpy(a, "\n"); strcpy(a, gettext("Hello there")); 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); printf("\\"); gets(f); gets(f); syslog(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno)) syslog(LOG_CRIT,"malloc() failed"); syslog(LOG_ERR, attacker_string); } demo2() { char d[20]; char s[20]; int n; _mbscpy(d,s); memcpy(d,s); CopyMemory(d,s); lstrcat(d,s); strncpy(d,s); _tcsncpy(d,s); strncat(d,s,10); strncat(d,s,sizeof(d)); _tcsncat(d,s,sizeof(d)); n = strlen(d); MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)); MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName); MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0])); MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0])); SetSecurityDescriptorDacl(&sd,TRUE, # 73 "test.c" 3 4 ((void *)0) # 73 "test.c" ,FALSE); CreateProcess( # 75 "test.c" 3 4 ((void *)0) # 75 "test.c" , "C:\\Program Files\\GoodGuy\\GoodGuy.exe -x", ""); 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, # 91 "test.c" 3 4 ((void *)0) # 91 "test.c" )) != # 91 "test.c" 3 4 (-1) # 91 "test.c" ) { } } int testfile() { FILE *f; f = fopen("/etc/passwd", "r"); fclose(f); } # 113 "test.c" int accesstest() { int access = 0; } flawfinder-2.0.10/test-results-004.txt0000755400514740010010000000303113504006051020300 0ustar dwheelerDomain Userstest.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.10/test-results-005.txt0000755400514740010010000000032413504006051020303 0ustar dwheelerDomain Userstest-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.10/test-results-006.txt0000755400514740010010000000303113504006052020303 0ustar dwheelerDomain Userstest.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.10/test-results-008.txt0000644400514740010010000000131113504006056020305 0ustar dwheelerDomain UsersFlawfinder version 2.0.10, (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: 223 ANALYSIS SUMMARY: No hits found. Lines analyzed = 121 Physical Source Lines of Code (SLOC) = 84 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.10/test-results.csv0000755400514740010010000002723313504006050017764 0ustar dwheelerDomain UsersFile,Line,Column,Level,Category,Name,Warning,Suggestion,Note,CWEs,Context,Fingerprint test.c,32,2,5,buffer,gets,"Does not check for buffer overflows (CWE-120, CWE-20)",Use fgets() instead,,"CWE-120, CWE-20", gets(f);,6a5bb383fb44030b0d9428b17359e94ba3979bc1ce702be450427f85592c649a 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.",CWE-120," strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */",cbd19c308547e79af13436d8f7dbcf6c62e49e4f62ba9aee38fbef29e0772f74 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.",CWE-120," _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */",c3f6ba2c710efc878e66df4578894fd408452cb7cdec7ae6f492a3b1796f8c42 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));",4f5b73ff337a54d6e1d9a369659ca0ddb4f80e6b7e38a17e5b112f6d3e266e69 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);",9ecdc1e903acc16a646bf7909a630ae22a7593b70952c39ce6bd9c5a23fad0fd 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)",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb 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)",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);",5fed1e135b593b4c943e66e89a26ff131eba18b83a32a8af37d1c0bd7b01aadb 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)",,CWE-120," strcpy(b, a);",c01c8472bb53022e912da4da2faebc67d537855da324020c44bfd5e608a79b77 test.c,20,2,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 test.c,21,2,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 test.c,22,2,4,format,sprintf,Potential format string problem (CWE-134),Make format string constant,,CWE-134," sprintf(s, unknown, bug);",16ebc2ff96ee4bab2695783709e97b597ca9c8b8cc149e33aed859f0fafd3431 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,,CWE-134," printf(bf, x);",46f42896019245d2dffc4caf4fe018b073ce2a58203676eaa28b6374558a5b5d 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",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f 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",,"CWE-120, CWE-20"," scanf(""%s"", s);",3f169dd9fe508f70438f818770a3cb8b0f228e4245ea11a929a5fb0a7839fd5f 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,,CWE-134," syslog(LOG_ERR, attacker_string);",22e98963d5af7b197a090bd522d2d39b8d8ee7bdf08453fd2008939c92cd9677 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,,CWE-120," _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */",e00a4a1a0a3603db98a23fcff3c9cdfd9012f5a81826814d9508e0f22089b993 test.c,56,3,4,buffer,lstrcat,Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120),,,CWE-120," lstrcat(d,s);",364b4c512862fdccbca27d2fa7737995b5d24b637a760976c940ae636218d340 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",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf 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",,CWE-78," CreateProcess(NULL, ""C:\\Program Files\\GoodGuy\\GoodGuy.exe -x"", """");",3c712b38d0857bde3832d85ad35ac9859be55c5f5f1c20af659a577dd4d0acbf test.c,95,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",,"CWE-120, CWE-20"," while ((optc = getopt_long (argc, argv, ""a"",longopts, NULL )) != EOF) {",5bedf6e5bccf596008ef191ec4c5d4cc51a32cff0c05ef62d5f10fab93d0cc24 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.,CWE-120," strcpy(a, gettext(""Hello there"")); // Did this work?",d64070fb93ff0bb797fb926f4dddc7212d42f77e288d5ceb0cd30ed2979fa28d 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.,CWE-120," sprintf(s, ""hello"");",907b46be1c3ea7b38f90a4d1b0f43b7751cd8cbe38fae840930ff006b702157d 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",,CWE-119!/CWE-120, char d[20];,36c87517700337a59cc3ad3218cfdde56cad37d69cdeccee5a55ab232d5c7946 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",,CWE-119!/CWE-120, char s[20];,213de8e8815fc84c423b55fd845fea541f25744718e486234364bb457863b597 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,,CWE-120," memcpy(d,s); // fail - no size",e667b352fb0748c67b607b11577b11bad87545779c39923e61839dd04056055f 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,,CWE-120," memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination",01bcc2c8ba2d928ac3315b4dcc6593042ea05e62888a10a6d2cf16797a65ed32 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,,CWE-120," memcpy(d,s,n); // fail - size unguessable",2517a2fb5981193a6017cca660d16e85aab133706cbec302df97aaa623fc77ef 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,,CWE-120," CopyMemory(d,s);",977f8c805ddd76ff32e0f7aea08701ba97d9ce6955136e98b308ed4f70eb2e11 test.c,101,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)",,,CWE-362," f = fopen(""/etc/passwd"", ""r""); ",2ec6928c77a8b54caa61d0459f367c4394ee1f5e6f488753f587bfa9c780bad8 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.,CWE-120," strcpy(a, ""\n""); // Did this work?",0badc5f4c500d17b42794feaca54ee0f49e607a32510af3ed749579001017edb 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.,CWE-120," sprintf(s, ""\n"");",c65fbd60851f3c8ace22332805966606488c0d242c1823493c582e267609b1a7 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",,CWE-120," scanf(""%10s"", s);",e24c4c801f10acfa93098b2bef58524efe4f88237f2dd8b58be9afa838616afe test.c,57,3,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 test.c,58,3,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 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",,CWE-120," strncat(d,s,10);",dd92f996a554bfbc038bea27640ba25dcf298383140a8330dca7cdacf493a701 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),,,CWE-126, n = strlen(d);,db7201c7df7f543ea76febb060bda167e414e71e3d18095fe1def69f8c47a4f6 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));",1813fc329227b38abae867d8023a9e29c7517d679fe55c86f8300dde681b6470 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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));",7c6cdcb10ad3a16b8bfd56e3dac84829f9bc3e39d4dde74a2be9bbe000102fc5 flawfinder-2.0.10/test-results.html0000755400514740010010000003503413504006050020133 0ustar dwheelerDomain Users Flawfinder Results

        Flawfinder Results

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

        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:95: [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:101: [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 = 38
        Lines analyzed = 122
        Physical Source Lines of Code (SLOC) = 84
        Hits@level = [0] 16 [1] 9 [2] 9 [3] 3 [4] 10 [5] 7
        Hits@level+ = [0+] 54 [1+] 38 [2+] 29 [3+] 20 [4+] 17 [5+] 7
        Hits/KSLOC@level+ = [0+] 642.857 [1+] 452.381 [2+] 345.238 [3+] 238.095 [4+] 202.381 [5+] 83.3333
        Suppressed hits = 2 (use --neverignore to show them)
        Minimum risk level = 1
        Not every hit is necessarily a security vulnerability.
        There may be other security vulnerabilities; review your code!
        See 'Secure Programming HOWTO' (https://dwheeler.com/secure-programs) for more information. flawfinder-2.0.10/test-results.txt0000755400514740010010000002050313504006050020001 0ustar dwheelerDomain UsersFlawfinder version 2.0.10, (C) 2001-2019 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 223 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:95: [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:101: [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 = 38 Lines analyzed = 122 Physical Source Lines of Code (SLOC) = 84 Hits@level = [0] 16 [1] 9 [2] 9 [3] 3 [4] 10 [5] 7 Hits@level+ = [0+] 54 [1+] 38 [2+] 29 [3+] 20 [4+] 17 [5+] 7 Hits/KSLOC@level+ = [0+] 642.857 [1+] 452.381 [2+] 345.238 [3+] 238.095 [4+] 202.381 [5+] 83.3333 Suppressed hits = 2 (use --neverignore to show them) Minimum risk level = 1 Not every hit is necessarily a security vulnerability. 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.10/test-saved-hitlist-006.txt0000755400514740010010000004533713504006052021401 0ustar dwheelerDomain Users(lp0 ccopy_reg _reconstructor p1 (c__main__ Hit p2 c__builtin__ object p3 Ntp4 Rp5 (dp6 S'category' p7 S'buffer' p8 sS'end' p9 I692 sS'name' p10 S'gets' p11 sS'parameters' p12 (lp13 S'' p14 aS'f' p15 asS'level' p16 I5 sS'url' p17 g14 sS'column' p18 I2 sS'context_text' p19 S' gets(f);' p20 sS'hook' p21 c__main__ normal p22 sS'warning' p23 S'Does not check for buffer overflows (CWE-120, CWE-20)' p24 sS'suggestion' p25 S'Use fgets() instead' p26 sS'input' p27 I1 sS'line' p28 I32 sS'filename' p29 S'test.c' p30 sS'start' p31 I688 sbag1 (g2 g3 Ntp32 Rp33 (dp34 g7 g8 sg9 I1462 sg10 S'strncat' p35 sg12 (lp36 g14 aS'd' p37 aS's' p38 aS'sizeof(d)' p39 asg16 I5 sg17 g14 sg18 I3 sg19 S' strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */' p40 sS'note' p41 S'Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.' p42 sg21 c__main__ c_strncat p43 sg23 S'Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120)' p44 sg25 S'Consider strcat_s, strlcat, snprintf, or automatically resizing strings' p45 sg28 I60 sg29 g30 sg31 I1455 sbag1 (g2 g3 Ntp46 Rp47 (dp48 g7 g8 sg9 I1539 sg10 S'_tcsncat' p49 sg12 (lp50 g14 aS'd' p51 aS's' p52 aS'sizeof(d)' p53 asg16 I5 sg17 g14 sg18 I3 sg19 S' _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */' p54 sg41 g42 sg21 g43 sg23 g44 sg25 S'Consider strcat_s, strlcat, or automatically resizing strings' p55 sg28 I61 sg29 g30 sg31 I1531 sbag1 (g2 g3 Ntp56 Rp57 (dp58 g7 g8 sg9 I1680 sg10 S'MultiByteToWideChar' p59 sg12 (lp60 g14 aS'CP_ACP' p61 aS'0' p62 aS'szName' p63 aS'-1' p64 aS'wszUserName' p65 aS'sizeof(wszUserName)' p66 asg16 I5 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));' p67 sg41 S'Risk is high, it appears that the size is given as bytes, but the function requires size as characters.' p68 sg21 c__main__ c_multi_byte_to_wide_char p69 sg23 S'Requires maximum length in CHARACTERS, not bytes (CWE-120)' p70 sg25 g14 sg28 I64 sg29 g30 sg31 I1661 sbag1 (g2 g3 Ntp71 Rp72 (dp73 g7 g8 sg9 I1815 sg10 S'MultiByteToWideChar' p74 sg12 (lp75 g14 aS'CP_ACP' p76 aS'0' p77 aS'szName' p78 aS'-1' p79 aS'wszUserName' p80 aS'sizeof wszUserName' p81 asg16 I5 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);' p82 sg41 g68 sg21 g69 sg23 g70 sg25 g14 sg28 I66 sg29 g30 sg31 I1796 sbag1 (g2 g3 Ntp83 Rp84 (dp85 g7 S'misc' p86 sg9 I2533 sg10 S'SetSecurityDescriptorDacl' p87 sg12 (lp88 g14 aS'&sd' p89 aS'TRUE' p90 aS'NULL' p91 aS'FALSE' p92 asg16 I5 sg17 g14 sg18 I3 sg31 I2508 sg19 S' SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);' p93 sg21 c__main__ c_hit_if_null p94 sg23 S'Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732)' p95 sg25 g14 sg28 I77 sg29 g30 sS'check_for_null' p96 I3 sbag84 ag1 (g2 g3 Ntp97 Rp98 (dp99 g7 g8 sg9 I372 sg10 S'strcpy' p100 sg12 (lp101 g14 aS'b' p102 aS'a' p103 asg16 I4 sg17 g14 sg18 I2 sg19 S' strcpy(b, a);' p104 sg21 c__main__ c_buffer p105 sg23 S'Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)' p106 sg25 S'Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)' p107 sg28 I17 sg29 g30 sg31 I366 sbag1 (g2 g3 Ntp108 Rp109 (dp110 g7 g8 sg9 I429 sg10 S'sprintf' p111 sg12 (lp112 g14 aS's' p113 aS'"hello %s"' p114 aS'bug' p115 asg16 I4 sg17 g14 sg18 I2 sg19 S' sprintf(s, "hello %s", bug);' p116 sg21 c__main__ c_sprintf p117 sg23 S'Does not check for buffer overflows (CWE-120)' p118 sg25 S'Use sprintf_s, snprintf, or vsnprintf' p119 sg28 I20 sg29 g30 sg31 I422 sbag1 (g2 g3 Ntp120 Rp121 (dp122 g7 g8 sg9 I459 sg10 S'sprintf' p123 sg12 (lp124 g14 aS's' p125 aS'gettext("hello %s")' p126 aS'bug' p127 asg16 I4 sg17 g14 sg18 I2 sg19 S' sprintf(s, gettext("hello %s"), bug);' p128 sg21 g117 sg23 g118 sg25 g119 sg28 I21 sg29 g30 sg31 I452 sbag1 (g2 g3 Ntp129 Rp130 (dp131 g7 S'format' p132 sg9 I498 sg10 S'sprintf' p133 sg12 (lp134 g14 aS's' p135 aS'unknown' p136 aS'bug' p137 asg16 I4 sg17 g14 sg18 I2 sg19 S' sprintf(s, unknown, bug);' p138 sg21 g117 sg23 S'Potential format string problem (CWE-134)' p139 sg25 S'Make format string constant' p140 sg28 I22 sg29 g30 sg31 I491 sbag1 (g2 g3 Ntp141 Rp142 (dp143 g7 g132 sg9 I524 sg10 S'printf' p144 sg12 (lp145 g14 aS'bf' p146 aS'x' p147 asg16 I4 sg17 g14 sg18 I2 sg19 S' printf(bf, x);' p148 sg21 c__main__ c_printf p149 sg23 S'If format strings can be influenced by an attacker, they can be exploited (CWE-134)' p150 sg25 S'Use a constant for the format specification' p151 sg28 I23 sg29 g30 sg31 I518 sbag1 (g2 g3 Ntp152 Rp153 (dp154 g7 g8 sg9 I557 sg10 S'scanf' p155 sg12 (lp156 g14 aS'"%s"' p157 aS's' p158 asg16 I4 sg17 g14 sg18 I2 sg19 S' scanf("%s", s);' p159 sg21 c__main__ c_scanf p160 sg23 S"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20)" p161 sg25 S'Specify a limit to %s, or use a different input function' p162 sg27 I1 sg28 I25 sg29 g30 sg31 I552 sbag1 (g2 g3 Ntp163 Rp164 (dp165 g7 g8 sg9 I593 sg10 S'scanf' p166 sg12 (lp167 g14 aS'"%s"' p168 ag158 asg16 I4 sg17 g14 sg18 I2 sg19 S' scanf("%s", s);' p169 sg21 g160 sg23 g161 sg25 g162 sg27 I1 sg28 I27 sg29 g30 sg31 I588 sbag1 (g2 g3 Ntp170 Rp171 (dp172 g7 g132 sg9 I997 sg10 S'syslog' p173 sg12 (lp174 g14 aS'LOG_ERR' p175 aS'attacker_string' p176 asg16 I4 sg17 g14 sg18 I2 sg19 S' syslog(LOG_ERR, attacker_string);' p177 sg21 g149 sS'format_position' p178 I2 sg23 S"If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134)" p179 sg25 S'Use a constant format string for syslog' p180 sg28 I38 sg29 g30 sg31 I991 sbag1 (g2 g3 Ntp181 Rp182 (dp183 g7 g8 sg9 I1088 sg10 S'_mbscpy' p184 sg12 (lp185 g14 aS'd' p186 aS's' p187 asg16 I4 sg17 g14 sg18 I3 sg19 S" _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */" p188 sg21 g105 sg23 g106 sg25 S'Consider using a function version that stops copying at the end of the buffer' p189 sg28 I49 sg29 g30 sg31 I1081 sbag1 (g2 g3 Ntp190 Rp191 (dp192 g7 g8 sg9 I1394 sg10 S'lstrcat' p193 sg12 (lp194 g14 aS'd' p195 aS's' p196 asg16 I4 sg17 g14 sg18 I3 sg19 S' lstrcat(d,s);' p197 sg21 g105 sg23 S'Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120)' p198 sg25 g14 sg28 I56 sg29 g30 sg31 I1387 sbag1 (g2 g3 Ntp199 Rp200 (dp201 g7 S'shell' p202 sg9 I2634 sg10 S'CreateProcess' p203 sg12 (lp204 g14 aS'NULL' p205 aS'"C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x"' p206 aS'""' p207 asg16 I3 sg17 g14 sg18 I3 sg31 I2621 sg19 S' CreateProcess(NULL, "C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x", "");' p208 sg21 g94 sg23 S'This causes a new process to execute and is difficult to use safely (CWE-78)' p209 sg25 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' p210 sg28 I79 sg29 g30 sg96 I1 sbag200 ag1 (g2 g3 Ntp211 Rp212 (dp213 g7 g8 sg9 I3057 sg10 S'getopt_long' p214 sg12 (lp215 g14 aS'argc' p216 aS'argv' p217 aS'"a"' p218 aS'longopts' p219 aS'NULL' p220 asg16 I3 sg17 S'dangers-c' p221 sg18 I20 sg19 S' while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) {' p222 sg21 g22 sg23 S'Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20)' p223 sg25 S'Check implementation on installation, or limit the size of all string inputs' p224 sg27 I1 sg28 I95 sg29 g30 sg31 I3046 sbag1 (g2 g3 Ntp225 Rp226 (dp227 g7 g8 sg9 I318 sg10 S'strcpy' p228 sg12 (lp229 g14 aS'a' p230 aS'gettext("Hello there")' p231 asg16 I2 sg17 g14 sg18 I2 sg19 S' strcpy(a, gettext("Hello there")); // Did this work?' p232 sg41 S'Risk is low because the source is a constant string.' p233 sg21 g105 sg23 g106 sg25 g107 sg28 I16 sg29 g30 sg31 I312 sbag1 (g2 g3 Ntp234 Rp235 (dp236 g7 g8 sg9 I407 sg10 S'sprintf' p237 sg12 (lp238 g14 aS's' p239 aS'"hello"' p240 asg16 I2 sg17 g14 sg18 I2 sg19 S' sprintf(s, "hello");' p241 sg41 S'Risk is low because the source has a constant maximum length.' p242 sg21 g117 sg23 g118 sg25 g119 sg28 I19 sg29 g30 sg31 I400 sbag1 (g2 g3 Ntp243 Rp244 (dp245 g7 g8 sg29 g30 sg9 I1047 sg10 S'char' p246 sg12 (lp247 sg16 I2 sg17 g14 sS'lookahead' p248 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" p249 sg18 I3 sg19 S' char d[20];' p250 sg21 c__main__ c_static_array p251 sg23 S'Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)' p252 sg25 S'Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length' p253 sg28 I45 sS'extract_lookahead' p254 I1 sg31 I1043 sbag1 (g2 g3 Ntp255 Rp256 (dp257 g7 g8 sg29 g30 sg9 I1061 sg10 S'char' p258 sg12 (lp259 sg16 I2 sg17 g14 sg248 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)); /" p260 sg18 I3 sg19 S' char s[20];' p261 sg21 g251 sg23 g252 sg25 g253 sg28 I46 sg254 I1 sg31 I1057 sbag1 (g2 g3 Ntp262 Rp263 (dp264 g7 g8 sg9 I1161 sg10 S'memcpy' p265 sg12 (lp266 g14 aS'd' p267 aS's' p268 asg16 I2 sg17 g14 sg18 I3 sg19 S' memcpy(d,s); // fail - no size' p269 sg21 c__main__ c_memcpy p270 sg23 S'Does not check for buffer overflows when copying to destination (CWE-120)' p271 sg25 S'Make sure destination can always hold the source data' p272 sg28 I50 sg29 g30 sg31 I1155 sbag1 (g2 g3 Ntp273 Rp274 (dp275 g7 g8 sg9 I1268 sg10 S'memcpy' p276 sg12 (lp277 g14 aS'&n' p278 aS's' p279 aS'sizeof(s)' p280 asg16 I2 sg17 g14 sg18 I3 sg19 S' memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination' p281 sg21 g270 sg23 g271 sg25 g272 sg28 I53 sg29 g30 sg31 I1262 sbag1 (g2 g3 Ntp282 Rp283 (dp284 g7 g8 sg9 I1330 sg10 S'memcpy' p285 sg12 (lp286 g14 aS'd' p287 aS's' p288 aS'n' p289 asg16 I2 sg17 g14 sg18 I3 sg19 S' memcpy(d,s,n); // fail - size unguessable' p290 sg21 g270 sg23 g271 sg25 g272 sg28 I54 sg29 g30 sg31 I1324 sbag1 (g2 g3 Ntp291 Rp292 (dp293 g7 g8 sg9 I1378 sg10 S'CopyMemory' p294 sg12 (lp295 g14 aS'd' p296 aS's' p297 asg16 I2 sg17 g14 sg18 I3 sg19 S' CopyMemory(d,s);' p298 sg21 g270 sg23 g271 sg25 g272 sg28 I55 sg29 g30 sg31 I1368 sbag1 (g2 g3 Ntp299 Rp300 (dp301 g7 g86 sg9 I3151 sg10 S'fopen' p302 sg12 (lp303 g14 aS'"/etc/passwd"' p304 aS'"r"' p305 asg16 I2 sg17 g14 sg18 I7 sg19 S' f = fopen("/etc/passwd", "r"); ' p306 sg21 g22 sg23 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)' p307 sg25 g14 sg28 I101 sg29 g30 sg31 I3146 sbag1 (g2 g3 Ntp308 Rp309 (dp310 g7 g8 sg9 I282 sg10 S'strcpy' p311 sg12 (lp312 g14 aS'a' p313 aS'"\\n"' p314 asg16 I1 sg17 g14 sg18 I2 sg19 S' strcpy(a, "\\n"); // Did this work?' p315 sg41 S'Risk is low because the source is a constant character.' p316 sg21 g105 sg23 g106 sg25 g107 sg28 I15 sg29 g30 sg31 I276 sbag1 (g2 g3 Ntp317 Rp318 (dp319 g7 g8 sg9 I388 sg10 S'sprintf' p320 sg12 (lp321 g14 aS's' p322 aS'"\\n"' p323 asg16 I1 sg17 g14 sg18 I2 sg19 S' sprintf(s, "\\n");' p324 sg41 S'Risk is low because the source is a constant character.' p325 sg21 g117 sg23 g118 sg25 g119 sg28 I18 sg29 g30 sg31 I381 sbag1 (g2 g3 Ntp326 Rp327 (dp328 g7 g8 sg9 I574 sg10 S'scanf' p329 sg12 (lp330 g14 aS'"%10s"' p331 ag158 asg16 I1 sg17 g14 sg18 I2 sg19 S' scanf("%10s", s);' p332 sg21 g160 sg23 S"It's unclear if the %s limit in the format string is small enough (CWE-120)" p333 sg25 S'Check that the limit is sufficiently small, or use a different input function' p334 sg27 I1 sg28 I26 sg29 g30 sg31 I569 sbag1 (g2 g3 Ntp335 Rp336 (dp337 g7 g8 sg9 I1410 sg10 S'strncpy' p338 sg12 (lp339 g14 aS'd' p340 aS's' p341 asg16 I1 sg17 g14 sg18 I3 sg19 S' strncpy(d,s);' p342 sg21 g105 sg23 S"Easily used incorrectly; doesn't always \\0-terminate or check for invalid pointers [MS-banned] (CWE-120)" p343 sg25 g14 sg28 I57 sg29 g30 sg31 I1403 sbag1 (g2 g3 Ntp344 Rp345 (dp346 g7 g8 sg9 I1427 sg10 S'_tcsncpy' p347 sg12 (lp348 g14 aS'd' p349 aS's' p350 asg16 I1 sg17 g14 sg18 I3 sg19 S' _tcsncpy(d,s);' p351 sg21 g105 sg23 g343 sg25 g14 sg28 I58 sg29 g30 sg31 I1419 sbag1 (g2 g3 Ntp352 Rp353 (dp354 g7 g8 sg9 I1443 sg10 S'strncat' p355 sg12 (lp356 g14 aS'd' p357 aS's' p358 aS'10' p359 asg16 I1 sg17 g14 sg18 I3 sg19 S' strncat(d,s,10);' p360 sg21 g43 sg23 g44 sg25 g45 sg28 I59 sg29 g30 sg31 I1436 sbag1 (g2 g3 Ntp361 Rp362 (dp363 g7 g8 sg9 I1599 sg10 S'strlen' p364 sg12 (lp365 g14 aS'd' p366 asg16 I1 sg17 g14 sg18 I7 sg19 S' n = strlen(d);' p367 sg21 g22 sg23 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)' p368 sg25 g14 sg28 I62 sg29 g30 sg31 I1593 sbag1 (g2 g3 Ntp369 Rp370 (dp371 g7 g8 sg9 I1918 sg10 S'MultiByteToWideChar' p372 sg12 (lp373 g14 aS'CP_ACP' p374 aS'0' p375 aS'szName' p376 aS'-1' p377 aS'wszUserName' p378 aS'sizeof(wszUserName)/sizeof(wszUserName[0])' p379 asg16 I1 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));' p380 sg41 S'Risk is very low, the length appears to be in characters not bytes.' p381 sg21 g69 sg23 g70 sg25 g14 sg28 I68 sg29 g30 sg31 I1899 sbag1 (g2 g3 Ntp382 Rp383 (dp384 g7 g8 sg9 I2045 sg10 S'MultiByteToWideChar' p385 sg12 (lp386 g14 aS'CP_ACP' p387 aS'0' p388 aS'szName' p389 aS'-1' p390 aS'wszUserName' p391 aS'sizeof wszUserName /sizeof(wszUserName[0])' p392 asg16 I1 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));' p393 sg41 g381 sg21 g69 sg23 g70 sg25 g14 sg28 I70 sg29 g30 sg31 I2026 sbag1 (g2 g3 Ntp394 Rp395 (dp396 g7 g132 sg9 I200 sg10 S'printf' p397 sg12 (lp398 g14 aS'"hello\\n"' p399 asg16 I0 sg17 g14 sg18 I2 sg19 S' printf("hello\\n");' p400 sg41 S'Constant format string, so not considered risky.' p401 sg21 g149 sg23 g150 sg25 g151 sg28 I9 sg29 g30 sg31 I194 sbag1 (g2 g3 Ntp402 Rp403 (dp404 g7 g8 sg9 I539 sg10 S'scanf' p405 sg12 (lp406 g14 aS'"%d"' p407 aS'&x' p408 asg16 I0 sg17 g14 sg18 I2 sg19 S' scanf("%d", &x);' p409 sg41 S'No risky scanf format detected.' p410 sg21 g160 sg23 g161 sg25 g162 sg27 I1 sg28 I24 sg29 g30 sg31 I534 sbag1 (g2 g3 Ntp411 Rp412 (dp413 g7 g132 sg9 I643 sg10 S'printf' p414 sg12 (lp415 g14 aS'"\\\\"' p416 asg16 I0 sg17 g14 sg18 I2 sg19 S' printf("\\\\");' p417 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I29 sg29 g30 sg31 I637 sbag1 (g2 g3 Ntp418 Rp419 (dp420 g7 g132 sg9 I837 sg10 S'syslog' p421 sg12 (lp422 g14 aS'LOG_ERR' p423 aS'"cannot open config file (%s): %s"' p424 aS'filename' p425 aS'strerror(errno)' p426 asg16 I0 sg17 g14 sg18 I2 sg19 S' syslog(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno))' p427 sg41 g401 sg21 g149 sg178 I2 sg23 g179 sg25 g180 sg28 I35 sg29 g30 sg31 I831 sbag1 (g2 g3 Ntp428 Rp429 (dp430 g7 g132 sg9 I914 sg10 S'syslog' p431 sg12 (lp432 g14 aS'LOG_CRIT' p433 aS'"malloc() failed"' p434 asg16 I0 sg17 g14 sg18 I2 sg19 S' syslog(LOG_CRIT,"malloc() failed");' p435 sg41 g401 sg21 g149 sg178 I2 sg23 g179 sg25 g180 sg28 I36 sg29 g30 sg31 I908 sbag1 (g2 g3 Ntp436 Rp437 (dp438 g7 g132 sg9 I2745 sg10 S'printf' p439 sg12 (lp440 g14 aS'"%c\\n"' p441 aS"'x'" p442 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'x\');' p443 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I81 sg29 g30 sg31 I2739 sbag1 (g2 g3 Ntp444 Rp445 (dp446 g7 g132 sg9 I2768 sg10 S'printf' p447 sg12 (lp448 g14 aS'"%c\\n"' p449 aS'\'"\'' p450 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'"\');' p451 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I82 sg29 g30 sg31 I2762 sbag1 (g2 g3 Ntp452 Rp453 (dp454 g7 g132 sg9 I2791 sg10 S'printf' p455 sg12 (lp456 g14 aS'"%c\\n"' p457 aS'\'\\"\'' p458 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\"\');' p459 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I83 sg29 g30 sg31 I2785 sbag1 (g2 g3 Ntp460 Rp461 (dp462 g7 g132 sg9 I2815 sg10 S'printf' p463 sg12 (lp464 g14 aS'"%c\\n"' p465 aS"'\\''" p466 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\\'\');' p467 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I84 sg29 g30 sg31 I2809 sbag1 (g2 g3 Ntp468 Rp469 (dp470 g7 g132 sg9 I2839 sg10 S'printf' p471 sg12 (lp472 g14 aS'"%c\\n"' p473 aS"'\\177'" p474 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\177\');' p475 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I85 sg29 g30 sg31 I2833 sbag1 (g2 g3 Ntp476 Rp477 (dp478 g7 g132 sg9 I2865 sg10 S'printf' p479 sg12 (lp480 g14 aS'"%c\\n"' p481 aS"'\\xfe'" p482 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\xfe\');' p483 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I86 sg29 g30 sg31 I2859 sbag1 (g2 g3 Ntp484 Rp485 (dp486 g7 g132 sg9 I2891 sg10 S'printf' p487 sg12 (lp488 g14 aS'"%c\\n"' p489 aS"'\\xd'" p490 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\xd\');' p491 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I87 sg29 g30 sg31 I2885 sbag1 (g2 g3 Ntp492 Rp493 (dp494 g7 g132 sg9 I2916 sg10 S'printf' p495 sg12 (lp496 g14 aS'"%c\\n"' p497 aS"'\\n'" p498 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\n\');' p499 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I88 sg29 g30 sg31 I2910 sbag1 (g2 g3 Ntp500 Rp501 (dp502 g7 g132 sg9 I2940 sg10 S'printf' p503 sg12 (lp504 g14 aS'"%c\\n"' p505 aS"'\\\\'" p506 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\\\\');' p507 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I89 sg29 g30 sg31 I2934 sbag1 (g2 g3 Ntp508 Rp509 (dp510 g7 g132 sg9 I2964 sg10 S'printf' p511 sg12 (lp512 g14 aS'"%c\\n"' p513 aS'"\'"' p514 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", "\'");' p515 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I90 sg29 g30 sg31 I2958 sbag1 (g2 g3 Ntp516 Rp517 (dp518 g7 g132 sg9 I3289 sg10 S'fprintf' p519 sg12 (lp520 g14 aS'stderr' p521 aS'"Assertion failed.\\n"\\\n "File: %s\\nLine: %d\\n"\\\n "Assertion: %s\\n\\n"' p522 aS'__FILE__' p523 aS'__LINE__' p524 aS'#x' p525 asg16 I0 sg17 g14 sg18 I2 sg19 S' fprintf(stderr,"Assertion failed.\\n"\\' p526 sg41 g401 sg21 g149 sg178 I2 sg23 g150 sg25 g151 sg28 I109 sg29 g30 sg31 I3282 sba.flawfinder-2.0.10/test-saved-hitlist-008.txt0000644400514740010010000004533713504006056021404 0ustar dwheelerDomain Users(lp0 ccopy_reg _reconstructor p1 (c__main__ Hit p2 c__builtin__ object p3 Ntp4 Rp5 (dp6 S'category' p7 S'buffer' p8 sS'end' p9 I692 sS'name' p10 S'gets' p11 sS'parameters' p12 (lp13 S'' p14 aS'f' p15 asS'level' p16 I5 sS'url' p17 g14 sS'column' p18 I2 sS'context_text' p19 S' gets(f);' p20 sS'hook' p21 c__main__ normal p22 sS'warning' p23 S'Does not check for buffer overflows (CWE-120, CWE-20)' p24 sS'suggestion' p25 S'Use fgets() instead' p26 sS'input' p27 I1 sS'line' p28 I32 sS'filename' p29 S'test.c' p30 sS'start' p31 I688 sbag1 (g2 g3 Ntp32 Rp33 (dp34 g7 g8 sg9 I1462 sg10 S'strncat' p35 sg12 (lp36 g14 aS'd' p37 aS's' p38 aS'sizeof(d)' p39 asg16 I5 sg17 g14 sg18 I3 sg19 S' strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */' p40 sS'note' p41 S'Risk is high; the length parameter appears to be a constant, instead of computing the number of characters left.' p42 sg21 c__main__ c_strncat p43 sg23 S'Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) [MS-banned] (CWE-120)' p44 sg25 S'Consider strcat_s, strlcat, snprintf, or automatically resizing strings' p45 sg28 I60 sg29 g30 sg31 I1455 sbag1 (g2 g3 Ntp46 Rp47 (dp48 g7 g8 sg9 I1539 sg10 S'_tcsncat' p49 sg12 (lp50 g14 aS'd' p51 aS's' p52 aS'sizeof(d)' p53 asg16 I5 sg17 g14 sg18 I3 sg19 S' _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */' p54 sg41 g42 sg21 g43 sg23 g44 sg25 S'Consider strcat_s, strlcat, or automatically resizing strings' p55 sg28 I61 sg29 g30 sg31 I1531 sbag1 (g2 g3 Ntp56 Rp57 (dp58 g7 g8 sg9 I1680 sg10 S'MultiByteToWideChar' p59 sg12 (lp60 g14 aS'CP_ACP' p61 aS'0' p62 aS'szName' p63 aS'-1' p64 aS'wszUserName' p65 aS'sizeof(wszUserName)' p66 asg16 I5 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));' p67 sg41 S'Risk is high, it appears that the size is given as bytes, but the function requires size as characters.' p68 sg21 c__main__ c_multi_byte_to_wide_char p69 sg23 S'Requires maximum length in CHARACTERS, not bytes (CWE-120)' p70 sg25 g14 sg28 I64 sg29 g30 sg31 I1661 sbag1 (g2 g3 Ntp71 Rp72 (dp73 g7 g8 sg9 I1815 sg10 S'MultiByteToWideChar' p74 sg12 (lp75 g14 aS'CP_ACP' p76 aS'0' p77 aS'szName' p78 aS'-1' p79 aS'wszUserName' p80 aS'sizeof wszUserName' p81 asg16 I5 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);' p82 sg41 g68 sg21 g69 sg23 g70 sg25 g14 sg28 I66 sg29 g30 sg31 I1796 sbag1 (g2 g3 Ntp83 Rp84 (dp85 g7 S'misc' p86 sg9 I2533 sg10 S'SetSecurityDescriptorDacl' p87 sg12 (lp88 g14 aS'&sd' p89 aS'TRUE' p90 aS'NULL' p91 aS'FALSE' p92 asg16 I5 sg17 g14 sg18 I3 sg31 I2508 sg19 S' SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);' p93 sg21 c__main__ c_hit_if_null p94 sg23 S'Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), which would even forbid administrator access (CWE-732)' p95 sg25 g14 sg28 I77 sg29 g30 sS'check_for_null' p96 I3 sbag84 ag1 (g2 g3 Ntp97 Rp98 (dp99 g7 g8 sg9 I372 sg10 S'strcpy' p100 sg12 (lp101 g14 aS'b' p102 aS'a' p103 asg16 I4 sg17 g14 sg18 I2 sg19 S' strcpy(b, a);' p104 sg21 c__main__ c_buffer p105 sg23 S'Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)' p106 sg25 S'Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)' p107 sg28 I17 sg29 g30 sg31 I366 sbag1 (g2 g3 Ntp108 Rp109 (dp110 g7 g8 sg9 I429 sg10 S'sprintf' p111 sg12 (lp112 g14 aS's' p113 aS'"hello %s"' p114 aS'bug' p115 asg16 I4 sg17 g14 sg18 I2 sg19 S' sprintf(s, "hello %s", bug);' p116 sg21 c__main__ c_sprintf p117 sg23 S'Does not check for buffer overflows (CWE-120)' p118 sg25 S'Use sprintf_s, snprintf, or vsnprintf' p119 sg28 I20 sg29 g30 sg31 I422 sbag1 (g2 g3 Ntp120 Rp121 (dp122 g7 g8 sg9 I459 sg10 S'sprintf' p123 sg12 (lp124 g14 aS's' p125 aS'gettext("hello %s")' p126 aS'bug' p127 asg16 I4 sg17 g14 sg18 I2 sg19 S' sprintf(s, gettext("hello %s"), bug);' p128 sg21 g117 sg23 g118 sg25 g119 sg28 I21 sg29 g30 sg31 I452 sbag1 (g2 g3 Ntp129 Rp130 (dp131 g7 S'format' p132 sg9 I498 sg10 S'sprintf' p133 sg12 (lp134 g14 aS's' p135 aS'unknown' p136 aS'bug' p137 asg16 I4 sg17 g14 sg18 I2 sg19 S' sprintf(s, unknown, bug);' p138 sg21 g117 sg23 S'Potential format string problem (CWE-134)' p139 sg25 S'Make format string constant' p140 sg28 I22 sg29 g30 sg31 I491 sbag1 (g2 g3 Ntp141 Rp142 (dp143 g7 g132 sg9 I524 sg10 S'printf' p144 sg12 (lp145 g14 aS'bf' p146 aS'x' p147 asg16 I4 sg17 g14 sg18 I2 sg19 S' printf(bf, x);' p148 sg21 c__main__ c_printf p149 sg23 S'If format strings can be influenced by an attacker, they can be exploited (CWE-134)' p150 sg25 S'Use a constant for the format specification' p151 sg28 I23 sg29 g30 sg31 I518 sbag1 (g2 g3 Ntp152 Rp153 (dp154 g7 g8 sg9 I557 sg10 S'scanf' p155 sg12 (lp156 g14 aS'"%s"' p157 aS's' p158 asg16 I4 sg17 g14 sg18 I2 sg19 S' scanf("%s", s);' p159 sg21 c__main__ c_scanf p160 sg23 S"The scanf() family's %s operation, without a limit specification, permits buffer overflows (CWE-120, CWE-20)" p161 sg25 S'Specify a limit to %s, or use a different input function' p162 sg27 I1 sg28 I25 sg29 g30 sg31 I552 sbag1 (g2 g3 Ntp163 Rp164 (dp165 g7 g8 sg9 I593 sg10 S'scanf' p166 sg12 (lp167 g14 aS'"%s"' p168 ag158 asg16 I4 sg17 g14 sg18 I2 sg19 S' scanf("%s", s);' p169 sg21 g160 sg23 g161 sg25 g162 sg27 I1 sg28 I27 sg29 g30 sg31 I588 sbag1 (g2 g3 Ntp170 Rp171 (dp172 g7 g132 sg9 I997 sg10 S'syslog' p173 sg12 (lp174 g14 aS'LOG_ERR' p175 aS'attacker_string' p176 asg16 I4 sg17 g14 sg18 I2 sg19 S' syslog(LOG_ERR, attacker_string);' p177 sg21 g149 sS'format_position' p178 I2 sg23 S"If syslog's format strings can be influenced by an attacker, they can be exploited (CWE-134)" p179 sg25 S'Use a constant format string for syslog' p180 sg28 I38 sg29 g30 sg31 I991 sbag1 (g2 g3 Ntp181 Rp182 (dp183 g7 g8 sg9 I1088 sg10 S'_mbscpy' p184 sg12 (lp185 g14 aS'd' p186 aS's' p187 asg16 I4 sg17 g14 sg18 I3 sg19 S" _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */" p188 sg21 g105 sg23 g106 sg25 S'Consider using a function version that stops copying at the end of the buffer' p189 sg28 I49 sg29 g30 sg31 I1081 sbag1 (g2 g3 Ntp190 Rp191 (dp192 g7 g8 sg9 I1394 sg10 S'lstrcat' p193 sg12 (lp194 g14 aS'd' p195 aS's' p196 asg16 I4 sg17 g14 sg18 I3 sg19 S' lstrcat(d,s);' p197 sg21 g105 sg23 S'Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120)' p198 sg25 g14 sg28 I56 sg29 g30 sg31 I1387 sbag1 (g2 g3 Ntp199 Rp200 (dp201 g7 S'shell' p202 sg9 I2634 sg10 S'CreateProcess' p203 sg12 (lp204 g14 aS'NULL' p205 aS'"C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x"' p206 aS'""' p207 asg16 I3 sg17 g14 sg18 I3 sg31 I2621 sg19 S' CreateProcess(NULL, "C:\\\\Program Files\\\\GoodGuy\\\\GoodGuy.exe -x", "");' p208 sg21 g94 sg23 S'This causes a new process to execute and is difficult to use safely (CWE-78)' p209 sg25 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' p210 sg28 I79 sg29 g30 sg96 I1 sbag200 ag1 (g2 g3 Ntp211 Rp212 (dp213 g7 g8 sg9 I3057 sg10 S'getopt_long' p214 sg12 (lp215 g14 aS'argc' p216 aS'argv' p217 aS'"a"' p218 aS'longopts' p219 aS'NULL' p220 asg16 I3 sg17 S'dangers-c' p221 sg18 I20 sg19 S' while ((optc = getopt_long (argc, argv, "a",longopts, NULL )) != EOF) {' p222 sg21 g22 sg23 S'Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20)' p223 sg25 S'Check implementation on installation, or limit the size of all string inputs' p224 sg27 I1 sg28 I95 sg29 g30 sg31 I3046 sbag1 (g2 g3 Ntp225 Rp226 (dp227 g7 g8 sg9 I318 sg10 S'strcpy' p228 sg12 (lp229 g14 aS'a' p230 aS'gettext("Hello there")' p231 asg16 I2 sg17 g14 sg18 I2 sg19 S' strcpy(a, gettext("Hello there")); // Did this work?' p232 sg41 S'Risk is low because the source is a constant string.' p233 sg21 g105 sg23 g106 sg25 g107 sg28 I16 sg29 g30 sg31 I312 sbag1 (g2 g3 Ntp234 Rp235 (dp236 g7 g8 sg9 I407 sg10 S'sprintf' p237 sg12 (lp238 g14 aS's' p239 aS'"hello"' p240 asg16 I2 sg17 g14 sg18 I2 sg19 S' sprintf(s, "hello");' p241 sg41 S'Risk is low because the source has a constant maximum length.' p242 sg21 g117 sg23 g118 sg25 g119 sg28 I19 sg29 g30 sg31 I400 sbag1 (g2 g3 Ntp243 Rp244 (dp245 g7 g8 sg29 g30 sg9 I1047 sg10 S'char' p246 sg12 (lp247 sg16 I2 sg17 g14 sS'lookahead' p248 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" p249 sg18 I3 sg19 S' char d[20];' p250 sg21 c__main__ c_static_array p251 sg23 S'Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)' p252 sg25 S'Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length' p253 sg28 I45 sS'extract_lookahead' p254 I1 sg31 I1043 sbag1 (g2 g3 Ntp255 Rp256 (dp257 g7 g8 sg29 g30 sg9 I1061 sg10 S'char' p258 sg12 (lp259 sg16 I2 sg17 g14 sg248 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)); /" p260 sg18 I3 sg19 S' char s[20];' p261 sg21 g251 sg23 g252 sg25 g253 sg28 I46 sg254 I1 sg31 I1057 sbag1 (g2 g3 Ntp262 Rp263 (dp264 g7 g8 sg9 I1161 sg10 S'memcpy' p265 sg12 (lp266 g14 aS'd' p267 aS's' p268 asg16 I2 sg17 g14 sg18 I3 sg19 S' memcpy(d,s); // fail - no size' p269 sg21 c__main__ c_memcpy p270 sg23 S'Does not check for buffer overflows when copying to destination (CWE-120)' p271 sg25 S'Make sure destination can always hold the source data' p272 sg28 I50 sg29 g30 sg31 I1155 sbag1 (g2 g3 Ntp273 Rp274 (dp275 g7 g8 sg9 I1268 sg10 S'memcpy' p276 sg12 (lp277 g14 aS'&n' p278 aS's' p279 aS'sizeof(s)' p280 asg16 I2 sg17 g14 sg18 I3 sg19 S' memcpy(&n,s,sizeof(s)); // fail - sizeof not of destination' p281 sg21 g270 sg23 g271 sg25 g272 sg28 I53 sg29 g30 sg31 I1262 sbag1 (g2 g3 Ntp282 Rp283 (dp284 g7 g8 sg9 I1330 sg10 S'memcpy' p285 sg12 (lp286 g14 aS'd' p287 aS's' p288 aS'n' p289 asg16 I2 sg17 g14 sg18 I3 sg19 S' memcpy(d,s,n); // fail - size unguessable' p290 sg21 g270 sg23 g271 sg25 g272 sg28 I54 sg29 g30 sg31 I1324 sbag1 (g2 g3 Ntp291 Rp292 (dp293 g7 g8 sg9 I1378 sg10 S'CopyMemory' p294 sg12 (lp295 g14 aS'd' p296 aS's' p297 asg16 I2 sg17 g14 sg18 I3 sg19 S' CopyMemory(d,s);' p298 sg21 g270 sg23 g271 sg25 g272 sg28 I55 sg29 g30 sg31 I1368 sbag1 (g2 g3 Ntp299 Rp300 (dp301 g7 g86 sg9 I3151 sg10 S'fopen' p302 sg12 (lp303 g14 aS'"/etc/passwd"' p304 aS'"r"' p305 asg16 I2 sg17 g14 sg18 I7 sg19 S' f = fopen("/etc/passwd", "r"); ' p306 sg21 g22 sg23 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)' p307 sg25 g14 sg28 I101 sg29 g30 sg31 I3146 sbag1 (g2 g3 Ntp308 Rp309 (dp310 g7 g8 sg9 I282 sg10 S'strcpy' p311 sg12 (lp312 g14 aS'a' p313 aS'"\\n"' p314 asg16 I1 sg17 g14 sg18 I2 sg19 S' strcpy(a, "\\n"); // Did this work?' p315 sg41 S'Risk is low because the source is a constant character.' p316 sg21 g105 sg23 g106 sg25 g107 sg28 I15 sg29 g30 sg31 I276 sbag1 (g2 g3 Ntp317 Rp318 (dp319 g7 g8 sg9 I388 sg10 S'sprintf' p320 sg12 (lp321 g14 aS's' p322 aS'"\\n"' p323 asg16 I1 sg17 g14 sg18 I2 sg19 S' sprintf(s, "\\n");' p324 sg41 S'Risk is low because the source is a constant character.' p325 sg21 g117 sg23 g118 sg25 g119 sg28 I18 sg29 g30 sg31 I381 sbag1 (g2 g3 Ntp326 Rp327 (dp328 g7 g8 sg9 I574 sg10 S'scanf' p329 sg12 (lp330 g14 aS'"%10s"' p331 ag158 asg16 I1 sg17 g14 sg18 I2 sg19 S' scanf("%10s", s);' p332 sg21 g160 sg23 S"It's unclear if the %s limit in the format string is small enough (CWE-120)" p333 sg25 S'Check that the limit is sufficiently small, or use a different input function' p334 sg27 I1 sg28 I26 sg29 g30 sg31 I569 sbag1 (g2 g3 Ntp335 Rp336 (dp337 g7 g8 sg9 I1410 sg10 S'strncpy' p338 sg12 (lp339 g14 aS'd' p340 aS's' p341 asg16 I1 sg17 g14 sg18 I3 sg19 S' strncpy(d,s);' p342 sg21 g105 sg23 S"Easily used incorrectly; doesn't always \\0-terminate or check for invalid pointers [MS-banned] (CWE-120)" p343 sg25 g14 sg28 I57 sg29 g30 sg31 I1403 sbag1 (g2 g3 Ntp344 Rp345 (dp346 g7 g8 sg9 I1427 sg10 S'_tcsncpy' p347 sg12 (lp348 g14 aS'd' p349 aS's' p350 asg16 I1 sg17 g14 sg18 I3 sg19 S' _tcsncpy(d,s);' p351 sg21 g105 sg23 g343 sg25 g14 sg28 I58 sg29 g30 sg31 I1419 sbag1 (g2 g3 Ntp352 Rp353 (dp354 g7 g8 sg9 I1443 sg10 S'strncat' p355 sg12 (lp356 g14 aS'd' p357 aS's' p358 aS'10' p359 asg16 I1 sg17 g14 sg18 I3 sg19 S' strncat(d,s,10);' p360 sg21 g43 sg23 g44 sg25 g45 sg28 I59 sg29 g30 sg31 I1436 sbag1 (g2 g3 Ntp361 Rp362 (dp363 g7 g8 sg9 I1599 sg10 S'strlen' p364 sg12 (lp365 g14 aS'd' p366 asg16 I1 sg17 g14 sg18 I7 sg19 S' n = strlen(d);' p367 sg21 g22 sg23 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)' p368 sg25 g14 sg28 I62 sg29 g30 sg31 I1593 sbag1 (g2 g3 Ntp369 Rp370 (dp371 g7 g8 sg9 I1918 sg10 S'MultiByteToWideChar' p372 sg12 (lp373 g14 aS'CP_ACP' p374 aS'0' p375 aS'szName' p376 aS'-1' p377 aS'wszUserName' p378 aS'sizeof(wszUserName)/sizeof(wszUserName[0])' p379 asg16 I1 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));' p380 sg41 S'Risk is very low, the length appears to be in characters not bytes.' p381 sg21 g69 sg23 g70 sg25 g14 sg28 I68 sg29 g30 sg31 I1899 sbag1 (g2 g3 Ntp382 Rp383 (dp384 g7 g8 sg9 I2045 sg10 S'MultiByteToWideChar' p385 sg12 (lp386 g14 aS'CP_ACP' p387 aS'0' p388 aS'szName' p389 aS'-1' p390 aS'wszUserName' p391 aS'sizeof wszUserName /sizeof(wszUserName[0])' p392 asg16 I1 sg17 g14 sg18 I3 sg19 S' MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));' p393 sg41 g381 sg21 g69 sg23 g70 sg25 g14 sg28 I70 sg29 g30 sg31 I2026 sbag1 (g2 g3 Ntp394 Rp395 (dp396 g7 g132 sg9 I200 sg10 S'printf' p397 sg12 (lp398 g14 aS'"hello\\n"' p399 asg16 I0 sg17 g14 sg18 I2 sg19 S' printf("hello\\n");' p400 sg41 S'Constant format string, so not considered risky.' p401 sg21 g149 sg23 g150 sg25 g151 sg28 I9 sg29 g30 sg31 I194 sbag1 (g2 g3 Ntp402 Rp403 (dp404 g7 g8 sg9 I539 sg10 S'scanf' p405 sg12 (lp406 g14 aS'"%d"' p407 aS'&x' p408 asg16 I0 sg17 g14 sg18 I2 sg19 S' scanf("%d", &x);' p409 sg41 S'No risky scanf format detected.' p410 sg21 g160 sg23 g161 sg25 g162 sg27 I1 sg28 I24 sg29 g30 sg31 I534 sbag1 (g2 g3 Ntp411 Rp412 (dp413 g7 g132 sg9 I643 sg10 S'printf' p414 sg12 (lp415 g14 aS'"\\\\"' p416 asg16 I0 sg17 g14 sg18 I2 sg19 S' printf("\\\\");' p417 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I29 sg29 g30 sg31 I637 sbag1 (g2 g3 Ntp418 Rp419 (dp420 g7 g132 sg9 I837 sg10 S'syslog' p421 sg12 (lp422 g14 aS'LOG_ERR' p423 aS'"cannot open config file (%s): %s"' p424 aS'filename' p425 aS'strerror(errno)' p426 asg16 I0 sg17 g14 sg18 I2 sg19 S' syslog(LOG_ERR,"cannot open config file (%s): %s",filename,strerror(errno))' p427 sg41 g401 sg21 g149 sg178 I2 sg23 g179 sg25 g180 sg28 I35 sg29 g30 sg31 I831 sbag1 (g2 g3 Ntp428 Rp429 (dp430 g7 g132 sg9 I914 sg10 S'syslog' p431 sg12 (lp432 g14 aS'LOG_CRIT' p433 aS'"malloc() failed"' p434 asg16 I0 sg17 g14 sg18 I2 sg19 S' syslog(LOG_CRIT,"malloc() failed");' p435 sg41 g401 sg21 g149 sg178 I2 sg23 g179 sg25 g180 sg28 I36 sg29 g30 sg31 I908 sbag1 (g2 g3 Ntp436 Rp437 (dp438 g7 g132 sg9 I2745 sg10 S'printf' p439 sg12 (lp440 g14 aS'"%c\\n"' p441 aS"'x'" p442 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'x\');' p443 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I81 sg29 g30 sg31 I2739 sbag1 (g2 g3 Ntp444 Rp445 (dp446 g7 g132 sg9 I2768 sg10 S'printf' p447 sg12 (lp448 g14 aS'"%c\\n"' p449 aS'\'"\'' p450 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'"\');' p451 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I82 sg29 g30 sg31 I2762 sbag1 (g2 g3 Ntp452 Rp453 (dp454 g7 g132 sg9 I2791 sg10 S'printf' p455 sg12 (lp456 g14 aS'"%c\\n"' p457 aS'\'\\"\'' p458 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\"\');' p459 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I83 sg29 g30 sg31 I2785 sbag1 (g2 g3 Ntp460 Rp461 (dp462 g7 g132 sg9 I2815 sg10 S'printf' p463 sg12 (lp464 g14 aS'"%c\\n"' p465 aS"'\\''" p466 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\\'\');' p467 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I84 sg29 g30 sg31 I2809 sbag1 (g2 g3 Ntp468 Rp469 (dp470 g7 g132 sg9 I2839 sg10 S'printf' p471 sg12 (lp472 g14 aS'"%c\\n"' p473 aS"'\\177'" p474 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\177\');' p475 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I85 sg29 g30 sg31 I2833 sbag1 (g2 g3 Ntp476 Rp477 (dp478 g7 g132 sg9 I2865 sg10 S'printf' p479 sg12 (lp480 g14 aS'"%c\\n"' p481 aS"'\\xfe'" p482 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\xfe\');' p483 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I86 sg29 g30 sg31 I2859 sbag1 (g2 g3 Ntp484 Rp485 (dp486 g7 g132 sg9 I2891 sg10 S'printf' p487 sg12 (lp488 g14 aS'"%c\\n"' p489 aS"'\\xd'" p490 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\xd\');' p491 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I87 sg29 g30 sg31 I2885 sbag1 (g2 g3 Ntp492 Rp493 (dp494 g7 g132 sg9 I2916 sg10 S'printf' p495 sg12 (lp496 g14 aS'"%c\\n"' p497 aS"'\\n'" p498 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\n\');' p499 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I88 sg29 g30 sg31 I2910 sbag1 (g2 g3 Ntp500 Rp501 (dp502 g7 g132 sg9 I2940 sg10 S'printf' p503 sg12 (lp504 g14 aS'"%c\\n"' p505 aS"'\\\\'" p506 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", \'\\\\\');' p507 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I89 sg29 g30 sg31 I2934 sbag1 (g2 g3 Ntp508 Rp509 (dp510 g7 g132 sg9 I2964 sg10 S'printf' p511 sg12 (lp512 g14 aS'"%c\\n"' p513 aS'"\'"' p514 asg16 I0 sg17 g14 sg18 I3 sg19 S' printf("%c\\n", "\'");' p515 sg41 g401 sg21 g149 sg23 g150 sg25 g151 sg28 I90 sg29 g30 sg31 I2958 sbag1 (g2 g3 Ntp516 Rp517 (dp518 g7 g132 sg9 I3289 sg10 S'fprintf' p519 sg12 (lp520 g14 aS'stderr' p521 aS'"Assertion failed.\\n"\\\n "File: %s\\nLine: %d\\n"\\\n "Assertion: %s\\n\\n"' p522 aS'__FILE__' p523 aS'__LINE__' p524 aS'#x' p525 asg16 I0 sg17 g14 sg18 I2 sg19 S' fprintf(stderr,"Assertion failed.\\n"\\' p526 sg41 g401 sg21 g149 sg178 I2 sg23 g150 sg25 g151 sg28 I109 sg29 g30 sg31 I3282 sba.flawfinder-2.0.10/test.c0000644400514740010010000000677213406446435015736 0ustar dwheelerDomain Users/* 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", ""); /* 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.10/test.csv0000755400514740010010000002143413137165472016302 0ustar dwheelerDomain UsersFile,Line,Column,Level,Category,Name,Warning,Suggestion,Note,CWEs,Context test.c,32,2,5,buffer,gets,"Does not check for buffer overflows (CWE-120, CWE-20)",Use fgets() instead,,"CWE-120, CWE-20", gets(f); test.c,56,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.",CWE-120," strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */" test.c,57,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.",CWE-120," _tcsncat(d,s,sizeof(d)); /* Misuse - flag as riskier */" test.c,60,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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName));" test.c,62,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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName);" test.c,73,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)",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);" test.c,73,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)",,,CWE-732," SetSecurityDescriptorDacl(&sd,TRUE,NULL,FALSE);" 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)",,CWE-120," strcpy(b, a);" test.c,20,2,4,buffer,sprintf,Does not check for buffer overflows (CWE-120),"Use sprintf_s, snprintf, or vsnprintf",,CWE-120," sprintf(s, ""hello %s"", bug);" test.c,21,2,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);" test.c,22,2,4,format,sprintf,Potential format string problem (CWE-134),Make format string constant,,CWE-134," sprintf(s, unknown, bug);" 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,,CWE-134," printf(bf, x);" 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",,"CWE-120, CWE-20"," scanf(""%s"", s);" 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",,"CWE-120, CWE-20"," scanf(""%s"", s);" 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,,CWE-134," syslog(LOG_ERR, attacker_string);" 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,,CWE-120," _mbscpy(d,s); /* like strcpy, this doesn't check for buffer overflow */" test.c,52,3,4,buffer,lstrcat,Does not check for buffer overflows when concatenating to destination [MS-banned] (CWE-120),,,CWE-120," lstrcat(d,s);" test.c,75,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"", """");" test.c,75,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"", """");" test.c,91,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",,"CWE-120, CWE-20"," while ((optc = getopt_long (argc, argv, ""a"",longopts, NULL )) != EOF) {" 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.,CWE-120," strcpy(a, gettext(""Hello there"")); // Did this work?" 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.,CWE-120," sprintf(s, ""hello"");" 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",,CWE-119!/CWE-120, char d[20]; 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",,CWE-119!/CWE-120, char s[20]; 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,,CWE-120," memcpy(d,s);" test.c,51,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,,CWE-120," CopyMemory(d,s);" test.c,97,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)",,,CWE-362," f = fopen(""/etc/passwd"", ""r""); " 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.,CWE-120," strcpy(a, ""\n""); // Did this work?" 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.,CWE-120," sprintf(s, ""\n"");" 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",,CWE-120," scanf(""%10s"", s);" test.c,53,3,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);" test.c,54,3,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);" test.c,55,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",,CWE-120," strncat(d,s,10);" test.c,58,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),,,CWE-126, n = strlen(d); test.c,64,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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof(wszUserName)/sizeof(wszUserName[0]));" test.c,66,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.",CWE-120," MultiByteToWideChar(CP_ACP,0,szName,-1,wszUserName,sizeof wszUserName /sizeof(wszUserName[0]));" flawfinder-2.0.10/test.patch0000755400514740010010000000037113147433074016600 0ustar dwheelerDomain Usersdiff --git a/test.c b/test.c index 97579c0..9ee11a1 100644 --- a/test.c +++ b/test.c @@ -9,6 +9,10 @@ main() { 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.10/test2.c0000644400514740010010000000005413406345645016004 0ustar dwheelerDomain Users/* Here's a file with no contents to try */