flawfinder-1.31/0000755003056700244210000000000012367534671014457 5ustar dwheelerDomain Usersflawfinder-1.31/announcement0000644003056700244210000000252412206405744017065 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-1.31/ChangeLog0000644003056700244210000007053712367534036016240 0ustar dwheelerDomain Users2014-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-1.31/COPYING0000644003056700244210000004312712206405744015507 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-1.31/correct-results.html0000644003056700244210000003314212365573667020516 0ustar dwheelerDomain Users Flawfinder Results

Flawfinder Results

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

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:56: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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.
      strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */
    
  • test.c:57: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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:60: [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:62: [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:73: [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:73: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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 (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:52: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination (CWE-120).
      lstrcat(d,s);
    
  • test.c:75: [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:75: [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:91: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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);
    
  • test.c:51: [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:97: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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:53: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120).
      strncpy(d,s);
    
  • test.c:54: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120).
      _tcsncpy(d,s);
    
  • test.c:55: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings.
      strncat(d,s,10);
    
  • test.c:58: [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:64: [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:66: [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 = 36
Lines analyzed = 118
Physical Source Lines of Code (SLOC) = 80
Hits@level = [0] 0 [1] 9 [2] 7 [3] 3 [4] 10 [5] 7
Hits@level+ = [0+] 36 [1+] 36 [2+] 27 [3+] 20 [4+] 17 [5+] 7
Hits/KSLOC@level+ = [0+] 450 [1+] 450 [2+] 337.5 [3+] 250 [4+] 212.5 [5+] 87.5
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 for Linux and Unix HOWTO' (http://www.dwheeler.com/secure-programs) for more information. flawfinder-1.31/correct-results.txt0000644003056700244210000001755312365573666020400 0ustar dwheelerDomain UsersFlawfinder version 1.31, (C) 2001-2014 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 169 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:56: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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:57: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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:60: [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:62: [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:73: [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:73: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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 (CWE-120). Consider using a function version that stops copying at the end of the buffer. test.c:52: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination (CWE-120). test.c:75: [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:75: [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:91: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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:51: [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:97: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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:53: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120). test.c:54: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120). test.c:55: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. test.c:58: [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:64: [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:66: [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 = 36 Lines analyzed = 118 Physical Source Lines of Code (SLOC) = 80 Hits@level = [0] 0 [1] 9 [2] 7 [3] 3 [4] 10 [5] 7 Hits@level+ = [0+] 36 [1+] 36 [2+] 27 [3+] 20 [4+] 17 [5+] 7 Hits/KSLOC@level+ = [0+] 450 [1+] 450 [2+] 337.5 [3+] 250 [4+] 212.5 [5+] 87.5 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 for Linux and Unix HOWTO' (http://www.dwheeler.com/secure-programs) for more information. Testing for no ending newline: Lines analyzed = 32 flawfinder-1.31/cwe.l0000644003056700244210000000054512360506306015401 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-1.31/flawfinder0000755003056700244210000023566312367506515016541 0ustar dwheelerDomain Users#!/usr/bin/env python from __future__ import division """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.""" version="1.31" # 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-2014 David A. Wheeler. # This is released under the # GNU General Public License (GPL) version 2 or later (GPLv2+): # # 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 # The Python developers did a *terrible* job when they transitioned # to Python version 3, as I have documented elsewhere. What's more, # many mechanisms that do exist do not come natively with Python 2, or # require version 2.6 or later (yet older versions are still in use). # For example, this requires Python version 2.6: # from __future__ import print_function # As a result, many Python programs (including this one) do not use Python 3. # The solution used here is to gradually transition the Python code # to Python 2 code that works across 2.2 through 2.7. A preference is # given to code constructs that would ALSO work in version 3.X, but # only if they would *already* work in Python 2, and only if they don't # make the code too complicated. # The plan is to eventually switch this code so that it runs unchanged # on both 2.X and 3.X, but that is hard to support if the version number # is less than 2.6, so we won't do that at this time. Instead, we'll # wait until versions lower than 2.6 are a distant memory, and then # start in that direction. Hopefully by then the developers of Python # will begin to make it easy to transition to newer versions of Python. import sys, re, string, getopt import pickle # To support load/save/diff of hitlist import os, glob, operator # To support filename expansion on Windows import os.path import time # import formatter # Program Options - these are the default values: 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 = 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) 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 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. line_beginning = re.compile( r'(?m)^' ) blank_line = re.compile( r'(?m)^\s+$' ) # 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.*)((\s\d\d\d\d+-\d\d-\d\d\s+\d\d:\d[0-9:.]+Z?(\s+[\-\+0-9A-Z]+)?)|(\s[A-Za-z][a-z]+\s[A-za-z][a-z]+\s\d+\s\d+:\d[0-9:.]+Z?(\s[\-\+0-9]*)?\s\d\d\d\d+)|(\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 = string.strip(newfile_match.group('filename')) # Clean up filename - remove trailing timestamp and/or (comment). return diff_findjunk.match(patched_filename) return None git_splitter=' b/' len_git_splitter=len(git_splitter) def git_diff_get_filename(sLine): return diff_git_filename.match(sLine) # For each file found in the file 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(patch_file): patch={} line_counter= 0 initial_number= 0 index_statement = False # Set true if we see "Index:". try: hPatch = open(patch_file, 'r') except: print "Error: failed to open", h(patch_file) sys.exit(1) 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(1) 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 = string.strip(filename_match.group('filename')) if (patched_file in patch): error("filename occurs more than once in the patch: %s" % patched_filename) sys.exit(1) 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(1) 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 == 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. s1 = string.replace(s,"&","&") s2 = string.replace(s1,"<","<") s3 = string.replace(s2,">",">") return s3 def h(s): # htmlize s if we're generating html, otherwise just return s. if output_format: return htmlize(s) else: return s def print_multi_line(text): # Print text as multiple indented lines. width = 78 prefix = " " starting_position = len(prefix) + 1 # print prefix, position = starting_position # for w in text.split(): if len(w) + position >= width: print print prefix, position = starting_position print w, position = position + len(w) + 1 # This matches references to CWE identifiers, so we can HTMLize them. # We don't refer to CWEs with one digit, so we'll only match on 2+ digits. link_cwe_pattern = re.compile(r'(CWE-([1-9][0-9]+))([,()])') class Hit: """ 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.keys(): setattr(self, key, other[key]) def __cmp__(self, other): return (cmp(other.level, self.level) or # Highest risk first. cmp(self.filename, other.filename) or cmp(self.line, other.line) or cmp(self.column, other.column) or cmp(self.name, other.name)) def __getitem__(self, X): # Define this so this works: "%(line)" % hit return getattr(self, X) def show(self): if output_format: print "

  • ", sys.stdout.write(h(self.filename)) if show_columns: print ":%(line)s:%(column)s:" % self, else: print ":%(line)s:" % self, if output_format: print "", # Extra space before risk level in text, makes it easier to find: print " [%(level)s]" % self, if output_format: print "", print "(%(category)s)" % self, if output_format: print "", print h("%(name)s:" % self), 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, if self.suggestion: print h(self.suggestion)+".", print h(self.note), else: if self.suggestion: main_text = main_text + h(self.suggestion) + ". " main_text = main_text + h(self.note) print print_multi_line(main_text) if output_format: print "", 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 hit.level >= minimum_level: if linenumber == ignoreline: num_ignored_hits = 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 = i + 1 else: return [] else: # Never found a reasonable ending. return [] i = 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 = i + 1 elif incomment: if c == '*' and text[i:i+2]=='*/': incomment = 0 i = i + 1 else: if c == '"': instring = 1 elif c == "'": instring = 2 elif c == '/' and text[i:i+2]=='/*': incomment = 1 i = i + 1 elif c == '/' and text[i:i+2]=='//': while i < len(text) and text[i] != "\n": i = i + 1 elif c == '\\' and text[i:i+2]=='\\"': i = i + 1 # Handle exposed '\"' elif c == '(': parenlevel = parenlevel + 1 elif c == ',' and (parenlevel == 1): parameters.append(string.strip( p_trailingbackslashes.sub('', text[currentstart:i]))) currentstart = i + 1 elif c == ')': parenlevel = parenlevel - 1 if parenlevel <= 0: parameters.append(string.strip( p_trailingbackslashes.sub('', text[currentstart:i]))) # 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 = i + 1 internal_warn("Parsing failed to find end of parameter list in %s" % text[pos:pos+200]) # 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', " "such as gettext() and _()." match = gettext_pattern.search(text) if match: return string.strip(match.group(1)) match = undersc_pattern.search(text) if match: return string.strip(match.group(3)) 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." if p_c_singleton_string.search(text): return 1 else: return 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." if p_c_constant_string.search(text): return 1 else: return 0 # Precompile patterns for speed. 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. if hit.name == "snprintf" or hit.name == "vsnprintf": hit.level = 1 hit.warning = \ "On some very old systems, snprintf is incorrectly implemented " \ "and permits buffer overflows; there are also incompatible " \ "standard definitions of it" hit.suggestion = "Check it during installation, or use something else" hit.category = "port" else: # 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 very risky (there's some residual risk, especially in a loop)." 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*' + r'\[\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 normal(hit): add_warning(hit) # "c_ruleset": the rules for identifying "hits" in C (potential warnings). # It's a dictionary, where the key is the function name causing the hit, # and the value is a tuple with the following format: # (hook, level, warning, suggestion, category, {other}) # See the definition for class "Hit". # The key can have multiple values separated with "|". c_ruleset = { "strcpy" : (c_buffer, 4, "Does not check for buffer overflows when copying to destination (CWE-120)", "Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is easily misused)", "buffer", "", {}), "lstrcpy|wcscpy|_tcscpy|_mbscpy" : (c_buffer, 4, "Does not check for buffer overflows when copying to destination (CWE-120)", "Consider using a function version that stops copying at the end of the buffer", "buffer", "", {}), "memcpy|CopyMemory|bcopy" : (normal, 2, # I've found this to have a lower risk in practice. "Does not check for buffer overflows when copying to destination (CWE-120)", "Make sure destination can always hold the source data", "buffer", "", {}), "strcat" : (c_buffer, 4, "Does not check for buffer overflows when concatenating to destination (CWE-120)", "Consider using strcat_s, strncat, or strlcat (warning, strncat is easily misused)", "buffer", "", {}), "lstrcat|wcscat|_tcscat|_mbscat" : (c_buffer, 4, "Does not check for buffer overflows when concatenating to destination (CWE-120)", "", "buffer", "", {}), "strncpy" : (c_buffer, 1, # Low risk level, because this is often used correctly when FIXING security # problems, and raising it to a higher risk level would cause many false positives. "Easily used incorrectly; doesn't always \\0-terminate or " + "check for invalid pointers (CWE-120)", "", "buffer", "", {}), "lstrcpyn|wcsncpy|_tcsncpy|_mbsnbcpy" : (c_buffer, 1, # Low risk level, because this is often used correctly when FIXING security # problems, and raising it to a higher risk levle would cause many false positives. "Easily used incorrectly; doesn't always \\0-terminate or " + "check for invalid pointers (CWE-120)", "", "buffer", "", {}), "strncat" : (c_strncat, 1, # Low risk level, because this is often used correctly when # FIXING security problems, and raising it to a # higher risk level would cause many false positives. "Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (CWE-120)", "Consider strcat_s, strlcat, or automatically resizing strings", "buffer", "", {}), "lstrcatn|wcsncat|_tcsncat|_mbsnbcat" : (c_strncat, 1, # Low risk level, because this is often used correctly when FIXING security # problems, and raising it to a higher risk level would cause many false positives. "Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (CWE-120)", "Consider strcat_s, strlcat, or automatically resizing strings", "buffer", "", {}), "strccpy|strcadd": (normal, 1, "Subject to buffer overflow if buffer is not as big as claimed (CWE-120)", "Ensure that destination buffer is sufficiently large", "buffer", "", {}), "char|TCHAR|wchar_t": # This isn't really a function call, but it works. (c_static_array, 2, "Statically-sized arrays can be improperly restricted, " + "leading to potential overflows or other issues (CWE-119:CWE-120)", "Perform bounds checking, use functions that limit length, " + "or ensure that the size is larger than the maximum possible length", "buffer", "", {'extract_lookahead' : 1}), "gets|_getts": (normal, 5, "Does not check for buffer overflows (CWE-120, CWE-20)", "Use fgets() instead", "buffer", "", {'input' : 1}), # The "sprintf" hook will raise "format" issues instead if appropriate: "sprintf|vsprintf|swprintf|vswprintf|_stprintf|_vstprintf": (c_sprintf, 4, "Does not check for buffer overflows (CWE-120)", "Use sprintf_s, snprintf, or vsnprintf", "buffer", "", {}), "printf|vprintf|vwprintf|vfwprintf|_vtprintf|wprintf": (c_printf, 4, "If format strings can be influenced by an attacker, they can be exploited (CWE-134)", "Use a constant for the format specification", "format", "", {}), "fprintf|vfprintf|_ftprintf|_vftprintf|fwprintf|fvwprintf": (c_printf, 4, "If format strings can be influenced by an attacker, they can be exploited (CWE-134)", "Use a constant for the format specification", "format", "", { 'format_position' : 2}), # The "syslog" hook will raise "format" issues. "syslog": (c_printf, 4, "If syslog's format strings can be influenced by an attacker, " + "they can be exploited (CWE-134)", "Use a constant format string for syslog", "format", "", { 'format_position' : 2} ), "snprintf|vsnprintf|_snprintf|_sntprintf|_vsntprintf": (c_printf, 4, "If format strings can be influenced by an attacker, they can be " + "exploited, and note that sprintf variations do not always \\0-terminate (CWE-134)", "Use a constant for the format specification", "format", "", { 'format_position' : 3}), "scanf|vscanf|wscanf|_tscanf|vwscanf": (c_scanf, 4, "The scanf() family's %s operation, without a limit specification, " + "permits buffer overflows (CWE-120, CWE-20)", "Specify a limit to %s, or use a different input function", "buffer", "", {'input' : 1}), "fscanf|sscanf|vsscanf|vfscanf|_ftscanf|fwscanf|vfwscanf|vswscanf": (c_scanf, 4, "The scanf() family's %s operation, without a limit specification, " "permits buffer overflows (CWE-120, CWE-20)", "Specify a limit to %s, or use a different input function", "buffer", "", {'input' : 1, 'format_position' : 2}), "strlen|wcslen|_tcslen|_mbslen" : (normal, 1, # Often this isn't really a risk, and even when, it usually at worst causes # program crash (and nothing worse). "Does not handle strings that are not \\0-terminated; " + "if given one it may perform an over-read (it could cause a crash " + "if unprotected) (CWE-126)", "", "buffer", "", {}), "MultiByteToWideChar" : # Windows (c_multi_byte_to_wide_char, 2, # Only the default - this will be changed in many cases. "Requires maximum length in CHARACTERS, not bytes (CWE-120)", "", "buffer", "", {}), "streadd|strecpy": (normal, 4, "This function does not protect against buffer overflows (CWE-120)", "Ensure the destination has 4 times the size of the source, to leave room for expansion", "buffer", "dangers-c", {}), "strtrns": (normal, 3, "This function does not protect against buffer overflows (CWE-120)", "Ensure that destination is at least as long as the source", "buffer", "dangers-c", {}), "realpath": (normal, 3, "This function does not protect against buffer overflows, " + "and some implementations can overflow internally (CWE-120/CWE-785)", "Ensure that the destination buffer is at least of size MAXPATHLEN, and" + "to protect against implementation problems, the input argument should also " + "be checked to ensure it is no larger than MAXPATHLEN", "buffer", "dangers-c", {}), "getopt|getopt_long": (normal, 3, "Some older implementations do not protect against internal buffer overflows (CWE-120, CWE-20)", "Check implementation on installation, or limit the size of all string inputs", "buffer", "dangers-c", {'input' : 1}), "getpass": (normal, 3, "Some implementations may overflow buffers (CWE-120, CWE-20)", "", "buffer", "dangers-c", {'input' : 1}), "getwd": (normal, 3, "This does not protect against buffer overflows " "by itself, so use with caution (CWE-120, CWE-20)", "Use getcwd instead", "buffer", "dangers-c", {'input' : 1}), # fread not included here; in practice I think it's rare to mistake it. "getchar|fgetc|getc|read|_gettc": (normal, 1, "Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20)", "", "buffer", "dangers-c", {'input' : 1}), "access": # ???: TODO: analyze TOCTOU more carefully. (normal, 4, "This usually indicates a security flaw. If an " + "attacker can change anything along the path between the " + "call to access() and the file's actual use (e.g., by moving " + "files), the attacker can exploit the race condition (CWE-362/CWE-367)", "Set up the correct permissions (e.g., using setuid()) and " + "try to open the file directly", "race", "avoid-race#atomic-filesystem", {}), "chown": (normal, 5, "This accepts filename arguments; if an attacker " + "can move those files, a race condition results. (CWE-362)", "Use fchown( ) instead", "race", "", {}), "chgrp": (normal, 5, "This accepts filename arguments; if an attacker " + "can move those files, a race condition results. (CWE-362)", "Use fchgrp( ) instead", "race", "", {}), "chmod": (normal, 5, "This accepts filename arguments; if an attacker " + "can move those files, a race condition results. (CWE-362)", "Use fchmod( ) instead", "race", "", {}), "vfork": (normal, 2, "On some old systems, vfork() permits race conditions, and it's " + "very difficult to use correctly (CWE-362)", "Use fork() instead", "race", "", {}), "readlink": (normal, 5, "This accepts filename arguments; if an attacker " + "can move those files or change the link content, " + "a race condition results. " + "Also, it does not terminate with ASCII NUL. (CWE-362, CWE-20)", # This is often just a bad idea, and it's hard to suggest a # simple alternative: "Reconsider approach", "race", "", {'input' : 1}), "tmpfile": (normal, 2, "Function tmpfile() has a security flaw on some systems (e.g., older System V systems) (CWE-377)", "", "tmpfile", "", {}), "tmpnam|tempnam": (normal, 3, "Temporary file race condition (CWE-377)", "", "tmpfile", "avoid-race", {}), # TODO: Detect GNOME approach to mktemp and ignore it. "mktemp": (normal, 4, "Temporary file race condition (CWE-377)", "", "tmpfile", "avoid-race", {}), "mkstemp": (normal, 2, "Potential for temporary file vulnerability in some circumstances. Some older Unix-like systems create temp files with permission to write by all by default, so be sure to set the umask to override this. Also, some older Unix systems might fail to use O_EXCL when opening the file, so make sure that O_EXCL is used by the library (CWE-377)", "", "tmpfile", "avoid-race", {}), "fopen|open": (normal, 2, "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)", "", "misc", "", {}), "umask": (normal, 1, "Ensure that umask is given most restrictive possible setting (e.g., 066 or 077) (CWE-732)", "", "access", "", {}), # Windows. TODO: Detect correct usage approaches and ignore it. "GetTempFileName": (normal, 3, "Temporary file race condition in certain cases " + "(e.g., if run as SYSTEM in many versions of Windows) (CWE-377)", "", "tmpfile", "avoid-race", {}), # TODO: Need to detect varying levels of danger. "execl|execlp|execle|execv|execvp|system|popen|WinExec|ShellExecute": (normal, 4, "This causes a new program to execute and is difficult to use safely (CWE-78)", "try using a library call that implements the same functionality " + "if available", "shell", "", {}), # TODO: Need to detect varying levels of danger. "execl|execlp|execle|execv|execvp|system|popen|WinExec|ShellExecute": (normal, 4, "This causes a new program to execute and is difficult to use safely (CWE-78)", "try using a library call that implements the same functionality " + "if available", "shell", "", {}), # TODO: Be more specific. The biggest problem involves "first" param NULL, # second param with embedded space. Windows. "CreateProcessAsUser|CreateProcessWithLogon": (normal, 3, "This causes a new process to execute and is difficult to use safely (CWE-78)", "Especially watch out for embedded spaces", "shell", "", {}), # TODO: Be more specific. The biggest problem involves "first" param NULL, # second param with embedded space. Windows. "CreateProcess": (c_hit_if_null, 3, "This causes a new process to execute and is difficult to use safely (CWE-78)", "Specify the application path in the first argument, NOT as part of the second, " + "or embedded spaces could allow an attacker to force a different program to run", "shell", "", {'check_for_null' : 1}), "atoi|atol|_wtoi|_wtoi64": (normal, 2, "Unless checked, the resulting number can exceed the expected range " + "(CWE-190)", "If source untrusted, check both minimum and maximum, even if the" + " input had no minus sign (large numbers can roll over into negative" + " number; consider saving to an unsigned value if that is intended)", "integer", "dangers-c", {}), # Random values. Don't trigger on "initstate", it's too common a term. "drand48|erand48|jrand48|lcong48|lrand48|mrand48|nrand48|random|seed48|setstate|srand|strfry|srandom": (normal, 3, "This function is not sufficiently random for security-related functions such as key and nonce creation (CWE-327)", "use a more secure technique for acquiring random values", "random", "", {}), "crypt": (normal, 4, "Function crypt is a poor one-way hashing algorithm; since it only accepts passwords of 8 " + "characters or less, and only a two-byte salt, it is excessively vulnerable to " + "dictionary attacks given today's faster computing equipment (CWE-327)", "Use a different algorithm, such as SHA-1, with a larger non-repeating salt", "crypto", "", {}), # OpenSSL EVP calls to use DES. "EVP_des_ecb|EVP_des_cbc|EVP_des_cfb|EVP_des_ofb|EVP_desx_cbc": (normal, 4, "DES only supports a 56-bit keysize, which is too small given today's computers (CWE-327)", "Use a different patent-free encryption algorithm with a larger keysize, " + "such as 3DES or AES", "crypto", "", {}), # Other OpenSSL EVP calls to use small keys. "EVP_rc4_40|EVP_rc2_40_cbc|EVP_rc2_64_cbc": (normal, 4, "These keysizes are too small given today's computers (CWE-327)", "Use a different patent-free encryption algorithm with a larger keysize, " + "such as 3DES or AES", "crypto", "", {}), "chroot": (normal, 3, "chroot can be very helpful, but is hard to use correctly (CWE-250, CWE-22)", "Make sure the program immediately chdir(\"/\")," + " closes file descriptors," + " and drops root privileges, and that all necessary files" + " (and no more!) are in the new root", "misc", "", {}), "getenv|curl_getenv": (normal, 3, "Environment variables are untrustable input if they can be" + " set by an attacker. They can have any content and" + " length, and the same variable can be set more than once (CWE-807, CWE-20)", "Check environment variables carefully before using them", "buffer", "", {'input' : 1}), "g_get_home_dir": (normal, 3, "This function is synonymous with 'getenv(\"HOME\")';" + "it returns untrustable input if the environment can be" + "set by an attacker. It can have any content and length, " + "and the same variable can be set more than once (CWE-807, CWE-20)", "Check environment variables carefully before using them", "buffer", "", {'input' : 1}), "g_get_tmp_dir": (normal, 3, "This function is synonymous with 'getenv(\"TMP\")';" + "it returns untrustable input if the environment can be" + "set by an attacker. It can have any content and length, " + "and the same variable can be set more than once (CWE-807, CWE-20)", "Check environment variables carefully before using them", "buffer", "", {'input' : 1}), # These are Windows-unique: # TODO: Should have lower risk if the program checks return value. "RpcImpersonateClient|ImpersonateLoggedOnUser|CoImpersonateClient|" + "ImpersonateNamedPipeClient|ImpersonateDdeClientWindow|ImpersonateSecurityContext|" + "SetThreadToken": (normal, 4, "If this call fails, the program could fail to drop heightened privileges (CWE-250)", "Make sure the return value is checked, and do not continue if a failure is reported", "access", "", {}), "InitializeCriticalSection": (normal, 3, "Exceptions can be thrown in low-memory situations", "Use InitializeCriticalSectionAndSpinCount instead", "misc", "", {}), "EnterCriticalSection": (normal, 3, "On some versions of Windows, exceptions can be thrown in low-memory situations", "Use InitializeCriticalSectionAndSpinCount instead", "misc", "", {}), "LoadLibrary|LoadLibraryEx": (normal, 3, "Ensure that the full path to the library is specified, or current directory may be used (CWE-829, CWE-20)", "Use registry entry or GetWindowsDirectory to find library path, if you aren't already", "misc", "", {'input' : 1}), "SetSecurityDescriptorDacl": (c_hit_if_null, 5, "Never create NULL ACLs; an attacker can set it to Everyone (Deny All Access), " + "which would even forbid administrator access (CWE-732)", "", "misc", "", {'check_for_null' : 3}), "AddAccessAllowedAce": (normal, 3, "This doesn't set the inheritance bits in the access control entry (ACE) header (CWE-732)", "Make sure that you set inheritance by hand if you wish it to inherit", "misc", "", {}), "getlogin": (normal, 4, "It's often easy to fool getlogin. Sometimes it does not work at all, because some program messed up the utmp file. Often, it gives only the first 8 characters of the login name. The user currently logged in on the controlling tty of our program need not be the user who started it. Avoid getlogin() for security-related purposes (CWE-807)", "Use getpwuid(geteuid()) and extract the desired information instead", "misc", "", {}), "cuserid": (normal, 4, "Exactly what cuserid() does is poorly defined (e.g., some systems use the effective uid, like Linux, while others like System V use the real uid). Thus, you can't trust what it does. It's certainly not portable (The cuserid function was included in the 1988 version of POSIX, but removed from the 1990 version). Also, if passed a non-null parameter, there's a risk of a buffer overflow if the passed-in buffer is not at least L_cuserid characters long (CWE-120)", "Use getpwuid(geteuid()) and extract the desired information instead", "misc", "", {}), "getpw": (normal, 4, "This function is dangerous; it may overflow the provided buffer. It extracts data from a 'protected' area, but most systems have many commands to let users modify the protected area, and it's not always clear what their limits are. Best to avoid using this function altogether (CWE-676, CWE-120)", "Use getpwuid() instead", "buffer", "", {}), "getpass": (normal, 4, "This function is obsolete and not portable. It was in SUSv2 but removed by POSIX.2. What it does exactly varies considerably between systems, particularly in where its prompt is displayed and where it gets its data (e.g., /dev/tty, stdin, stderr, etc.) (CWE-676)", "Make the specific calls to do exactly what you want. If you continue to use it, or write your own, be sure to zero the password as soon as possible to avoid leaving the cleartext password visible in the process' address space", "misc", "", {}), "gsignal|ssignal": (normal, 2, "These functions are considered obsolete on most systems, and very non-poertable (Linux-based systems handle them radically different, basically if gsignal/ssignal were the same as raise/signal respectively, while System V considers them a separate set and obsolete) (CWE-676)", "Switch to raise/signal, or some other signalling approach", "obsolete", "", {}), "memalign": (normal, 1, "On some systems (though not Linux-based systems) an attempt to free() results from memalign() may fail. This may, on a few systems, be exploitable. Also note that memalign() may not check that the boundary parameter is correct (CWE-676)", "Use posix_memalign instead (defined in POSIX's 1003.1d). Don't switch to valloc(); it is marked as obsolete in BSD 4.3, as legacy in SUSv2, and is no longer defined in SUSv3. In some cases, malloc()'s alignment may be sufficient", "free", "", {}), "ulimit": (normal, 1, "This C routine is considered obsolete (as opposed to the shell command by the same name, which is NOT obsolete) (CWE-676)", "Use getrlimit(2), setrlimit(2), and sysconf(3) instead", "obsolete", "", {}), "usleep": (normal, 1, "This C routine is considered obsolete (as opposed to the shell command by the same name). The interaction of this function with SIGALRM and other timer functions such as sleep(), alarm(), setitimer(), and nanosleep() is unspecified (CWE-676)", "Use nanosleep(2) or setitimer(2) instead", "obsolete", "", {}), # Input functions, useful for -I "recv|recvfrom|recvmsg|fread|readv": (normal, 0, "Function accepts input from outside program (CWE-20)", "Make sure input data is filtered, especially if an attacker could manipulate it", "input", "", {'input' : 1}), # TODO: detect C++'s: cin >> charbuf, where charbuf is a char array; the problem # is that flawfinder doesn't have type information, and ">>" is safe with # many other types. # ("send" and friends aren't todo, because they send out.. not input.) # TODO: cwd("..") in user's space - TOCTOU vulnerability # TODO: There are many more rules to add, esp. for TOCTOU. } template_ruleset = { # This is a template for adding new entries (the key is impossible): "9": (normal, 2, "", "", "tmpfile", "", {}), } def find_column(text, position): "Find column number inside line." newline = string.rfind(text, "\n", 0, position) if newline == -1: return position + 1 else: return position - newline def get_context(text, position): "Get surrounding text line starting from text[position]" linestart = string.rfind(text, "\n", 0, position+1) + 1 lineend = string.find(text, "\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 = 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 for i in xrange(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 = 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 != None) and (not (f 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 == "-": 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 = num_links_skipped + 1 return try: input = open(f, "r") except: print "Error: failed to open", h(f) sys.exit(1) # 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 = string.join(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 = linenumber + 1 sumlines = sumlines + 1 linebegin = 1 if codeinline: sloc = sloc + 1 codeinline = 0 i = i +1 continue i = 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 = i + 1 incomment = 0 elif instring: if c == '\\' and (nextc != "\n"): i = 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 = 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" 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 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-2014 David A. Wheeler.' else: print "Flawfinder version %s, (C) 2001-2014 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 = 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 = num_dotdirs_skipped + 1 return for file in os.listdir(f): maybe_process_file(os.path.join(f, file), 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 = string.rfind(f, ".") 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 = 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 == None) or (patch_infos != 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 = 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 != None and k in patch_infos) or (patch_infos == 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: if h(f).startswith("\342\210\222"): print_warning("Skipping non-existent filename starting with UTF-8 long 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. 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 required_regex, required_regex_compiled global falsepositive global show_columns, never_ignore, quiet, showheading, list_rules global loadhitlist, savehitlist, diffhitlist 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", "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 = string.atoi(value) elif opt == "--singleline" or opt == "-S": single_line = 1 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 = 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:] = reduce(operator.add, 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, text: print "*** getopt error:", text usage() sys.exit(1) def process_files(): global hitlist if loadhitlist: f = open(loadhitlist) hitlist = pickle.load(f) 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 1 def show_final_results(): global hitlist count = 0 count_per_level = {} count_per_level_and_up = {} for i in range(0,6): # Initialize count_per_level count_per_level[i] = 0 for i in range(0,6): # Initialize count_per_level count_per_level_and_up[i] = 0 if show_immediately or not quiet: # Separate the final results. print if showheading: if output_format: print "

    Final Results

    " else: print "FINAL RESULTS:" print hitlist.sort() # 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: diff_file = open(diffhitlist) diff_hitlist = pickle.load(diff_file) if output_format: print "
          " for h in hitlist: if h not in diff_hitlist: h.show() count_per_level[h.level] = count_per_level[h.level] + 1 count = count + 1 if output_format: print "
        " diff_file.close() else: if output_format: print "
          " for h in hitlist: h.show() count_per_level[h.level] = count_per_level[h.level] + 1 if output_format: print "
        " count = len(hitlist) # 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, 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 =", for i in range(0,6): print "[%d] %3d" % (i, count_per_level[i]), if output_format: print "
        " else: print # Compute hits at "level x or higher" print "Hits@level+ =", for i in range(0,6): for j in range(i,6): count_per_level_and_up[i] = count_per_level_and_up[i] + count_per_level[j] # Display hits at "level x or higher" for i in range(0,6): print "[%d+] %3d" % (i, count_per_level_and_up[i]), if output_format: print "
        " else: print if (sloc > 0): print "Hits/KSLOC@level+ =", for i in range(0,6): print "[%d+] %3g" % (i, count_per_level_and_up[i]*1000.0/sloc), 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 for Linux and Unix HOWTO'" print "(http://www.dwheeler.com/secure-programs) for more information." else: print "See 'Secure Programming for Linux and Unix HOWTO'" print "(http://www.dwheeler.com/secure-programs) for more information." if output_format: print "" print "" def save_if_desired(): # We'll save entire hitlist, even if only differences displayed. if savehitlist: print "Saving hitlist to", savehitlist f = open(savehitlist, "w") pickle.dump(hitlist, f) f.close() def flawfind(): process_options() display_header() initialize_ruleset() if process_files(): show_final_results() save_if_desired() if __name__ == '__main__': try: flawfind() except KeyboardInterrupt: print "*** Flawfinder interrupted" flawfinder-1.31/flawfinder.10000644003056700244210000013214412367502042016652 0ustar dwheelerDomain Users'\" .\" (C) Copyright 2001-2014 David A. Wheeler (dwheeler@dwheeler.com) .\" .\" This program is free software; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by .\" the Free Software Foundation; either version 2 of the License, or .\" (at your option) any later version. .\" .\" This program is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public License .\" along with this program; if not, write to the Free Software .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA .\" .\" .\" .\" Man page created 17 May 2001 by David A. Wheeler (dwheeler@dwheeler.com) .\" .TH FLAWFINDER 1 "3 Aug 2014" "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 [ \-\-dataonly | \-D ] .RB [ \-\-html | \-H ] .RB [ \-\-immediate | -i ] .RB [ \-\-singleline | \-S ] .RB [ \-\-omittime ] .RB [ \-\-quiet | \-Q ] .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. 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), 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 most 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. .PP Not every hit 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", ".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 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. .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 "http://www.dwheeler.com/secure-programs" .I "Writing Secure Programs for Linux and Unix HOWTO" .UE at http://www.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. Flawfinder supports the standard syntax defined in the POSIX (Issue 7, 2013 Edition) section ``Utility Conventions''. It 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''. Some options can only be accessed using the more readable GNU long option conventions; common options are also supported by the older single-letter option convention. .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/), configurations, 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 by 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. .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 "\-\-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. .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). .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. .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 \-QD mydir" Examine mydir and report only the actual results (removing the header and footer of the output). This form is useful if the output will be piped into other tools for further analysis. 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'' (http://cwe.mitre.org/about/faq.html). For more information on CWEs, see http://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 Many of the CWEs reported by flawfinder are identified in the CWE/SANS top 25 list 2011 (http://cwe.mitre.org/top25/). Many people will want to search for CWEs in this list, such as CWE-120 (classic buffer overflow), When flawfinder maps to a CWE that is more general than a top 25 item, it lists it as more-general:more-specific (e.g., CWE-119:CWE-120), where more-general is the actual mapping. If flawfinder maps to a more specific CWE item that is a specific case of a top 25 item, it is listed in the form top-25/more-specific (e.g., CWE-362/CWE-367), where the real mapping is the more specific CWE entry. If the same entry maps to multiple CWEs, the CWEs are separated by commas (this often occurs with CWE-20, Improper Input Validation). This simplifies 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 http://www.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 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 apporach 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 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 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 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'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 (failure to report on a security vulnerability). 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 http://www.dwheeler.com/flawfinder. You should also see the .I "Secure Programming for Unix and Linux HOWTO" at .IR "http://www.dwheeler.com/secure-programs" . .SH AUTHOR David A. Wheeler (dwheeler@dwheeler.com). flawfinder-1.31/flawfinder.1.gz0000644003056700244210000004046612367514521017303 0ustar dwheelerDomain Users‹"„ÞS­}ûsÛH’æïõWÔq÷Bd7Eù1=½mÅέ,ËkÝÚ–V”ÏÝ1žXA$(bL”¬‰‰ûÛ/¿|T@ª§ow#:Ú" Ô3+óËg|¸É—žŽüiµy¬‹»eë_<{öüðųç¿óo²ûbîO&þó2ÏWyí‡óùë_ìɬZÐ7t½,¿©«»:[{úsQç¹oªEûÕù±¬¶~–•¾ÎçEÓÖÅí¶Í}Ñú¬œUµ_WóbñÈ Ñ—ÛrN=¶ËÜ·y½n|µàÿúñ“ÿ×¼Ìëlå/··«bæß³¼lrŸQßø¦Yæs+ á•·ÅTGáßVÔrÖUyìó‚~¯ý}^7ôÙ¿°N´Å±¯jY ¬Åàk_mðâˆFüèWYßðs{!Îuî‹’Û_VšÖ’Z¥‰>«•¿Íý¶ÉÛÕ˜Û §ýçóëwŸ®ýÉÇ_üç“««“׿ÓÓí²¢_óû\Ú*Ö›UAMÓäê¬liÜ㳫ÓwôÎÉëó÷ç׿ÐTüÛóëgÓ©{qåOüåÉÕõùé§÷'WþòÓÕåÅôlâý4ÇÀrnáW–zÁÛE«9ÏÛ¬X5Éô¡Mnhˆ«¹_f÷9mö,/îi€™Ÿýý}äV²UUÞñdé鸞ǾXø²jÇþ¡.ˆxÚjw‡ùý¸Ëc^Î&cÿÃOþ:§µÊýå*›ÑÞN·háåËgcÿºjZ<ùáÄûg/ž?~øüå³½ÿ4=  Dþ(x“Ýå~Vç6õùôÝ#Ÿ"»ÿÏSsýο}òùíùÇ7gWþ¹¼ô'Û;ó7ðƒ·«ìaQà$t?¸ÉôÿxòáÌ-—þË¡_åߊY¶Z=z|ç7U›—mAKÜä³-­}OÏ7~8Xm3 "ìͦšçÜìô——Óó©›¼ö±užú›j¶]S‹¼°¯Üäêµÿ#uûåp™¯6þoôçÒÿ)ùÚVúÝ Ça»Ê|{+íNiQfmA;~^nˆ¸ßdm–6O3ªVEùµÓÒ¢Â×óªu燲²gÑ~øz“µ³å?Yœ/ŠU^fëüËâŠ}ùÅ÷¾Ý7´w´b ¸7E³Yeéø Œºá¶Îé]úrñ߯‹rEuE^Q?k‡øq¯¼}Ù™V¶jòMÕ-nóíÎTJj•¸u‰#ˆ'J}âÚqßåß´×Ë“ë볫Iß<ÅÎ/ûæ{±m±o«zµélgUÙæßZîxÖú¬Zm×¥,Äiç:‹YU]â§7Ÿ–ízÅ_¿ë|]¬×$&è€Ño‡E秆†·ÊieòÓÎÕºhÛbw¾ü˶ÈeÀÿžì-äìS¥ÃàA—“°€«*›Ó·øR—ñ-/“ýÞkûµßI’-öýÞÝFŒåœþNŽ ‚YëwuUµ$Bˆ‹¶Uýèÿô=ŸÑ7gÓÓ«óËëó‹nryé"k “žÕ³%¯vYWÛ»¥?=:ýþûN«ªúŠiwO±ˆ‰»®|½-0ö „Í£¿a&Œ'ãÅg·Ô?Ís¡–ˆ„|žÍ–É<Ð1\:ØòHC2^;ž(¤q‘ƱôÌÒåtð8—Íö6é{ ©³%ÞCgïq$lþ-£™ÏinË-=$RŒFNÒåÏônóä !dx4*½d5VóLaÃÍ$ã"aîon&Ü ^¡ñÔ´Òñ¡ÑØaôI/þÛõ- Öœ´SQîŽÐ°j3Ù!ë¹ÀÕœ´*;XÒýë¡Ìê?®Ï~¦¿ÇNWäC1«+èQ´ø‹—†6n¾Â»¿6Á ֋rQÑ!ÉóW~Ù¶›WGG“zSLhžGÿw³çÕQV·ÅŒ(äˆ8³èt*³ª #ŠÒåÅÕcƒqÓ!åóbk:q%œ&âjɤÂÁ‚ò:déQ¡%¢Í]åuñ|ìp.LL9‹A-e+ŽÎ š–Ó›^’ŠÛ¡Ë| ½qâÞ—åͬ.¸Œ¬©pL¥§šÐÑ=щ;•ùœg_K¦3"Òeð©ÓŸÏYÏÁ¥ˆÅÖÆq6\ú†$3É'—±^8Û2…ÞætZ:ÔRàp/ŠYÁËEíR‡Ä< :žÂ1?V¬Ö<9<ŸÍÚ-?EI~¿]Aú-ˆ==Ž=Ë›2¼¸ÿ1´U’ÎÖ4İWФhïð¬cœn 6âœÞg3|²Dgu¾®îéƒÛÛWppbÇþt(Ú5lꢳô%3k—m6]â¡_0[>G)ÀA×&GÁ3y×›ö·´>œ büÄfÑ[‚à©Áä=Ïß\šñÆ*ÿ#p5ûJOºuö•Žñ¶VUž)m•ß”bªÏÖ€2pè¦Ùl–o £XzlKR…|¤qÔììEIÓ Š<Ý΋–ug=Òã@üë¬þÚEu4jÁQœ>ÐóÁ±™e˜m³¡¨¶ %³ù¦’ ô‰jƒÍ!m§(yG™aÓ¬ò2î7´Áô›fq»ÝlˆI¡Vƒvl“ e“ å3TŽa&}à”Ž;f‹VX2阉|:ãùja&– ¦‰·EÌ[ëm£P³*¢kˆÊX¡TdLãjHë9¿ô_†·[wtäãù|¥œ/ùù»=?ûïŽÝT5¯#Î/Ÿ1Br Ï8±ˆm`”HuüWæXnp~=ýÝ+AZW'×SúS¦È{ùäB1M PRÜHêdÞ!›Ôl „ ¹`ƒꪼ§\ÕWMõLa¬cÿ°,èu&¦¦wùq›<ÛȨW‚TZìÞƒ’HØ Ã¶± nÈbŠ„ñbË:ñ¬þ(Läðñ”¿G;’‡–ÙL‚—ÔÏÛ ˜…V‹1à9›!òöàà˜'¬#çn´Rý$«sãV:0ž¾Þ%01Ïêyl³œ­H¼68/Y}— @çœUƒˆlé´Ón­‰ãÈ‹ ÉÛªˆ“YÑ4[Óš°i¤¶ÐÇš;Ñ¿ IóÓ ÉÐwì•I‡$ŒÿTßWÅW᚟iI »=ϵyÑóLæÛ5쥀¨ ãÈVŒ7-HDôkQ»y¾È¶«6Ì$ ƒýÝV÷tZDl=¡±Š ò¬°v¹£UyAýÙä© jL¹…n)0‘H&*ǘT¦IFÒÛ|[Ksï´[Ú]µ9ªnfîžÚHAäÀŸIRègshh¹gkA³…m¨T‚lN‡IÊ%/%Œ‘È-;ß)nOö8Тcù”Ñò3\¢ %m'ÆÝ³("j4̳Õj ìÆ HV­Y_™glFdEOȼ ˜«úk¾>¯ð²¶¨Njëk^e¹ì†¤ám6xªƒ;#NÕ§¹£„­+ˆ<à™<òÆ¬ÊÆ4Ü0î-7&ÆU;"¼±`BÝEh—$|hÔ½…wÀ»yXàçÆE.Kå§§×i˜ÆUDá“åv÷4AŸ(‰€4M[¬aIeôSÉǛӈ, Þ@DÜ’´ÖÙì `¬»Fì³U)‘0üyECø²8'"…Ó`µ¸e ¢ £üµ±®VÔRõ0æEÖ?éeþÔ>n¨áš©c–íR<ù=‰Wu’Lh`8¦<˜¾íÂVÖÇœëÌäÀ¯¨xf„}«×§o²›¥¬NÞÝA¸Âcä(AkÛÁÏLOý9AeP=NP= ð~ 4W¯¬øeý oX¶ÎEˆž3$zO§%{}H·,Ò6Äçn4­ÛGÕwØjT³‘«êS9ëF ‚ò€õxБo1°²Jê=^°0á5“u¨æs™&ˆå~SmH馃Ɔ'!O¦&"—-À fÒfʃî3sršˆöZÞT&>p8.ft³ÕcSè”°Î*UÇ®QÈ„Lëð¨oÑÖ ÷cÅB¿g% zá' ³ZŠR ®„7Èö‘~ÈÛP,TO]Ì¥Úè‚ðODGÇÂdŒ±‘Îr×EdÁšHƒ "_,®x !°‰û¼„µ.ž¶ÔŽ›˜R;„+v«M^ŠU,0¥:¿§üívÝΖBU UZ_”6 ™âÛ¬±³éFˆcÙ±&³ÁØ&Kþ>Ó6üïæN>Ÿòÿgú–^8½¼”Ï߾ɿú<µÑK<Í(|òn ¨'ÌåææË!á„už•wþcµ%($@>´ŒçXéì†Æ’çtøfäÛZ@…§>ç~S›‰V¹"å™x8Ä L¼x’SAU󸾭àa“P¥LuCCúÑŦèM”¡¦÷²Êû“ Œ°sß-Q áË-Ñ|ܽØÕUÛ86Œ¾ž¹®xÿŠÆ'RbÄ<ŒO #•®í ÝŒMwÁ9†¹k˜5Ê…ï<ÌhJ+µ¯3 [Òy‡\UH(ï/NG¡9˜$ øI¦UVåá-ÉÀ¯cþÓ4Q/mÄ,žŸ6ÌXìaÑtlF%шja N4(ØSØ®X¦¢L ªl® ¶®áód›G&åüàÏþ使ÿøÿþ4”™µbLÃËϬ_üï™ ÑVQ–.<ú<}ô§î£qò%ȯLÞp¹ŠæZ4¡šà[¥ß½üžÎ´ž íÚhg·%}zì'´þC˜{öô4-Ã÷4ÿ—?ÔÊØŸ?ЊØãôÜË¥>Ï¾×æx‚zÌnóhÅÕÑŠ;ÝFÊêʈ‰¤zÓÿfd–¨T 3Ë¢ ê ¬ làÔv´¦ .$Ѓvüù³gÏxâó⾘Ëw:Gì¢Ó+‡ž·.0‘JÛR‘#¬ùEgKu­å­`À1%€‡*Ú÷ êð®L€ñFmª·¦ËÆéÎ&tFK´^¬‰‹pËò^5êS#¯9 ¸6”ÏS&hËý\œs›1µ(Ž/~j¤:¼r0vÔ0ˆ"TA]ÀM@¼‹ÅUój×›OŸ¶ÅBd Õ­³GÌG`ÑSvR6Û¦<ŽmV„_öé_°RgXÍCÅá6—ï‰]IOòTk$Ó~¿ñý®F'š˜ª2¢™b¬ ©RSðh8•Œ*,Œ6ø}xn*Ͻ ˆqäJ¸‘Ó0²Î˺OExéNf["qf ɬÀh„Û69u À,—ºVÙÕ>x}u~öÖ_º¾¸:?y?pîíÚA”têpcþD¼/AHkާlŠCµF´ò| ¯€_v]ô ŽXG‚Èüoý+©ù²ÎhÄ÷ý áEx(ªýÄÖºšÔ“d^ðdñ½4ƒŒ³mÓÒH§ÌKfJ[½6Fâ‡äóÖn" Yûó¶AÛ… q®NÌPÍcÓækBE ƒÞåöÛ˜ äõô C°ÙìbêJ=_ô­Âž_Œ xLWPŒ¤–Ý’(8ÿVHVźõ›ÄÔ•­J±îðA1VÞB÷làýu %: q‡°šk~AëÒ²³ÎÔ¿öÎîˆñ>‚›†NˆÆ¼gÑd‚S™8/Qø!<ÓT=à¥ðco0ývæÚ)«ÜTl×ÀXžï1^B:²’{)&²rÉ:˜ã1þ­`9V_¼M]êx/£“èŒñ1£äâ^dwõˆ[#vuG;:vý°Œè>{ÍROyXv½GK–Œ‚bË\`^‡Mw4“Ò¼— [55È@†?f¡n¢1„°«É±óêØüŒ|DWÄLYÉ-°@b¢W:¤ÓÖ´QïóE»piî4m–3¢¼moR±â>عáN=„ ‹áîÅÆ%²’ñ85­‚ª-ß,'iG“zc ™Œ;~‚ž÷Õ:Ä¿“ƒÁÈì[[gU=/JÈÕ¾C=Z[ns¶®; Hà=n8lÉ3‹˜CV×ðî‹?2N\ÂoO°ªfNýXº2ó jwTéE­¬kðVHó;Ú¦ KU>s „Œö3šýtEH0zÖÓpÏ#>Ôù¡bˆü| Å™òþÒ¬4àÑÌ÷x‡Áý»‹Ï×ôÖ§3—µî7öâDRÐGàÄ&†˜I~Wƒ¼šÆ$ÎHsŠ<Oƒê*<1®YÑŽ;£ Í÷b6ËŽL Ò6‰etH#ճɌÅÍ¡À«šðŒFX‘bµ/‹sêõËâMõœ±Ìò‰j5«ŠÙƒhF0V%ž—Þ©W±¢NØ9 ©b«÷ä²r 4[çêw×eî£äÏC"Oצ FG›ù·ÈVœ+åÖ‰è2ñÌGMókÎ,Ü?íl$&Nkñ5Ï7"¹ÙŠo¬i»1°Uqhç®»y^)<‘±j÷]%¾öj3Œ° 6 Æ9hÄÐÁÒoßV˜lZøÙ)½‚uÚÁ.Å«Ó$ÎpikÇÒHͬÁ³"ž{bÇQ7‰}g^K1y“`Ûƒ‰û_àV±gêL¤Û\üi›€Ï b Ía¾ÉWÕF¼Úå}A3g–qÌDÌVŒù¸»þÑÜöæBäé«u£ ÑMX±c rÀçß]xoh?DŒÉþ³"›)ÛÖkðiXõE"˜$k.LÖ´¸FuFížÅb6€ç O:×Ý©2ŒßœÊl¾#Ö¾a: j²>Ä®¾Ð ¢ôæi@:AF^Ö¨ øÂWÒþRC¸uŽá×dMdýÅþAª;>zõuaáI ¿mB} ŽÎ`ùkiXßzjŽ»¼˜žÿì‡çpßúLjóéÏæ¢ì„u¾¹ùÔJ0ÎiUÂjˆ88`S Û»;]B·ãt ]*7œ³½üpž5˰~³˜ È8§|ýeq5r»ÊýŽFOII(ÞUÎŒ’8ҬÜf+zÏÝܨ¸ò'õʜ;ƒæ•´+&Ñ©®¦ÞÜ„Lˆ§j,îw%c‘‘BÙ¿“ô™öܦ*ãæÆ77‡‡ÿÌÖ‚ÊÔ.}ÇPQ¿š¸)ظ­ûLJF_ê¼Êç Cu;:Ps†#½³ù[Èž5Ì¡8É–ås§JkµbâáXöÃUÎ; òYšúA'ó‚tÐÉõ¥þÂM^Ÿ‡ü |§_,9îï}¨yø¿ ¢õuRC'N¹ÂŠò¾‚ö€·i= ½nuüߌºÜ(i>$vð;„×!ÉF¢ ª]Á,aˆU€™÷‡ÂÜ{œ­˜è5dçg3r"=ê⎰½š9ž¸4³‡cünì@´üÚoæÐFFÉŠ÷ç³n Þ0qfÅ [ 2̺Ùía“éìR2ÖŒS±kÀÔT•[=îbUŽ„Ll¿Ñ®“mn•A»` ÖrÕpQ ‡“YÄ‹Xðf™ÅСìˆU‚ÎÛ­ø¥Hž!7£0DÌjË\}QK:5Sög[þ|òâ'…f.Á+ÆÀ Î1;׳ÛFU´ù<ß¿Q´«¹Qÿ¾ü ÝC\îé¨}ulj.÷¤kdâÞˆNШBÏf4Ñò%쀶ãV…2ñ€¬m¡ÊÖp‡AÍ+ÚëËK ðÖ\@ÌøàËTìbâ›öJª4=9ï…xãíÊIO -{Óâ…Uµ•£¼!>úaÖ|•8⾫¾U'‡Ù)  @ZÔ …l3VCŒ)2­® ÊèÍ P.Q ïI4²Á“å ʱLÖZÅ~±ˆwÎ+`#§Š¤¹ÇsVveÛÝ%»$Ó28Žz/…kloR÷‰QzrÓ˜dÃc„hfºkU gw¤G7ý}á åÄ»§‘=ÿ_òË0ŸÜMÆþˆ~9ú+1ä§ž¾úòeýØ´ÛÅâË>Ï»ƒÄéÛwVŸ=/!«cYõõfèYìñü4Ýαõ/u?0"x›ß’à}LIà7O-}+ !}ÈLaï;»ví€:]Ò0rC€ÄuïAŽ1\¦“»¢=±NšûòˆèËEq·­Ó^’|;MRݹ ®›#”\J^ÂŒ|“(ÑWqüÜm¾Ì3øÃî‚‚ei–˜e$"?ŒÿÆ^[ahüÌ¥¦êu~=KB”ÁbX|À«Î¦X ÍAM–µÀP⾄[v-ëⱋ="ü’ Ÿµ(±bo¥Ž«»’­šiz‘‚j§ä› mbÍiv0Ôv8ÜCŽÑ¸“däÿ€U´ôbQš$l  cd…COç-ìü,Û9¼$p·fgR!®Ä¨ÏҢ譢¶$y™]èê Ôì±Û@ÓªDuL²¤¦œäJÕâ(`ÅL¢¸8qXKªŠHX$;uLŠaç´âyrI78äšÜ…`B }Ñô†ä1Mz³K%¬*ÿpŽYYd!žšØZìÔøL’ ycaÁâ¼>ïö,CÒ=½ “©$߯êåT¾‹bøå‹¿o&þh„+Zô='ip?¡áGZ9%-Á ²”&!~¾f£c—.oj-RQ¸zº†EkëvÒN$7`6Û²…Gìó CJ¼µLã!ãÆWxI•C+–]©Î;îÑDRr€¦.M§ zĩÈÑ2H˜ã¹hÌEzaÁÕ-Û‡%†–ó›²EÑ`ÝO½®Ï” ïæKs^tÅáÚüÏ7ÍÛ'<Â?kº‘Ë –ÅØÊB©š(Y{~xsSŠÉûà`Ä {øj} MÓ÷nȾãIoµ:¹Ú颽%ôÈøÙ8H7ÎÖ(ñ¤bH]ó7Ar ’F¼¯]½Ñµw§âÓ¢¢àìCÇ"¦„“†ƒ±F1#}6Ÿ­2•ˆ³¤O3Ès”xäV ù:޽¶ÀŠô,ãe¾cŸû¨Íq†³Ç`[røJB5শ bó X›ºgb_M5šÄ2lDE+\Ã0ožZÙbYUs$µ®‹†Á`ôÜcŽ5KczÇýU¥_ÿA,"ŽVJ“ æçÒ c¬mÅiM€—è4Ÿ÷F<”‘ªKI«2 nðûItÿØkd`í–KËãÝЋ`)îž).°Ù©`ì) Ì+ ÑÖ)Ñš'ͺ«DûQáàcØ2J¯-öt˜ôúíÔiŽ‘(¨ÔÓYoÏ_<Œ$S‡ÉxýºÄ5çÁXÈÚ*»KF¤sGÝía†»¥Ö3H6òT˜¡ÄÏàG³t “<‹Ž ô!òSž.9懦£€$ë8KâêÂ8ÁÐÄ%Í®Ô`ÞèŽAE¯äKÉ H%盩D=®ûîóQ8s>1 ›m;$šüy»ÞxÓ[ÄÁkĵr,cðÕ*ÊžÄÚ£» ÚôRµëˆCÄõøá¨w’4í8ùn&›¢?¯šä 3y®Àã´Dk>8ŠqäPä¤QBѬ‰àQ*'Û£fо<°2©(x£†„àjEÖ›Q˜4¦ž¸O‘©…Ò7±tV<ÏÅed¹ šñÖ[ÎÖ_¼sBÜ)ê¦õg·TR§Ø6!gƒ–°?­°q^‡…;OVÆ&'¡sâMåÁ>d\Ë živy”óQ¿õXÎ#i~ê ÈÐð„l `'§<{}8M¼ˆF¹Ì”³Y¤C‰rÏ4¼Z5ýqXå»`÷8Ö]׺ç„K2Æ×æHã¡=ñÚð-AÒ%Û`nÉ{H¾KSAêõ-B=úƒfòHÉíß{䆠÷m'ÂÖ倈á&†XßæèÞâÒG0ì¬òîè¿»J¸©æ/I5öŽ€‘Z!,áZ˜!kÄŒÅøªºS%»‘SJ»Dª×ÀÏ(™,ôÞ øŒ^W—Þ_‘ÅMYj_ä­Õ^4”f / ¾í Îý%`Ü{úÚ2§xÞŒ(ßvS0 jPRô©¾ñÊ<Œ©3èÊÚkú©ÁÒé™À-@Âo£î˜÷—I¼Ì]3ÈØè(¦°‘‚U,Â[Ö%Ÿ#R¬ˆåÔ®Ì×Ú[÷§¦ÇÚÕvzÞÕÛ‘ÄBˆ›ó'Aœ1Ym.Pò_C·19PE«ØÒb˜+,Aâ{ËÃa%½Ç¥“¡ýÚ$ AVßfþz­ù(~²ºCØR²+Xvï3ˆÄcj™ð¦â7š}² zîäIp:u ÌêDc)± çJ‹ú–ó'ïÙÏ'.ߟM%*’‡ wGðnk`dk§„=Z`JxžÍZQ©¤)4‡"6íNÞHÁ1Æ„ŒÅ€"™Oÿ%?½òì® ¼q<º0 H9>¼Ö÷…DÇäëlÖ7ÆÓsI±§$­m›ú¨©gG+„¾œ<ÿý 3I9è&Ǩ (ØLö´ÀCÃË»¥“ü0-4vÓU.…2Z"NýÔ:xQv¼+´ð“1¶FðºÖHÄ›”ÙºTE-ª³([Áïüä7­ÈN&·¿xTwŽ]ª­ô2Åüð; „ÚˆPA%-8‘¦3žžŠFŸ¬iw*üÔoú89 –u«"FGûZñ‹OÊËNôŽEë0óÒw² ±ÜM-èïW¦–¦îÿ¶ùuˆWÞñOTùJ¬ˆ¡&“'*S°¥^UkÁqª1%™ Oûßßôǡ먥ÎFLp²’'ûq~7Çt.̰ÒÜ] ͬ€|/‹‰IT*öð¨e8Í’òOQj+¨±R[õò†]Ø=riD/¡2ú;i6/¨®?”§Wszºw=Ç>å.{×ÓËÊVåEi¸±&\gÇ3Šš ¥ZR·Ùg>µê56[KÕTsÞXä9‡ã¥©²3¿mú¦Â…Z‡i E¡«?Øt¹ÖÒëá8&«¦VŠÞ‹…˜W­›¥‡Ø˜ˆŽbÔ“†æ'j¼”byAT.Û‰|H°ÁÞõê¦7÷Ý¥‰›4u¾±æ4O’ÏtQÍ»ܵb'õì<)EQoëÍALœfýü›üûû‚K¿qÔ8ý(Ee.X~'™Ú8¦¡í³_ôÑ€ê9p:Gá`‡Ë$7äÚŒ³¥PnRÙf@§wöuQ|CÂ)–ªhÖJ|œBñxRTÔí ¬A0 ¤¦6‹Ã[¼š!]Z”­›¼ÅѳP,$–¹Ì…”wTŽÆ±Ð–4›9ÍÑcs2á:Îÿ„¶R>Õ”/“bec“2 5Ú†R*Ä*8Àé°hA5ù0' 1ßitÈ•¤4ßCbkFx)i\ZJ¥Õ°}ÜXUhì§Öè£×,×OK”†‰Œ{•_µŒG(‡AKíhR(¥~õû3 4\=“«|0â«Dqâ‡ñ»¡Ù~€‡è§ÐÆÎj y!ºiXj— ¿`fÆÂÒîC}gI@´…ðÏæº°»a)iÍôªÂkì¯þG|èÐdÚ¼M0– ǛҽÄq™-â1*ÝèJ}i‘ƒ%¥Ô¡Gˆ½”4Ê §bÇHcjòí¼ê[ÞŒÁ(!ÚX‡èóošìPÖàY–‡àCåw/˜HèÓåá%ãúb¶Zj\äªfM0Ðr½L Ý/Åá”Q©“ F¡^“ f__&ÕE8›‚Cù/÷ÈÕ)Á÷‰r¬_”©”Ûš'æ’ô¢ãå•'À ë¤xí\9ÑñÑ0À^úñc÷G Сˆ”×ê5Ž„ÂFR*BJ-j' äösölf)ˆ&‰SAÖåXRcйb`Æúö€G9[UM®óßÜXïÑ`t»ÝÂeBŽÑ€q5!¥›/ÅÉ—Î2„A¥cf×Z*>ȃXpÂÀ/!¶›>’[ê!ä¬[T'c »¥1ÐIŸ;µ·õ£ög«,DªðS­‰Ž!|¯‘ Z¨ƒCG86XëÇyZ®f¿„d+Ï /ýöO]a?eæ~I„îО0‰h)ý*HQà ]«VZš{­1œ­Õ§qLÎ}á9ëñ”ä”í$bpše#ª`èë¿(Xû㙄ŠÓ™.‚¾º«Ûã}‹ó:J_,4ÍM‚è ÚÀc® ßø´IX¡+ÒdØÜLjeãG]•dH„àãhÞ‰{W=ÀÈB$,¹-]hŽ{ê›XYw`öà:£Ò¸îÞ$‚ËDH(­Ô¨íƘºî&R¤)u¶žõ3+mêìZ‘P'([ùNì¤ìûµÔg «=vyHŒòÃá7~bà‚Ô‰O\òùÙ6±ÆÓµûö·¯É©ùm­«ë.#Úk³Ã¯ùcV²û\ÃD¨ÙòHñ¬Ç³}½Ž>ÜVHð¶Á¸Õ0ÑÜŸMOñøˆ‹Š%5ÝeËTÖŒûqä„¿:»þtõQ°Œd£cÂtÝ9 (çP]9 \rqv‡]Œã(qœÜ–ÃÐhc|íI·ÒÞ&AHò6Ù€dA³¸@Á¨… ž²¢±Âì6dŽ[,œU¾xÜ‹ ~U`ŸBb‹ŠQ„•ÒäöX]#äÏ'a @DZ‡UÇr§2×Ã/ç»*ö&Úfý ‰B5Ž]ß)¼5BeíÀ`Dð´šúYÔ$Õ°\bÄN¸ö+¡fG‚]^Bè4\ÄW/sè%V È£ƒ/ËpÙžÂF©¨HËg e·ÊjØõ¢´½0è”ß—7<•8lú Ó~‘Äi Kƒë\7!L&\…À¸©' &îôp«­û¡FyÓ7³=ýÐÀõ›`@€s È0yƒIÇ"9i¡În‚7W¬“jÕ­ª¤ 9ûUAÐwIÁw†E¨‘ïpúì a|Á\Zçí¶.Á&nxMB½ä*=°{ Ó1g'!¿„gƒ8ÊE6¹K ƒmŽ4”?ê.ŽÛ wÌÑ€GšãÌ-ç­Ê„[™ó渿ÿñ÷~øIhë2¦Çû7!=þ­F¨ŒÄu%'5Û»g½¥¦tÉ&,;ì6œm‚È8!=p\/o$Š©_¼ÞаwêD‹”h¬%¢‰8Ęž–Ø÷VUwH!/?Œmf>”„fñ‰Æ(]m˘3ÄhÊ®Ûnæb^ä«ì²6<{<ÆkšŽØ)*—œ½’âÚ¡š³]„WHêä¡ùU>Z¤Xã#ȈyÎZKvS_W°‰ç×2忍ÉXñü¾¸\bú%$~H\¿¨oPkó\R³6ruù‘kýOÜ¥éRq™œ™hʤqÜnïÂÅO\|¤ÉJ‚(¶ïòP¿ˆ§åçtìM8ò.Þ,Óˆ<Žh«„`·¬˜ï–Óß[ ^Ù®¦äŠTkµ§±†‚i ÞP%Tk|‘|‹={¹à-Óqq ÝÆ„ü<èÌ|êíXÚM·2­Y€ˆãÔå(u~82rO}7¾~ŽÅógÏþ§”î=\æwÙ¾‡{õç™iY^«î†‹$«ªååd“_¦zmæö1=\>¸ž1=ß­‹i7B°g“Ï‘qýê¶áêi|‘\½i]±Ø [`R£¿þô¯SÉëÜ-¶ª·%ñ)1ß;Ï‘'Mœ˜úõ„4Ž –~‡²äYýÕ2n4yìÅÛŽü 'ñÕÓqçáÉÃïQ`0‹Fîˬ]r2s˜«·ppÖú›xeæÍ žò×u†Ág+‚Îñ~%ôðã?%=|Ì·mëîB/S5[Ÿ™ c‘Š ”Ò_LC]!ê'ùt^þY{©·ïºÝƒÅþlÌÚÙÅ&· J1ED¯!PÔ¼ñ!_cZ¢– :ŽrF »ï4¸“Öìà¿Þ¨°)ªdœ¦ Ê©)(SUPdÆ¿¦šôgüâ÷¯Ò§ÔÒ{äåï^ùO¥Zå %4½hÊ÷ªôü ;EÒ/TñÏu¶ccï?Ðgßè|òJ36ûTò¿¬‹{NwÈIß{ùâG—A××5ßçB]ñ%—§õã¦E4ÑfIëpbqõ½¾ ª¾Bí*\q"ž¦Ë <‘(A Š<¸@ ÓÇr¶¬+»µ …+½¨A)ïµCÏ/ü«£uq9yÅŶÞÂéÔy’ÀS˜Ý¯ƒ§Þ”~|‰SYªtô—@‚’«tÒ€á­5V¨`Yf×oèŸ~ˆ#À1%ý«ØlÕ\e½bü ‰Ô‡ ׂ°3@`y5ÿàų#í··jÿôŒVí*_õù)¤’œKl2g9NÅ¿!®Ðì®Ì?½ø‰WFÓÅQZ'‘qá56±Å¦ÕÜMLpä»Nlbñ¨D!S ižÃ1V¥ÐI]ˆ÷½¶‡y¼7Mí— >û¹¶ãÔq©ãèªDNT±4}v'¶Œ+Ë Ú׆úÍÍßPH­ìÄs–¹ ‚#4kî_¶U(,î#JUЬtÛ’˜kÓª"ÌYF¿–áÑ1NLY!aËÝŽBfVû»Jõæ*ñ#õ6*æç›¢+…ŒÇÑZÈâ–E~/Ç»•«“²qÝξfßpAº°ÑùN•=)ÕÖ»/j+ù‡¹ÿÇáL¯Ly>¢.£§áê1T2¸%PÄàNÁešð¶Òÿm‘¼M=ÂÁ¦µNúÙÉéw­ ðˆjñIÐàñÚ«ƒjxíSzh2mÔ5ÔY¾˜­ST¶!œK–ŸÃÈ9Il4nõV°$|.ë&Ei‰:è fC·F§¢YZ%Z# wËÒ©Ó {é3]=*qmù¶&PÍ«oª£ix]ç p'œ·n¿ÒÝiS< ±¥¨-‚Ëv5ùn¿U1塨½èaËü°[T!¬÷£"{⨱[°³nì 0­Ô–ŒS½ë†ÐÆ›ÿ&)íŽ>’@÷‡ ¦ðŽëÌ&#µƒË:¤ÙL¹ö÷–ý½CøÆîö~xÏ@Ÿ!VDrk»ƒ|òP°N.™ ´jke†¹¶oÿ˲§*9×eµ3­T"›½GÎâN±³”šQ#­…¤ ³b÷º=¾ÂÄÆ 7õÎÂè·y¬Ã{˜»¡»3÷&Sÿó°UÈK^Ünå† •;\v]na3L/;¹ßaà©…ƒÆ¬$»hâZÅ]¸ß"pf¬^V¢¼…53¾è„ƒ‘¨Èã8Õœ乇KË4B6™o,NžØœ:뺻¦! Š÷î «(_\>ÒÜʤ*ØÍÍì?ŒÁBS†dZoçÇ'BÑÊáŽ*!ªšØ”Ðã$Á]lé·|$tÿM¯˜KÂûÔð¬PMr? W{’8Ì@»–]ŒZAðVÒ¼8LÆÌæÉõ.“1b¥ua VÍã„ZÅ2R¢Îwÿ³¹è @*+±¸¤.±áÕã8Á{ÁÓ!¢YòœôÂR¶$ñ¬m·Ý>/x«Iב슷ð‡. ¤‚‡IyäÞD·–TðËqOò¸Õƒ`yäš™iõóƒ£7D‘éˆbÑvÂ? a8Ô°G óÊÒ^mìMË7Nñoœ.òÄ.@@XÊo+þÏT'µ}Cd•˜ï—j{¾{‘“|ƒ‚‹#J´ÜÎæãÒJ/jy¨êº Ú¶X«bÆ!JºR|ñSr+„F`Á=€0gÌMrq‚ï¬à…lðÅc ¦Ï3•Z¤§¨dåŸø”Ä‹ ª­2u¼êeÏ핈 Úr~éG»™u¹â$Ÿ*˜l …jŠÚ¥ÂŠŽoR{6©©¬˜÷ïeѲÑàéZ á€ÓoÁÅJ«—g7 'ÙÙkRÒ­ˆZð>öt!FX«Áh̪\ ßeBÐÜ~ÜæI¡„¡æƒVî Ö_h[Û‘%_¨nÔ¹,VüHV+‹—zWe½öÖVN®™íÜ,;f=¤Õ€ù'‡ñf´Sô;8ÉØ;Ä©52ž¯…Zí¥agn½¬Û#L@Š\¤ÁÊ[©ÿ‰ _+qoK)œžTqÖ}Ì]'_1 ‰PÀ¬%kR«ðØÄÀÔåY²/®Ïf&¦·ÔwïÙa7ŸB˜ÛµŒ:£´puzÅ3§Ÿ ÚìñîA[«¬«ÆµK«í¶ärý bçKŒòµ™ŒÙï¼Á¢æ ¢+p˜€`ã]]«Ö®—‹y\÷~ë8Óp×5 -ôk~Ù§7€ wÞ¡còÃà/‰P 9þ0=|s1åʳáQœ]ù~¼‚Vj'(ˤ"Uëç(9Ê×öv|à­†Úõ½Ô!+,/ ÁM[d0H$ËC¦a¸BÙhÅÀN]p…– &E gwüáB#¾ÑÅ,®\Û:›¯º—¢ÍéQ«ÉO<ÆH9V>²”p«Û?óý,aÀyÏwÿÞiA„ɉw\Ÿ=ÜhZ,¬*þwÚ'¨gh?Ù³že÷œ bÒëq /•l«²ûSB¨cG¢#1‚Ë53×°õ™•pǹwÑœâÉN¸CÆÆ©È@”—9!{ƒÓZJò1¡©`­f{.ð! ëÆ[)vfÉ¿‚ªàMnªCI$ %ð€¨V¹fº<_¿}ñqì/¯è'Ÿ~ûÓ÷§ÿöcÿñÓû±;½øðüþ÷“ØÞ_^??¤ÿÑGÆ’yœ”£•«àäÆn×9“ö[K§c,nÛÇ~YýBÝ pY69•Ñ$Œ¿_~JzÿASb¶ñ[dñðˆó׫¬œýænâ_¼x)˜§@‡)ÿýJf¼¦rz’àžÄ­ö Ô\fÚÛU“(åk'_›BB/„åÝæ¦é­ÑâeÃQ@Ši´0G#ä’í2qS©e¦`äÃ/Â]° RåCtGŸk–jûì’xÇ¢6 hQ>}uâ0×Y,ªa刃Øs}í-ÇÈáÆŠ”ÁKan…xÙ¬3••Ù3®~]kÒ¦ðt¾1½j-¯O3ø‚=OžA<´ÜÍÍ5f2¹Ÿ0it"PŸ¤ë2»EºçÂ-ÁlÆ ´˜áŠ™†.µžsT’ºžÓY¾0MX“À¢;ACàqwykÉÑ|ÄÖÃ#¸ÈFk÷©ÒÎeö$If.ã”âÄF¾ c¶D>gU§=yÏÑ“’S¥V…‡Xf0g»gA›rúˤÛm±šï»µ8ÆÄ…Û1+Éy’jEc•jAáBRB}ªWjN,±jDN½|h¬ãÈè`%TÈÃ.¸FêgDëø—Ô½Ý., U? ÏÇ©¤­‘^E¸ÑrßÎIÚ3 ˆÔâ'òqð‡?p:k“-4Ú ¹ú±ä±ß©Ï†—Ô'gN)ÚYys§ÒxŒDs| i÷V”CëkÂséÞòšhMâÌc]ö4Ò¹=”ÃÌåÂ2Í×–èM ©9²'Šýx•*`>‡‰+Ðs‚ ›X£8$ ¹®6Ù½¥vxk….Ìnl—,½dß3¡Û T|ÿ]ªï|á”Sh•µPù€F Fâ)O¹¢b¨:@j¹~Ñ­²Ûj7ùD¯k#ÑrmGÔ{”YÀR5c›w@ÈÑ&bqÍðàÚu ™{¢Ñî »¡M²êù*A”Z 2в¯Hîó¡«™,»¯ ¼(ã¤8î0±¡©§Óið¬÷•¿[U·Ä££U_îßÐ.RS”ƒªù¼ õx9\T/ͶYÆjîfN[™Þ'à :ãºh¶M0D²—L M³o¯ø0;}½/Ô#‹&õ&¯Í#jK 6æ˜ñ굆yv_p-Ø6¢½>óÊðµ[Éå:ŽÇŸ±ó"‚¹lÕa.„'ÊÊÉõî;·Õ™  ÿAüf6›&×è}K¾îÍfŒòj+¹áA1›/ÔâË)Yr¹ž“ÏʰiEþTŒÅKù>ß˹L%b¨’“ÐO+;­‹ù|¥–·èâ`üÎqꂌ%©Ij‰õnËÇË9óÉKõ„²BÄe9ž¸ÔŠúù‡bAÄí'ÿ9Íʌבew¹”Õ_È%oS¶…ÅØT6}ÓŠr¿¯®X.UÕ>½øøJ DžÑ„Ò7Áûà̤*k‘¶ûéê¼9útõ¾s*"%ë´ÔÅ)»mÔ¼çvÖ´b¥æþ”Á]•"%)|Ët0•i½Ïîaö½Zn5FN‹]ï×F£ˆ Ö ÓÅQVÅò_B? ë`A°üõF"óºuoÕ¯I“EìƒnÆÁ`I$o¸»Dâ,”EÙ5!¢5N/Àh°Øt¨¾mþ2Èdh’žÙ„“ÕÏZR—èj(¢RIáeˆ¶Ä#XÛx€ÔË!sCä^IDobÜÉöWy@ñ¦×Û6ÑYtQé§ãnÈÜòIÍH¢Æð—TºWZXp ×1â¢a~Àå·´øâô‰ZJJ:Ó$w>Ó;b; ö°gIœ#/»)BêËM+OÕ¶ˆ xXG%Æñ-Dn•iD`ÂÞñ¢‹¥—ø§ÅÈ@ERZÁâN®-V.$àEq<Óñò¦áO£Hx\¨Í¡Å½³BlÜcCã‡ÒªkÞé£Z¸’«‚ˆÈtn÷èh¾B'ôÌ00Ã16r¦ggþäýô·îö|ÈohB¿Õ•ê:ˆ¶ì&ç¸ÕŒ—Š+-+˜ý®ìåÀõþÝÅçk ¦Éù•üÆP²×Ùœ|º~wqåÞd÷´–'ÿYÞñC{û_Òfè$ý?$âÒad´flawfinder-1.31/flawfinder.pdf0000644003056700244210000014772612367502046017303 0ustar dwheelerDomain Users%PDF-1.4 %Çì¢ 5 0 obj <> stream xœ­[ËrÛH–Ýë+Ú¬adâ]½ð¸ìnOt»Ü6;ª&¤Š6‚"Z À@Ñš˜Ýl]Ÿâœsó…IYªˆ/L“@æ}ž{îÍôoŽï1ǧ?êïbsöâCâÜög¾s{öÛ?:ê¯bãüç¤ôÅbu&ßaNÂ$ ¼4s›3÷Í__Îÿ:c‰—¥YŠË3„^œÅþìÊýùÍÛw?¾þpí²ë™ó¦Îg,r÷_šeÙ9ôꯋÿ: 2î©7'Óºsßã ;$ƒ ^‘,ó“Ì™±xí§çXäEY –ûÛkú~Ôû^è'ΜqúÙ—"þn õÕ©Ë ¡MÈÜÏU‘×õƒƒŸœm;”ÍPåµÓ—Å®«†G¼èù,ŒÝ}ï\»çëjèÏ¡gÕ8}»ëŠÒ)Úe)”œŠ±ç,†Ö$äÇÿ~÷Óûo?JQ3%ªxDˆ ¥pS]ÂÈKmr÷êàm/|_ÿøõ뺬·¦È¼d|ý§¯sýâš¾ç^$=`By<öõC¿^ã+d‹}ËG® ÁýŒùnÙõUÛƒ-r^}þ¢X³®ú¡ÛÕedn‚ÑýUÄËR¤Mú-s‘´p{;ËDî¾®š»ÓBGÃ?j‰ÕŒ#¾2ž¸íd—e;,«îô>1.ðÙ1NÓ ±'– R/-“„^š>Ë2Xu›ÅúOòækƒûVö»_ê²É7åÁÎP 5 <nïF"cLâ@Áè ]¹]uÛ´ÝŒ! XÄ\] L 1/L²ä Uš#UlüB%ð@”=/ … ÕlÔ®ò¶üü'!4SµÖNmê­æÌCõDÑtß¿tcÉE|Œ–]¼þðî ÔÄT÷žŠ:mÛC ·1ëmza4E†ë¹þ.Úf(?Õ…{(cÜUÐ÷‰ÇÓºéÛY}gaÈ,êݦ9,p0èèÿǤxõ˜ÜËX–ý)–ù·Mýp U“'AòÇŸëaSà4Òç‰ýÿòØþaå7KêáþÕfS.«|8(AQìéSTj^="Gì±§óP޾jnëåýPfS¨Ç òñi0 Q@ãäÙ¸Ønªa¨de>æu šOøù°2ü¶«Êƒ¬C™÷c³Êcªýý@µ©‹%Pç?W³ºÍ—`õD4Km”x¯¿9©û3|{¨{ŸOjŒïùÏàˆ`•èß-à²Z­3 ðx²ß£Éê‹î …á™®8ŠÚÐ^Ìhf„¡Á²uÔU%ÍD…/{@tk³ ñ°sUÛæ€n:m':¹Ycçô[7C ñý$pÛvpˆ±ëËbh»ç×ïOt|12Ÿ°rlû~|ýñÕ‡·ïo:¨ZVçG 3u×ÜZ° DV-k_æ]±.{gXwíîví¼zñêûïíÔ©Ûö˜á¬ ÏéF»<‘›©V›ôž¬¸ê+Ädä~ ³ªíFÂL1žb†b…]£6àZNCŒTOúî¥$A† 6áà{‘Ÿ‰÷ûj³E~kX¢ð4¼•Ä™ö¢—ª‡ïKçw5H# ù~”‘Y”aÜCZ2w(ªvEnÞ¬`VØ ¡Ð{“íY oPóM+-Dñ*#ÌÂá®´C/IR6ÝóbmvY&L!磽Rm¯W£x)xEz(ˆ&¬;ëÑ´†EÆMps()!µfŽ,@ü,ã ”ë|FÜQûßÓ|Dˆ8ê|íæÍÒ©†Þéw7–ñ/Ž‚´Ÿš„#ã‚$~Ê$õÃõÌÙW°Ê’ 23…”Šª’,GV.èë]IÆ2.:RògÓöƒ²# FKø2c¶]û/ÈÙOGnÔK­l¦‹Öu¬YE®ÙLî°.a„.}¶rÿBFfȨ=ÝkH- "êtÞ’~ÏìúÒùDÏf‘Ís>é„H¡!^màh,æîÅ…³²ñ!±W´R|x¹.IË&±géà3‰ÒFªë¢3Ý OËá W¤SER(«(Ç\È©#ÒAÆRèé˜w{+ P¢©7›GšT?sß®œ‡vç5vö4ÉÉ| ”gh)US¥ # Ig;h­rÎÅ=‹rëÓQ}…åoÅ,­?h%ydÚ¬+®ÊÔ}%›N– e&½ßË%uŠà ¾ ’\GhîìŒTh®˜adf¹¦úR.>+Y”.ÖCº°¼BÍxÂÝÕ Ä’Öά)Žšùbµu‹Ø+Öи¤kÑ• ßKçæÁùó»8çã6rFÌЛef «¹Í–’T‹+wwN ~Þß7BR®†¸+ùõm5ˆ¯…Í|Ô¬LÊê\M¥CÑû§“A² TË1Ôâ“R‡"OÍÍ Â×÷À¤v;EþH:ðWYê/¦•vH¸]éE„#Š—»¢´ŠÕ'Ét¡NãO4оPÆ‘N• F}qíZÖ n"óQ~rÏ‚Ñá‰&”}Û)ÏtU÷Bkú G)"`Ï;àÒº•ÅREÚªûFÚ1¤\ÛO(„ëúY$ ªnd|„6rÆZ¤Â3™äš\ð(›ê ÁÐpÆí{+ Ss&!e†p&¹ö JX_Xõ¿íH¯›./îÄ$7 "·$máý{Bè¥x2¦I&±,ÜbÕµǿģ¶’Ø-¹5Ú©ZÚï’$ºtn)ôÅ7ž\5ež)t‹uÕ+†”ˆ8ƒä›JÃàÀDé ¹õÒ®qd¸_¹-›eï4àÁÛFø}µk ðKçFx;HA‡ î‰BóÝ _¸—) ×;b\ ¯ó5m(;ó^Ù›"+÷OKÅÅH•ð).f¦©Fµ˜+¢³ÇÔöb&sp[——Àÿ¦ßû¡¡–QÝ®10oß É‚Ë“ÇQ(efû‡IÍMGú3u^¬ƒ–tè$⇅J~ƒxÐ{h6y£ª˜Þ'àHo }…]t£ˆ™òÞÈáè±ÕN&²"ùC`®~0ƒ5LÒÓƒ ÿàÇ 5…‘ÈIÈv‰T 4ŠP& Bõ†¨*µzGj°šRP"O(Pfe¿ÞÈx*À˜/zŠ7oÕ*µç¨v‹Ó¬!>ØE7,Î]ÓšŠ±GÜ´äÛrT•õ#”²t|;Qä—8.ìºÙ èë ˆD'>YÁÒ]“SXçuõ?åRöÆ1U‚x´°Ìä+b—·H €®ð˜0ô Àá(6·yß“u[(edŠ@ œ:ñܦ‰‹ü¦–`S?Ì8UC©êe¿é*Ñ¿5—’;ú©—E¡ÅlX8ê ¯c\’¬P[`m&~vê¶ xk±.‹;ze“ßi"£RüÛL ËÞ†ê( MÉHüíºRŽ&E?càÌ—eŒ. |¾ÍUÉ213h;I¢00<”ên¾ÒjÜ‹Y#ˆ(ºžøQ4v"ÑͨÝÈ‹¢ÜR³-šÇ]3t»žþ óuýd¨@-† ÒŸøàa—å¨Î=Žc™DZ£ êGh5•J»eE;æšÈ\šªºÉ»»éѧ&ÒRx…L_àOY—)Äa‹"'ÿ÷[äQ»ëM9&)æQ†žÌº§±Ï'ŽŒÇYUÆ5Ílî[¹·º«‡hšÂ~h·Äжu^5"ãG mL)¹G˜!`3ÞT“‡BnœˆÑ„–gG¢Ira#Ž(H*ÅYá‘F·“r[ž‚ÄZtÅaÈn»ÇëijG„ÜÝ–²ÎÌWDßrŒâyN ê@üºi¯­zÖîpVL£©Np»›™Á"ŠhãÅwW.ÈHY¯d“HÓT{Ä—‰¥i8êû”îFˆÍ®އ¡Yäév˜¢#ÏâBÈÛqZ)g‹f¾=ì­3?” k,Ý®ìÌ/Í]ÉÛv\£Ÿ:ƒÁú”Éëbæ•û³yÀ#ß}ñB]]¥1‘×ß–´We™É¼õ£É<]&¾å|÷bjš[\ÐØB•ŠéØ¢°•ŠRn´•¬B”R5îS DÌ‹Çs„~rü9^ÍïälË:L†7˜ ÜrÌë®DŠ Lε!(k•Jç’¢ž¿]| 3Ô/g ™é3æ.>â;3"¿§Ñ:—VÈí~”Y‡<’2XáL­JÁë~â~¬Ñ*3Ì÷%ã­Íb¶ýv2:`ãô!â’kµ}OœL&e¿+Ö ¯ªö]ÛÜ^žèšCv™³èÇ r»ý^:ûu%'üó ¤âovDª{€Ø›[Æi`•ìæ _¡ ÙáC3‹Nô+]e‰Åãå3)`Þèw35D‰ôìÎ}¨m{ò`œ_eQ¦fàhê© /{u äÎô8Œ¡¬&~x$úqs8‰b{bH×‰ÕNÜ–"/ÇŽLŽjbñÊc‡"÷ÆáØ£ÌRMV¥Ùtï-(Šü|=S<–FÇâfž>ú?5§ñ'Ã~áüÜŒ@j‡.aÝä4œCþˆ¹Ž:—£¾‡›CŠOâFt9ȃ?dKjo¡ŽåÔ€^>iú©Þ X­Š-GRž"ù±*ʼn¬J*T‰Bœ¤^h:ˆÝD:^*P}ª€±&!Gü4VZæÝr”±)êÝ’LâÔ¹¼¼˜ní!’8ÌQCUI}ŸuÛT™¾éÕmˇàørhàÊ}¨:Ü´ ͈Î×`ÒýNóBƒ À[ *[ˆȃÿŒ&”šn>ا‰àW}|žŒ'ë†B¡9Ý—¨½9é8*%óKáü£©>ÏëJ6çÄ4ˆËè é¢Iè#ÌX¬ÿo†Ž³@,èGà¶v`¿ÜÝ:Üg¡ø•nMê\côÍëÅÙßñçÿï ûendstream endobj 6 0 obj 4600 endobj 14 0 obj <> stream xœ•[írÛF²ý¯§˜ÒAׂ_›_޳Þh¯o’k+•[%¥* ŠXƒ-1Ïà<Šßñžžž$³Ù-W™2Ìt÷tŸ>Ý=þ§|)úc>—Û‹¯Þ§â©¿ÄÓÅ?/¤þ¥0Ë­øædôÅýú‚ß‘" EšG~–‹ûí…÷öÝëëû\ÈÔϳ<Ã÷« )?•âþùâÁûùíÝ÷ßþõý£'¯ÅÛº¸–±÷ü¹Y• W¹ÿûE”‡¾ysö8­{¥X+·Q¢WöƒXÑÂ^ѬÄÏôD˜úA¤ÌëU³j8qHóís/Öûf9TmÓ‹aS ¢èJQö»rYu}»®]Ô嶪¥¯_Ïr? Í¢´g¬÷¼ß”âË—ºê‡n_—½hw´¤èÊ]Û ´r)è—¢]‹å¾ëÊfÐ*„0‡Ì2q+C³^³qxRïVX•ëëÜÏó0ɼb_¢«ú¢.µ™nqlxoy!eî§al”ûTÒ&ý"÷Cœ;òcÞÆ«{_¼îµ­°¸3‹“ÃkÚ¡\‰b¡Mç¶Qdq8ÛÆ,z´•wSÎÞ”&*û½†ÇÎÍ€C} “UÃAü^Ø”~%öãq­çµ[K¨a”º°_´{X³jD!žª™Pqà«Tæ'ê¨SÁš~Ü%ôU¢¬#µûnɪªg€0gеíðÞ²]•âs]ŠGþ´ÜTÍX@K¨ ¹ÈIô±—¢êÅHÖ¿ê ¥Ÿdv¿_7Õpc´`AeŒ_»8ó³Œw½ºÅ(sóFÓQ2ö2Z;(VFThk­`x-¥ÀÏéyZ%ö¥J$‡ÝÔ$xÄúEÑ!höuÑq´æä==„ÛÓÞݾ¡MiÄÚSWl'ªÓ·Zy!ìè£òNþÌ÷\æF¹ŠfÖßæ¾ 3çæV^޶mĆ(fþ‘(_å¤ô½©5¤´î¹ïÉ_¾-­”Ÿ%FÝÇë JÝ+˜fQ,?┌q ê”}.O8~»rUõ»º8À鬴ÀdE˜C»×º÷›–•S ‡kž-m„µ£jäk¼@IG¥=Ç¡èªZ_‡±yæ­KÂ<±îÚ-6lñp'èäTŒb!,Â.F‹ïË»†Œsoí„öõó2An¸‡DƒÜqEæN‚Á¾I®-`2 |ª}µÝ!þ†¶­o€ÅŠ 2´¢o·%åU±…”€x"ƒïyA{œÈjOŠv$¯<Þ2cð6{>_î´úm÷±‹ƒXµ´#‹Á:GA‚ôè⫵à4`½]i‚~©ø£[¹lªß k½þcµÛÑËvKŠXo–Þ£MÃ0ñS›iu“sh--ß@Qß“sÔmû‘¾‚£é×)a„G…Æ0ä(ØÇiN0Bö&~¨’TŸÂªŠEÑöí.h‘lår°ŽûžX§Z…Ýä¿4¹J’™É+ò¿}O&®°­ÿþõµ„µò,ñî?h‹ÜÝP7âyS-7¢¨ûVì{#¿ÌSdw9ʧ¯o\Ç#Éåä(èÍ4ÄqĹͯ¿6žŽ/ŒüqêGIèØ­oä‡%‘x•x/ŶjJæË(áöyŽ pr{,Š:[ÂÐðç¡ìô•ýPáÈJM8C•ø‘rÚz?5uõÑ }¬Á-„µ3G–Êax{šÇ3Ž"°`û=ÙŸ»ºj†ñ´\^ÍV%Pq졞f§Ü‚áÒGCž÷{ñÔ3H-ë¢yº! Í†Öh«¶ìµm¾z/KIœˆC_ í2a¬1" Í8—¾™cs|‘‰U1Ù“?•Ó|šÀ>éÄ üÌrYöÚèUc:V*zË߈ÕL¸P:W³Ë#W •»'iµÈ®ÖòÁÅôYѦƒn5õ†,³àH;En§á°ƒÿ>“[÷eÑ1ë!4ùݧ}Ý”]±¨êj¨ˆ;wÖY)3œ8WÉV2özÍ«ç .+ÓhžRáyÙ)™{ðêö:-‰rå­;íAZ˜QfÔ¼K$q#î.šw)p Ñƒ˜šæ~;_È¢iþy®êZ4%9FÑU\X¬öË0jÉUÆ6Ž‘h\t&¬tEZäð€[ Lm“Sóx|jT?:eýzz€a9.Ûœ ÅŸ~2«}²¨jãËáäpÌñÃÿ¹þ™èÈ~„hH"‹–ÞáÓŒ@ÆVó8Vš ã‹ôri ôJ&Á9Ÿ`‚±Ô7¦jHÁid>yXMO‡¸å¡cµÁÊ )5¼rô†ˆ…(ždº06YXCrq-u½–zû åZ«71¿.~t`žfVÝÔ“åÊw°¨ƒ$y€y€Äm׈¡ÁS¥GO™z§û·6§*GuÀ(>rš4>3Íâ:„å•ôÊå$d”e.Úí®"úþ ž…Âwq`¢–Ól4["3wjoŒ’?N]øT•Ì"ÓÈ{.»+î hfMû¢ÖŠlÑãõc‚¢Œª0“¥è…ÍÆŠj‡[VãšPni®˜›=ÓÜÒÄFèð4ƒA' j)ä@À÷ÙeEäo[,;,X~n*î7PP±§¶«;C^†Š “Ú¶ Ö}»Û€ ƒ‚Py>è´{”½ˆóct$‰K_“,XÆôe·èÚý\‡|Ç·Ék¬tϱii³ÁÉ¡öz_“ñ®(—õt~#Þ=P_Åè‹ê6QÄtrŠúЧÓ"ŸJŠO°wT Ïj Æ;˜å6\æmí÷{’ ¿lVZïuƒrü;1˜CdÛ‚Ñç)‰ÆüÆ ·Lʬ긅€òT&ÉI%ç¨Õ”Hå5Ã$‚Pšç2·KNDçIÀFɉæITŒ/L)ÚŽ»AH%IžH•ž“ªb©2ÔjöGé «‰€€3%mòpaá %ržsˆacìšÈˆ£Ý¢Êc+>‰¹P€ÃÐñ)¯ØÏjé<ɬãõ{ð‡7_½yõŠ+t0³S¹`-««òå|…rƒCeÓÃ;¯¿æBÂVÆ ,ð·ßë+_Eã›éœÂ·'gC ]xÁŵžYî+P‡IOIú±ÓÿÁ£.äç%©Æ‚¬Ê¾êJÿú6¦>_z?o€³bµª¨Ôkom5¦4¼¹ž % à5µÕú#öûq0w˜3íˆZc¹òe 7 ‹{7¿%FèNôy¦ª \ m×R'¡Ý•ÙŽÀqWu\*÷ž¨„dÛè¼ü›y(‰Ù%–ÔæAdð"$Œ ñMÌ3S‡bMPºø~1NÂÛÐEíCëdç+Õ\¦Óä²ëÊ~¿µ²k-¨gâ|h§Ë9ÓŽ‘ ‹‹2+ÆabüÔD˜-ò aÊ¥©)÷S‡ù¨¸ô——7ø{£ÿ.—æc§?wOø·ñ3?›&õUÀ±ÙcidÄ•ØU(Ö¯µ'µ '­Ô•~ÏÅ,ŒG«2”¡ ²4ËåÜ*W\ËS/¬\s Bé‰FØ.ÚºZjzÌá`Þ&ƒ°5•l– ÒsvÒ²nõ¯”îOÑXg¾šíÂ~f²ñü¹› ft÷R÷ ȵ@|n‹î`û*°õÐë–e)n¿º¾Ù¶à#æd ”ÒÕ€‰Ùë„t)åRYd'> tÜ/àúŸ$¾EÒôuw§}jÏrÉRCò¨¯`Oe˜yZjùü¦´5Ž*£4Í9ŽšývAØË¸Ñ4ƒ¼Üë7&ñ½)ä˜Ç>/Å—ÚvŽuß~õJªûé¶_’3€¿Q£¬×³6MÁhòè}x÷Ãr¸¦0e•YÄIã 4-‹/^Ö®‚ÈÆïrâÌž&¦©fö¦Mø`›¶¹]ÔEóñFÿhú¤Z*²vŠš.ÎܺgmN¢èâØáŒÍµ°¹3º˜ÛUæËb¹qýú(Mº¾ãÀ÷ï`A¨Œq¾4¨ã\BEiû ³e©i4RvÇUx†vTæ)?”¨óŠÍÈ#ØÞ•î$4Ò¯8nÆD!’ÒI7"Uò ©¨m6ÓoftÒΘÚoÈGº®Cô ìàhë8Jœpß3;?xõ£§• ²Ð“¬wçÞaB~Á¤¢(²Ë•knÒ'ã)™µ)å%¨ÄÔ"qùü2Û;…ƒç6dƒ‡©^A*¥›^™Õä/"¿äø ?S³ŠãwkRV¡ÏàØ•PÄDÇfÈ’3£Í:˜ø²æá£/“CÑ_»²E†€ÓM%u¡²ãÜù]åìú0Ù6Ÿo«1$.TÓWÔ™p™)ØË`'[Há8¹~6ÀHô%Ÿ¶r¤ëIœñÉøX‚•…ê´ø;ãäÍÜÉuYdDZ mÒô&e‘´ÜΕVܶ#’2öºzôQÔ‘« =»‚UÌÃhö•ÀÚ“xEºÙú¨Ê¹ ‰t äyä½ÚÌÊØq8j(Õ~k³é©]}(7Pÿ‘$Þ"Ãx7ůF¸hVÇíJ¬iÚ»± Zc¤ïúJP#387¯‡àíW¿ÀCî Gé¥ö2;ò|žÅäQa\ÌOÀ);«]@§2‰©ÛÌÊq•¨‰„léêiÃ´ÆÆN”²…™B¯Œü:j ëŽìeØ%,køÏ8jÿ€ë›EÉGM¬Üû% piüø2‰Œá¤ñ¦öùo›ö›IÉ@šR繡*¿ê¹‰ªlœóòøÀ y–½§íŠÍ‰Ù’Ì)ÖCŸd‚5v²»Ñw)>9z[Ô{P¥-²Iµ«+¦^2¹«ŠÇâ*¡_ñ/ #Ýâ(ž’ ˜u$¼»51cfØÚ?-t§iozR$ß;˜4æ)º6L Þ[Maøê"讋»tgüø kÞa¿£j·×\’»sÚÈÕSÓvå¥iZÌ15 `Ö4²ëff]éŠ{}£S†t&ž_ÎÉ]ûw”‹I¨æžãŒ¼7” ;ÓÑodF×e¿ìªÅ™kPqì'*ù3Ïõˆ*O obŽ™1©e@+Žcê\ÙB§Ú>íµ¯©ªãHyg^Oš ×Qõ÷Ú…þ1 r¯¬&€ kç®n–õžÜË^OÒÒ²½TJã—̰æÁƒVæÒI¹úzVéÉ+=sÒS_¾0›ƒ$Í⓹ZÊWñ9¶ µ ä²Ìk—ód(çEyljg0ƧRK¡«¬$ß bmg[ô•ͪçéIµ% ·`Ð~OhXhZ¨+Ýhþ‹øþd¾‚²&£çÞÛ†{ÚÓQa1VúÓÕÁ¦ ž¦‘®L®˜ìBæxLÑäÎWGÈõ“yqn#S™ÅùŒ%1C¢F"M“¦õ¡¾¬Ð¶5»´¹¤sÿ_º1f£ã}®¤ ^ÝÛâoßÿ$þöã;Ôe˲|r"`^ªöCjÕÅ i žü¾²þùÛ@šußžMÊñ&E LòЗu̾¢bo,™AÚÍìIÅXïkÓ»´µnß®¾D’S;C—Ò4ÒÅþ*) ó'™¥Ž}þ@Ë}àå¾µƒ#ÔËN±îJ»Ù9…±SFfæ*Òñ¶æ|ÞÒËœ€ÔO¥'ß2ö£vŠÃÄ6‰¹$G7mkD‰û¢9 %ó£måÈÄîLƒ¬i¤•0 ÖÕäU=¬q|¦Ÿd W ÉB{òWïsA÷ˆbº?r+‰€ÇâùêÏ#w„™»Uð'ýù-XÊ`†{º “B¶ðî¶ÅÍ94á¥IÅq3^â“ÜÍLbåòù¬1–MFôFQê¤pW¼ŸdïéÅÇ8LÇèÉ®pô•>{¡”»›/‡ß~£{¶$%AÜ”>(„&¨t=*µ¹Cšu!ñÄF¹Ÿ¹š}Ü:”Íän¥>ê$Æ1„ã³6kÝ‹±ÌêàÆÁrC Ž/*èbÎΪ>¿PŒoqNk/÷ýktà¸&xeÖ0·îÆZPåúf"{Æ[{1”iAîÚMçî1JU—mrC¢(áû¡í*ÞÞiƒÄÉôZmmo’àÛc¨(zš•8ﺺŽM߸+í¸WüÔT/·t}ßô!BZÌ Á,γ±v臘n{åïªfÿr£¡÷›ßêAÄÿË>ˆÿcû:jK8ò±–¹íwÇÕÃÔOuO—ø~afsHñwd£F)w‰µfín3y-,±Ò-¥1¢²Ôí¾^é@±@>â‘ø‚j0× ó˜Ê¡gýÿ"4êgÝ>mdR,Û’c³åy$K]#›w5X|K;‰F“÷«ÎÄÿ¢±ffå@·ÁúNǺ5=»3N™ÛF¾¬àiCEíkÛÝŸÿæ4’øïËÖ#¢ÅÆwÑSåýZƒ™]ÍüLBd{nWÿpº¡Ö“Ê=€êÒU¨Ž”tW²+gÓ‹Ù6ꎒpä/ærj‚âe¾â˜<3h¤«rüllRØYèB¼qžìŸêÅ]1ê&ùCúæ¯÷ÿ‹?ÿYÐÐendstream endobj 15 0 obj 5276 endobj 19 0 obj <> stream xœZÛ’ÛÆ}߯˜·]Kƒ;ìʃcK‰R²äHërª´©H ID @ã"jSù„ͧìGåò9==”¹ô`‰º{úrútž+…GÌ·Ç«'¯±ï®<±¿úíJê‡Âüg{¼Å )ýp»»âo¤H|‘d›fâöxå<{ñýêöW2q³4KñÂmq%ƒÐM¤¸=_½u~}öüåO_ß9òn%žUùJFÎù¡.T+èÓ¿ßþå*È|×|¹x䮃 u“L¬ƒ˜ž{,ôßs1ïÿùÏ{ñ/Q©®ÓòèݵŸB&}áÆ2¢¯œï{ÑÊNœš²îoÄ}3ˆsYU¢SJä¢Ê[}?qÃ(bkèÛ˜5‡ãêšPuß–ªsWë(–x'tžæÛƒþù^òâ*UçGuƒ¿n›ª©é/UYRøÜ®$ñÛ+? Ý0]p““!=X‡¾t³0ké³AAʇiËî=N¬]„pFZLè¦Q$˜ú!<›ê‡™ë#>!?|ëTåÊOS7òR§Þhk´B¨ oÑæÛ÷&¸Rzþø­ê;q眪U"ðhPâØt½ «×ó’À¹¿[éãç½Ò dá±½oÚû…}ЧVóMo}º2GÃh"¿RHën¨·}©Ý[PV¨nÛ–'ú ¯hïøa¦ˆ=³Ym’J­Ö‡ø,3Òïÿ½p¨ Ü MÊÏÖ$)ÝÈúÃcu®;œŽÈ±ú=ûD¼¤tø0TµjóMY•½>wÄ_AV¸~4ºÅ}6)™+¯tN$®[Þ1ýë¦=æUu/º¦E`6÷âs¹!é†~´È  ³øœðÕèÍʧ`†™s.ë½> /צÎÑЛe§ÇUï(äBÙ«c'Ú®ÿN”;]n‡|a²>ðm©æÛðÛä„ÐG'LâË#„¢/©ÀÊþš#%Ú¡Q©rŒhwšG-Œ½lÆm›M¾û6dt߈®ÏÛ^œW- "§ißÓÙ‘PöøÓñ(ë¶MÝ—õÀI¾– Ò-Ì&ŸÄ~ÄŠ¼Vi?´²sèuã G`? í9;JkÏü8uòZUÑ‘µEÙªüž~$[:`X€u8jMµ}^Ö6´E£»ƒ$q“E€üÏ‚C³ P{{˜aƒòP ÜV¡çܰšÐƒã£ñÜÒõPU¬¡SÚðÇÇcY_de»Q”¤FEôå…QdÓ,A’š@š×¡HW½+žë²27”£`¸ôÚàXjÑm²0¶W}OQÎk¡ˆ)?’éÅ”Cø±oó¦-Ê:ÐOý`·’ž“W8è©éʾ\ú]†Ïÿä駇ì6Ó!áÿ4ÓXmsòãýmˆÜ–·%²—½zh»é<õ]Ì!f'ª¦AR”ïMäéÙ–Šn=j)æêcé[ì«÷ªm†Îâ­áîFØà> £.å¥:6ËÆ¤±,+/K‚±ÒÛIa”lßåWÐkNÕò Õ 4u±$®ŸµR4õ5÷´î !®g—øp°?%¥”ì‘ •Žò%óUÛ6­À‰º|H9U*ÇÁˆÍv8¢±w¢Ðâs ì$úÉkébäé_ÛRgÒµZvu,µ«£˜ ÊFôgã¢Ð$ úÐèïµtÎÌFì?éH ~;1¤ÀæÑtN@Ô'{|úH`Å” A½pôŠïz:½_êò£øó+m4èܬÖ½]i‚ÆÎ+íë'¯a«9=75îÿ°oFÎ,åÐ÷§oŸ<9ŸÏ«8$| ·‘P $ŠwÛŸtä9µ>µÍ¾ÍÝ¥>$®QþïRê{Ö ó^ÌRÓAK§Sý>ÕëeåǶª8/χé€-ÝùP‚|€MÊzGM™YH-Î&%Xº¥»œµ1ñÔÈùÄ瘽ª·Jg6¢eìîuŠâ+ÔùQwœYö–†Én\ñOwu­2õlOO|ÃÅ_m·y£4] ¯Žh$g€NÙ^Ns}üQ˜E•(d šCÎ}W6 ZÐÆ`”%>Œ“ìí0ä²põ^d1¦XS¦®†c½À°cn°ËãšA½gÓ ª[6K,¢0æšoɸœÛh­FQšG©ØvqÞÎùGâE£Š¦ @P]}½øøžÅ#ƒúO5{Q:>ÀpÐÖ¡:ÈÀ夼Hª{Õ‡-wL»T;plDeI©t2?q8p@R ^#&äM@ñ#ËyRó&wõ€ÍÙ;£4Õ«›x9­kŽ–ÐÚóóø"FL˜ž_Ä2±sƒÎ»|LeæìÚâ0c0@„: zê<±Ëº±ÿÀ»6 µe¹¦£ Þw†¬að¯vª.¨õ h&;ªëv¨Ó¾f¡7-‰yë<ù†gV«PÊý­(÷5Õù7O B,¾A¦¾·üM©“n[b×6GfÔ£,2g8áplëП†~ )òc‹ †ÒMýĶJóêeLešXâ<Škj.v-¬ªBì±Á §£Ñ©¼®QÏ0 CPevÊ”ÅÇ(a[PW΢Ɯ%“Nî*5ŽŒ˜ê× Š0¯ÚºY–¯OÓ?X”- Z›£ L¨ Bjud/8|ÛÔ{$ÛCÕåµúÀ0ÈÒ-˶{Ĥ0ïìÊÅ(g±u¡Ÿ1i‘o‘ЍŒRÎ%á)z¶ÌF£ŸñÀF,j§ÍÀ¦3z„öã…iÒóh‘2×ÙôâOüÈá°õ4ò ™ÏØ9>H‡—-êÂy|4¯3Q»© ’ØñPõ³ âT¶£Êî[­!òyY6%ýb#cUéÕÌ´“á^÷÷€ ùf$›;ªî·XéSl{%Î ýDO=ãb!ˆÀ)£IŒeëBeß´<§YQ€ UˆâbF’™.¹ú§c2MH'ª^Tê‘DÿGÎiªøfŽšWû€ªÖ‡ó#øegÚzD|(*¾K¡SL»íúÒkQ‰oœVÖÛjÐL„3 (M/ %zŽ'¢ùžè—Ž'ƒÙ­IT-Kãù2QÄÛVQþ|ûÓ Œ#ÚYä Èèƒq-Ã`&îhøÛ á‰AlŸz—ˆ}jiü‚^3Üvw+¢ùžçÜr«Öj@>Q(Í«xÓ³!£ h‡1™àT;¯P˜„+×°Ç œÂÍ"¢‹í óêçÛç¯^¾¹`­W¾©ÀÖE¦òÎo­ÿ˜&R"o0db„:iÔ€G{5´Ñ ¡m*4=¸Íß9×vòÐñ73öh†g|3áu ±ÛžAyŸßó[p ÉÐj̉‘ð(ÓX'‘Ù¼ÍpØ›Í$‹›E—““»øIµôOÒS•èÒH>LRd¾ÎܵÌ@½¿îÖ(™§r7œxú#¥šîæ-ZÔ=|òñ}¨µ/õÓŸ_½yþ7äÛó®”Hn„ïÉ@~›a?æðOiÒ͆¾»U¾"ò/ÓÀéŠÅÈóÂ`²Üìüfñ¸0Éw}™Îºuj0šN÷æÓMË(K‡v+¯˜ï* ’œ9ŠHÐOy=äÕˆÖ i³Y!®ŒíëÝ;4†©}½u~6óûVϳY;{]dâ gBÑFß¿Òq×;æÞS8×ù¼®";SŒSu–Ô&Þ‘ò’J;ªÑPü†KA³ŽÄ »{(:“¶—îY‡`rb_t‘ÇWÐg”¼@ø|™êüÑççh¤­Þ²Ñj+¶Ð‘o»©=彑‡¼,6 ¬8‘SÕK³ 5$œŒF?‰žº7» zÜ6{· ÚǼ3— >f¾1ÎïÖkZPýფ¨säÕ xMäó…Ðö*–:„c|šy|fse»ð)<‰–|Õ‘Ò•†ÿjKÌæ.˜G‹MbwÔ î4ŸÁ_o0réÏÒÙG‚9#ÆÊ'çèý/<”oƒޱ„»!švA{ÂK4¡Î³€ºu¹å«ù¾6ë5ŠÿrŒu´Ußé‹öÆÊVÌÁ 6nx³ÑTìa/0­°ä3ÖéeÕï)F—Ë*³ê™:ÿóþª מ\ù *ͽÇ(×TI±g”¼943ö ì ìfÉ9‹‚´÷K´^~“p4¥K~7³6ÃLªýhî[ØôÖÌÌ´ ­¹´ê­6ËN˜Ô+hh†.rôË£XÈHX¨°•Ýc},ûnN›´=P0yîñ‘z|;û©Rbjú±RNÛ²§oÞÛ«UwÚ4îÚr¿‡-»¡Õ tfO~,k&A$¨KT;®ä$¢Â˜t2·ªÿìXk¾š=3;K¼gÒÞq9¤Ü0{oHÁâãjÝg}ÐÖTwÎD¡É ?üúÔ ª½s:º#-w"?ªrKª/M1àôùfÝ©S®ç͆ÁÓ½T3bíˉÎ1X3‡Êõ¦±<æm hàp„SÓ“rÚÄ€?\®õy”Åðí¢¡Ú³ÅŒà/ñé4‰·ÊTñgo)í—žF¡Äñg¼Ï¤Q.ú"Id´¦[{;k§rF[ÌDÁΧΥ÷VÝImˇ-ð¤Pzé¹Q¼f³Û!½fÃá˜NRi¬óü@‡ô¿œÌ uƒãNb!3/ÖÎÓè,é¹™›9fœP¡ž(|à…lsÙÑu ÅœØ Ré ën¨áêa÷ñÇñµhDݘ+JLž>/n¡cè@‘ÄXoþƒ˜¥ƒ‹ÄÚÞ‘ù-sèñÿ»f¶3£í‰ z }ffEL³et9ÕñÊ—/XL&#¼;W iÞ™Ëû¢0/_z¾¢æÀ>¨ª`ŒZg*ÀB¾> stream xœYÛ’ÛÆ}߯˜Ú<L-g1¸#ª<È–+år{Sq•è*a!9.4.Eƒò)þÇœž rå8¥Ià`¦§/çœnüÌ|.˜Oìßessÿ}ÊvÃÏv7?ßý#³• ûê 2zð°½1ï–,ÍCžå졹ñÞ~ûjõðï‘ò<Ë3,x¨nDñT°‡ÓÍ{ï_oß}÷úÍ÷OlVìm]¬Dì>·•ì½úÓÃ_oÂ<àöÍ‹å´ïý÷¹=~æ1Os¶ZéÓöÞ²–å¨Ú{׎#{]Œ½¶­{ïýúkQ×Ý*‡‘½S­ÚúÜùj‰oE+é}ž¤!{(é^qè ûói¤}ýƒY¢ŸÃŸ´öì%;’u[6œ›Ç®V%£ã†—¬íúvœ¯~`E/ÙðQ²âúä8åAæ|ݵ/œ=øiƒ`̸Wë£êZZ½EÆC?s†qlb¥¶ìÜ_¬bŸû~z0­h‹úü 9¸ì*ÉϬ÷²Ç…Šq,ÊäÖV”Z]#mÉæq:ÝcÒdÔnE[ð ¤ð˜ Yª¢Ö>χEÂVràm?ϼ'UÊÅŠ'ùŽß飽{¬{Aµ•O‡:&ÂO÷¿È¾£LþúO›MsÆã–œ•!0ÂÖ/ÒÌ®Þn6e×€D8#?ÐÂeÆ×û¾÷´‹Xžgñ“¶+ ¹ŸDb~ÑdƒêŒó()³ïL>tƒHâP¯ üÂŽ$øÉwFHxi»âø"νqå–¥&M­ƒ \iym» ÈÞ õº †«º±RýsŽ›395§¾iGÜkä®WˆÇiß¡žÛ‚òíQNi³S­©š[~‹‹AR`¤˜#5 ôr¢5µéÉꎡJ“]tO„tGZü™ÎÎí½.é,¶ë´‰‹ióØ…£ìÚ±ïjP†2ˆêóÀ L˜YÐ? ”3ÊÐQºô<O5 uYÌwj¼§äÃS{¿YÝÑaŸwÇ^cî@¨_éC p‚Ÿeˆ½¹Ûò+M³Œ(ÚvZœè5×Ú$æA®Ãæ½3~åì5»Kò½U– —¨Ä’Y¯²Rƒf?dºÕ8iJ±]¬NŒ‹OÏë¥IêG¹G‰ãÇ… Oàak˜‹ÌKŒbJx&_PLz‰ƒù½´Õð8™Åš«’¿[ðØ¡ËýŸÇ„oEþBŒŰF§ mºö\ïéÖƒ}ÝÆ¿ÚÀNJà··tA‹Àâ“ÈÀÀDâ ôj¥¡-]MíÝEÞ±G#ª}¨`ÞÅ`˜½kQ†Ø^ê"% }éê+ª ›cߦ« ­¬Ý~D0ê+!íȬºàæ™,‚ü‚›‰uÅs~nËêÅj ÝR'?|dÁÌÌúü|pËÀi 0#îTà’e·kä±Udh¥¶Î £rêEÌQÛí¢¬ãÌ÷]_¡•ÑÄ6:óÀHQº w‹1Š¡ž¨€ŽÿËwÿd·Ó‘¶PhfNn×îÇØŠÈwpì.1-W@óÞƒŒj‰ ½Óí»¶è+z·xˆ(Þ|ôsCÒö,è2ŽÜ²v¼_\6¸ÈØÕ¸(±QãO·D‹Ô‹+ ¢¨àýœN†#¨À8̇Òx©‡’ƒŽS ÷ÀJ'0¥D‡Z!rÐV’šD4;^¿$é\,—û¢ÝÁº·?a ¶R}›L $Tú;ïµ£)¹&#9”%Um9DôΧ%tù"uñ&á6(ý³ÎRƒÆ$½‚±2ͦy6%8Õ'kÍ#µJWe3#÷Tf)½}Ufï½V­‚4ç)\׎Æ-ºÅØ+ 'x]ø´°‚;„¢%­4õL‰o¢ ¯£SIèPº+°r‚´µa 2‡çuŸˆ8_Ü!@'•§N%復¦'ÔóäG²1 ݔǛ5(*l—F/0u$]Ú"ïL§gPØÜð¤ÅOCœ¶Ó©½œ0z'[Ù£\¤)½÷¹,ÅèôSá’ç«©C±m`–LmàiN,HÕ8Yô‡lªÚܨ¨Ît ­tŠp’’ÞÉR`ÄÓ4_ r’Í=ßU¢èI’쎓ßÊ“Ê.üT”£QÓyäöDrޚܒñ Êüx2„ ™DÅñpý=Ô‡–­Ð'ꊋ¢Fì¡ÙäçOFF™fægù‚¯Dnz|G•žòP ®È·Ù°§³{[Šœ¹ÎžÞ5Éö7¢Îk*Irë ͦáË™„P£ÂÝȰ ÄOQ–ò@$¾ñˆ(.p¥²€r?Êé5 @r{¿ žš'1ž5ä’ÏónÛ-ó.õ'ÌÎÒÀêâ,jf?çÍêåoÔiž/Gu(Há µ`Õ\ªÄŽÂEß“9"™Ïµ3>Ýûê n¹£VÑ´Q!µŠSÂS‚ËLé­ãŒ&C‘ ‹–2º7þúȲe忦]Y{ˆ ì=@$8Üâ“,͘ªid¥p6.»Ë2‚E"œ4f÷%ÌNFíÌÄèŽÖ^mÇD¸¢ÞMÁ&|XH^³dÚ ›;-Ñ\¯Ó5%Îv)ÂP–uÁ’ApÙJ¸aEC´:0ô òšM¢ÿg b¨ëº'!•˜¦ŒT±ÃóõŸŽ½Vá.Η“V¨qECXm·QÒßâá;0ô,Œ§Æà‡½´Æ–`gyM£§Éƒ4IžDÊ‘í±Õ +u»Ç‘’L·jÛ¾kHº ª²@ßw»¾hlû¢eÅ qP\}é²Ð§©Ã®Æ_@ÕzzQÅ^ç/PÕ_2ÁµKÃ<å”Ç‹ÆåÂmedž})ha8­¾nv2Šõ¤s¼:9¦yÎEk³nž·6b6ýÇËîl‘…s#å¹»äDÕÖ«á#»rgP¯ý¬m ·¿èQÂ$?𺷳KClæ§3äE¨›|PQ+ƒ ‘y™JFËGˆ2 >Pùà ½xžGÂûÐvÚÔúIEÞ‹ÍŠ’9ÖË´ˆR-0Õšâ“mœÂAˆ®g6îòØQoö’¹)ŽŠSK€,žµ±¨ƒe6l‘›ƒAj™¨}ÿ‹…¼v¿,ZÖ·—‘ 'œŽB;îyÝ¡['e=¡­£Z™a~'A&[O{9ÏW© “µ‘ž˜æïƒi2-yh¹#?š`™aЂ´€~|ÒQ#Ië¨7"¸µ9¡­çÌ‘qœ¡ \èÕ`bc×kªÊfªÇÅ=p,t‚ËÙ`±‚>Aß™eó;™&ø¸Cš,3‡¡€Ñâ zÚc WÌàpxdßueS£úôà”TÀI‘Ïß•ÓGCC@‚€"4xIÈ A=*ý…Èc–¤&Ã̼ÈãvQŒ ç–‹š£íþPÉÏh(‘êG²˜²Ÿ–d{ßwû¹L¢y´ M6„È.…ûfBwsñ»Ž Ú‘ÍY¦o¶"qߢÝL#Ô×òc>õú×WÇ  Üõ¯Q> stream xœXÛr7}çW ô¢a•0÷Úʃc[ål9v"3•i« “ 9Þá ÍEéœOÑ?îis!-oRzÄÁôåôéÓ ~e!,¤ÿ{±¼¸Éغ„l=ù:ö!ó¿[öórú`¾š¸wË$ËŠˆç›o'Áõ»—Óù—‰Èx‘9Ì—Å<l~œÜ^ÿòþõ››»@ÜMÙu¥¦" Žßê¥Þ3zõ?óO¢BrÿæÉq²ûâ¦ðîgQ«›E©=ùôTk:1£l拉\&Þʽ}ÒÇ¢"݃Û`_®ëf?9E"m˜E!O(ú™H Y˜ÕÎ{—<œ:Óï{§ ™‚Ç"”'~%Oœg™÷žá¸)ç©…7L¥Y«‡}iYÙ¶Ý^±S_€)ù'¾nƒºœÊ¸àE+cS´Ž‘u^ô6?öqãKû±f’0¦€Õ=0jaŠQB·ªÙ§i!‘Ÿ,êúÒ†â=Æ¢—ËÁPÈóÞPPîõ”'ÈGÞ þ @î5+Gyˆ˜'iQx µZ ¶‘|ÞÛn¶[]~N17f3™;Ü‚dà Q;N½Ö»ŸaB^Í7"ôïÆIÇá™àafcûí%›AUoþææý™óTòˆŒHØÕÿÜp’C–ÿÈMGdZy‘ÆX8 ?ÔÕ#Ûë]³7lSš–K³aƆPĨ‹ì€éUªñƒaf£ Û*³ØèÿhX@‡ó0,ò`}¨Ôžùÿã"xØíuÛ–MÍvʽ¯ÙoMÁ…maQ% _Ž’’6j÷@òÂ`³ã욎EŸ‰°±þc°Íþ ¶»J_1Óø®2¤•wPž%‘í‹ESUÖe½¶Ig4ObÂàâÕŸo`#¼¸b‡Vƒö–å…HúŽü&ùHd¬îÄ覘ò‹ŠÖ×óáÕx õâhÝ\Ú|S÷ ðv€È%gsTÂ-!Â"#7w¢ÙªÀ_jm¹%?O{:Ø3µÚ¢š ŠDɶø©–­ÈyÃ$›Áï–º¢ŽHfw0($˜bB€$Ñ9Cw-šê°­[;A,ëßáÓWÓËaÓÐgÿqÓØ´x(cM40ýhÐèHÔgžH—9RqîX}Ø~Æü¹ ÕQWeG™~«4«m¶õ’Ue­ýIL®fÅ´Zlˆ ÿÂÙ²…F[% ˜¸O©uAŠˆ§Q7Cž†… áX3µó­·‘öù‘©å’S$ D!˜ïB.ëáÕ»ÀƼomæ³ÎeߨIê›`±Q{µ0îuå^.Û3˘·|:K’tÈ‚¹Ëø¼:TlE}´,M³o]Ç/ ï_Ûz‰µ;½(¿-lqÉ÷;`ŽYmöõ½b0@FÊ­s9É1ðÙ(Êèz¯,{¬ò4È@5MÕ"Õöðm™´¼®{{à[E‰5 Ûj*Â@Ux¼kÚræzÜ{êÊs6N,ƒºI|º5ŒÇaKØœ»H: Ëd¤ö`N™¼ø&Ëä"/Nºx@üªö­Om‘~0W¬äš_ Ù(:žåPа;‹ï;-»¥/^ìƒyXª Êà!J]paÁÃ"s¯'<ñ¯9ûÙçÛé$%ó¢¯Ëq7Ê8ï$L¯lLÅ9Ô1?Ý?×Ãü\ªHí»m3x[šªDSþ “kM·9Êh»l»Q&< áPø}ElœÝŸœïþÊYô²wJyˆTF¸Fuž?ö~ýݺ_û;«_Øäùå+)˜iH8xÙêf5wL!ñ×Ó¬p î/Rвq$ÒƒD_¸{$v÷H»ogº>Š,raÝ)ñò°f cŸâ~+:¾'ôÉ›ùäwüü “Ï¢endstream endobj 31 0 obj 2008 endobj 35 0 obj <> stream xœYÛŽÛF}×Wô›)dÔfwóºAp|A8‹- Ì,Z¢FÜ¡H™—‘g¿Áþ”ùÇ=Õ^æfgᇠÔÍîªS§ªNu>1Ÿ æÓ?ûwsX<³Ëvá³Ëŧ…ЋÌþÙØÏklHè‡õna¾,–,NOR¶>,¼7ï^,×ÿYˆ˜§Iš`Ãz»*à±`ëÓâÜûãÍÛ¼zýþÂKö¦Ì–"ôN_ªmÞ0úôßë_*•Ü~9ÛNç>ŸÚëW*Æ©)[©Hï¼½-ël»/º²h»ŸÌ^áÛÍaÊ“ÁïYuŽÀ}á‹0b+!iÝçA@Æzïp ëö9³§²]SØVTm—c©Þ±¬ÊÊ›ÿÕ%kë¾ÙäìØÔ—Mvh9ݱòáÈz³aÀUì\Êhɧ߅â~â »ÐT8çoìU}Çø@L°ôªº››/B€›¦v™@pö¶Ú%C.Fç´gÚ‘¾êšžl­í-»ðvuÃÚ|Ó7EwÚ[É„|ÓÀo‹Ýî1à#†îx:«¼{íµâ¡J52!W—öËS=BoCë¬à>í†?UyCN“\‚&6ùDhˆÓDæ+:*à¡PöþÆFL赘G*v ž2k\ ×£Á¶ö8Ú&y \8a\`(ßämÈ>ÂÄ %¼M¾”OS_z×EÝ·Xë[D_ó%eÌ¥°¹½m3g[¨ïIy0‚s¤\‚(Y@E‘FÇÆ†³?´Ø•FÖJŸ+»){”~N•O°/ Üi˜@ËöjXŠ¡ÚíG¨ƒž¥+ûh)‘Dj8éíÎp>1ft%&”γRÁêcWÔ+ZÍä/J÷E!4`Ò*ÖNEY²,Õ e[8štÓ̦-æwSAZb ]ïxéJƦÞê"î õ`µ,…¾”€¡Ûg;åMn 5Jd:p¨íêçj¦“¡9æD‚+åìáoM"»èó4wýèÄl¡ÅÉYY£ÔŠn?ñ.HöxeîŽKad¶8Œlà$’Køià8<hSÜpšÜ¡ù€Qr×ÓÈÄT†Ð8΂´i0¤…Ÿ†¦Rï AÊÊËìÛˆ(Ð/o®u£Ãy‘p%.ëŠY¦¦(V³4…wix/U½÷SÐÕð9!à58ܺ2 ù1÷ýI¿ŠR ¤?5p$Pø³Íù3SÊD¢ƒ##D®yœ{ÏŠ¥ W¾òv¦±‰x¦³P GÌ=¹Ù[¤KƒDÚûW’KjvÍÆ¢%"ô/™:à#:{Ȳ—ûþž±²¨@ýþð1ofP¨ÃÔ™³ÍJ!Áê²?TìX·¥ûÛõÕ†þËd^,)åçMÒÜšU[Öí+óYh£„ûra¯œôNN¡Gû1•,¶ |ÛB_ÿëÅoÿ|÷úÃ9‰°4È{¿Pþ%®—’ÊT˜¢rSúQA-EÆÞçìp¤‚}b –ä±4­C‘ý¡‹7²‘\½º0­ÚGÓBq9t²ô‡äšÕ³&ðÀ…-°¡½ÊÙ×y³B'•C~œ¦ ›˜V€&¥±ùÚhžÀ‰ ¥»Ø"C™ü¥A50ä„4TN2ÑÓã0C‰Š¥nSAÊ£±®Ç»‚邺-è¤ãárØ”TR÷0ÁelRR“Ö´£ ¡ˆÒQ‰–º³S%à>wz…f›·ÅeE]³Ó2Å—qyus…>€R« q—ëЉª qŠ÷+C˜Ï€d[ 1´šÊE…ýÐÜ©Ôb·¹‹»Ð £oI ˆ¬ã!¯p²NŸ Dþ¹<».W§Ô©0³¬:÷èÃö ÍO—©*7í<†¥èñ©¡Ó‚›&Å%n8 %&´1õ¯Ï êël½µ$8XÓ!ŽYó >¨¯±2 ±¯Ù \d*Äãº8hDóC¶AhÉÚ‰DI„ú4‘É欙òÂÈÓ¹÷5³÷<ïÛæyÛ,Qð6ÏñYÿyEâÂ^èŠIrǽØ7 ¼ßéš T!¬_>ùÃLk ÛI·EÄëæÆ]5½A{GßRjûns‘·†´lýná]@ßB˜µÅòÙH#åkº|ƒFètÊ œòæbyew¬›Ž¦)2ºYwý]ÝW[¾\… e3ÞÏ7 ín‰àù"^Ö—‹‘/#£E®Š#koë²ØP¹ÒY`8!ÆiÍo_}G¸õ-¼2N¡{¿'ºV™’’2_&Äy M=×ùÓeWSüiŒ”“먞§FäÂÓý‡ÜÔ=ÛdZOÛC™ƒ÷Sfˆ ¡«G¿Ì^[Ƙ•'Ø,æÙ£ß±)PñÉûQì_›ŠZ5Ëìâü‘Ú7Íì½n&fCÅúƒfñòÃôÉCŽ@ݧÆ*LHí„cAø~ÌËÿSl9ÃöMÙo©.ϳ@.w³3¹O™j2ô¡Cuo6õÝÑ ºö²æ •ÞƒT¡7ÙáêFgÝRISÜëÁãß_=`4üÍѱ”×ó˜žå7]Ÿ•ŒžxÊÎäÕÁhK()‡FçƒÏtâ5¯Ÿ󌌡3wuM\„Z§…ºïl2Ù¬U@Ú7g€®à'[câÖê+ ™wÐ?ÂVÀ¥gÕ¾Íw=zøp:>7ÍñcÎŽÅQ¿@ÎÔXFBÔuÙj¨w}£ѯmaÄ«BuTÃÞÚ…š6˜Ð/¶o-·/ÈííF^¨„ÚÛÛúGzí*sRAøÝê ×Y‰L‡i£ÝÈøgËдd¯p›u™›Páî]8äÈ÷PáÃËo‘!  ƒ@ýP `¯?¨Ó³fà:îÃðë¸>Ñ6‘§ª/(šî•K 4ýa  ]ÇÏ6{IhCÍ|kÈ“‚. "úåõzñ;þý?Û9endstream endobj 36 0 obj 2645 endobj 40 0 obj <> stream xœ­ZíŽÛÆý¿O1Õs ‰æ ¿c @ÚØ¨‹ Aì‚` \ŠZ±K‘2IYVÑGX?JÞ±ç·Ú]oÐA²ŠÈÞ¹÷ÜsϽÔGøœôþ[î.^¾KÙíp°Û‹\^dúO¹c½Â }qµ¹Pk8KKóÐÏrvµ»ðÞ|ÿíåÕ?/xêçYžá†«õ#?åìêxqíýüæíß½~÷Áã.Ù›¦¸ä±w¼o×UÏhé¯Wÿ¸sá땳ÛißUȱWÎVaB×µéûîЗ՛K\Ës‘z]É3ï¶bE»fï ¹ë*ðE̮ʋ,ðý€OmÐ…Üç09ÒÚ¶ØÂÄ]}»ÙaÀ^¬ìv;Ú±©ïh‘ðå~\$¾0öV£³]Êa¾°­Ÿ.½|—kÿ­Dû‚áNK·|)´#~ÿýã¡®Fü¤u+ =)à~Ã+çIa8¾­Ç¦F6_Æ~lòôâµåû³]nUöšx¯ò˜N³Ò÷~$äïõçbW·ðPÓ0¿”N÷·ì¾©V·lÜV¬<ô}ÕŽl]÷U9vý‰¶ŽÕå…À¹aL𿳶ñ؇w »ö…r{®–ñÐçÆcï(à‰‰/™J#«}׬Sö c1ÖmؾïÊjêöv)Ý%ÂÌyb)×Ò‰&wʨ‹Ø’<7O å}Ÿ*6Å`Œ§;äu<¹¯†C3âqÌÄéƒ'-B¼a¹"äi×ÁçÏæyæGü±PŠì<”ç  ƒÔ£ÇQ·®7›ÇÑñ* ÿðÄ©ÏÉ·ÅÈŽì~ažÑ’˜–d&vãd-+E6¨M_ë 8/LdªXßUèAOÀ#ÌýÜïI|„~¤vÑ8aW (™–ÜÅ-ž%™Û+‹–ÝTÄ„k6vÆ™´‹DHšøiš‡;7‡{®¶9Éþ&×ÂÅ¡öðµ÷[[]RRiè_¨B`68 Ì&/>M›s<•‚84mÕ7uSµ‚OÁvݺ¾¯Ö*·ÜŽxÍrpÛ»%«7玌a:Ö‘×÷ÇK "Ù_ ¬DG¸jÓw;y䮡$û$kTG^Õ5Ø9OWµð0QCÑÍé_ÕÚ—np²— ¬æSö^»é»/Ær˨ôcîU%²ÆWßšL>&Á„¦DÁdâ£9âÂwC=O`%嗉𓂠§*>ƒÀ¬ZÞ¸9EbʹH!ï@´Ý’ÂØè$+·E{ Ow=+Ökjžf¨wóHk:)Tr­Šý¾©±N:ˆÒ¨-vz5r9%ƒ^¾ãQ;ƒ1¹Ÿ ™“ Ü$X[)²=s|Ä}1Aù$HhÙñ•¢¦º­>³Åß~~£ÿV“T؃4óÊ—OÆÚ†xF¥Î)‘ÅIlƒ=A<cî•g[âtal½ñ Ö<™4ÖסuÔ“°Èã¯Ï¡ ÒnK(Ð!h§0 ðé2!NÉ3ïA. ° °;U·­[ò #¬Ôê[rcËeêfJ7äù§zwæ(A»ØLãiªëp8VоX*„÷ydÕºFŸýØÊSD(Ûvî`w×$63©‡$ùz˜ééiJ|*žÉT2!u²U…¼@Fu_¥–lñÍŸT¨x„vÝöÄSõGÑ·²me¦YQeœÆb©Õ*Îñ¨Ö*¸ÊYhÜoº¦Ñu«f§Êmq˜W}§_“B†D‹ì8´9‹oÊ 3O”u±eêÙÓ}ömÛQ¹s}žÂ^ sÕÒÓ:a\jÁyíêK‘B‚ƇQ~<öºaÒ?!äNˆuÛMB&+gGhlD˜=pö*Rã:—öÑ!èc‚x +z¶+îlÛXQòÝãèIñŽ–Qèé­PXûɡڡë ÕaÝ=>¥ÄñÒ©ï¨.ÐÛäR¿!'²’ÕlaB±B\ÈT×&(‹±ê ÖVÝ=‰io¡ÊJ˜B¢ÌäWĵJ~ÛÊ©L€b€´ZlšÆnPs  ý9Z•«}mpÎS5´ ðÑÔo7aj§/즩¦Ì:nk4Ñû¦(aCUà3—ž)$Pü,ʈ®,2—B·ÇVö­ˆîê=˜Œìî«]g$ö çãíëyÛ4l]—†6?¯=4¶U¯äò¦ëFú¬Ûƒ±îЬI¢lh¤]CuèLBä‚[à§&ôýOß17®Îiudõý…÷Kwù‚|žhù4C9”.D¶N$zÌÊZM$j1„†ð³heËT\P;itÄãCÝÙNGêJâ¦ÎDÃA™F™›=JR¹Ãvh+ÕpУ~]Í«] ¥€RϸÔNÅç³lS_™Â•øî4àB{üp¶Ç¾W1%hªèPÛZ«dÜÝ/]'x¡÷<ÖtÆ›¢¼3’TTX 3 CE3==V)öéöŒ?ÖÈ3úˆ¼¢½tb®§¿Ô Ûq\…:àó ›±¥‘[ÂFe ðƒHÔ¹#Òb¡#^D î›æÝ ‰ÑJmƒµmtj¨°Ô+rEÙtC¥Ï ?Ë5ó%:Ï5 Mr³Ž|„¼PíÙÑgouÁ oÔ|—¬VÙLÒQš¬hzSÂé k¶‹nµSL#UÛqK×$M-s;hŠ 7ºê‡w¤· V2;Á¢G+Ùˆ¨ë¢gèŠ╺Æÿl¤˜èO:fÈQ°Öð?íBT9)&•á’a˜˜ï)¤Ô¶ÜèÙLŽ2ÍΊӀb™«²ôI>V½Fx%;~I;³ª„¶(ù³¼õ®(K4pTÃÖÅ Þ ^@qløŽÝª]Q_¼ =v#¿ÆNÝÄu„™n˜q/‰ûB‘á4Œ•~Ì4[ÜöÕžÞ/€{$)£ìk¨õ•ØÙL©iºþNágIçýN¦ß$ÍÆzêÕL”?Tš¡zõ4êyËÝ‘xÌòÃêiˆw2uÑÝ…FçVözGG¿Þ|>£[>Ðé6I+ØÔO Vþà|Nñ×ýgý,£·–ŠöI}tr„Ý|ÌèõtÝNéHøOO¹œ+L‚nÖˆy~HïÕÓgQÜOÄÓ `†kÏõÚžë¯ÌÕH8¦§JÁÆ3Òv¿èÑM.žQk@‡isÉ+ØHFº™Ðõ:Z©Lºð“(ÖJgž&ÓI$ûÐa ³ÒJØûq3B‘¸»ãŽ&윤D¡j?úÛd†²¼­AS¯( šê쥈{ê]ÕNЛQòˆŸù'J§_*L'Ô=|‡S‚Ç¡®JíØÊ-€5tgÃuzá¦÷éZ$®¾˜Uš[s[|3½%ªªcVâ§ÉT Ícõ3š|Áëí­LšÛ>öÚû{§^Çæh©Î*Ê~hõ·v.F> stream xœZÛrÜ8’}×W übª§Š"x§÷É#Ë1šiÙ;¶zÖF4Å‚$ŽXd™•5ß`¿ìì?îI$²d«wÂ˪¼ž<™àøRôÇü¬¶G'2q;âöèË‘Ô_ ó£ÚŠ?_bAN\Þñ3Rd¡ÈŠÈÏ q¹=òÞþúúøòŸG2ó‹¼È±àrs$£ØÏ¤¸Ü}ö>½=÷æìÕ'¯ŽÅÛ¦<–‰·ÿÖnT/èÑÿ¾üëQT„¾yò`9í»ðÕeu´Ž2ìYˆu”ÒºÐÒ„ð.;1Ñ€VÉܳ„· üØ,”¸íÕNl»Z ÕŽ8{¼S¢ê¶Û²Ýˆë¯zÅ A¿â«v±ªUj£6â{I§DAê‡Áâ„XŸ`2úKÁóÀ/¤ÑŽ¤ŽŸ‘:²”~<#?…©×2Ô&õ£ Óâ]ݨ?ÖÆ,b…žÓEÂìyf\†ýsöØSeÖiøYžz—wõ ð·Ô^[Ûç„ÞVåúÞè.Ò,Ìü4- g®ˆUP¢šµOýˆ5k$¯ùìññ+1tâ±›^°$J¼¦Ñjˆ&„gI-:YܳTöh™f~¦?9úf>:ñÃ${r²×õt`/U‰R?bã#õèö(üqo¿¸îÊ~#®¼Ñ˜j¦²iµ”gOŸì)aÿÿ³iè§ôìêØ¯ö€z.<ÉÁ¾¯Ç;3…Ú–Õ`½8¬Øˆ”©ðf^X¯2es/̺ëÕ0ˆg—¿}x'Ê<»º½/8K`¡6Â(>é§Aè}ìD× §=©/¥UîÑuæ ê€ÓóqÕ’‘\¢’õêÖ˜+ÔÖB¼‘Ù–d{Ùì¹×Ùú EÎŒŸ½Íõq˜Þã¨åÓ†CDv ­ZIòð@ôB‰1§´äÓÖ2‰ý<)å8ü‡–&òJo’šÛ°÷¦q8¤YKgü4bãâXës¶–Ös+Ñ«mw,c¿(é=„û»rTO½ˆý0´Š<(+OôcŒöûYžZAË\Ð+q­n:ü¨o T…X({í¾”fOıu­ÿzÞS+Å®)§¡¾n46­µ£LúY–€†­zxE+N>¶Ühãþzä}/ "ýïÇ¿¿9þñËEQ¢´ÕzùËg(‹ƒÛòþXÐ/<5ˆ'ö‚¹²Tföú1õh÷„]Ô?Š»z„3v]?Â=Íšº ïïêêŽ"v;á§*‡â†ðg× äÕ;ˆÔ($K"#?Ö`ªÄ—©V#A4Ë&¸#™³ÃObÎûM9–] évcݵ‡ÄIŠÀr‡¡¹yîð¸;)š­)ôDG^ÃXŽåäÞ–tŽh»Ñ– R†à¶n‡É©Á…´A&$…Vfì˺¡èÜ©¾îœJ‰ƒ,ýý•¢l)ÖÊ‘+×Ô÷ˆz±©{U,Mþ# Û¨¡Rð};¢ê "UöÕçôäôO‚»© êÚ²yü—ùò; `M‘{{J ÷¤&%Þû¶RŒ‡/gÆ€‚95S³&¬¥ccÅ<LÆ ½ª}x„¼Š tIÊ ÉÛ|?¬±±éSî—¸‘ÈÀ&œÎ†ƒ]CBFc«ÇÀ‘C{k€nUÙj‡r™@„þsÚî`än¢dlE=R˜ S3ü€2fÞ(d³ §àÿÃYg~Çsq 㜠˜wÚµcß5Xz]V÷c]݃>ÔG±0 òVJ{U4]Åq¨3IÓ-Id°„ö6„áë(öœñaè•}K±¸%ôº¥¼KÃØO§ë‰%E•®Œ0«ÝØå_î(×O„†qƲ‡Ø7}·Õâ]kñdŠzŠ9Úv[·$‘/þA‹bÀyžI—°f‘ñ‹¶ÇÒd€²e—kžFÜÇ„®¼îf—ë3óyk6=D­«©)QÕúÛ˰¿¢ÜÏ’×LcÃÞ¯…->(ðºø TtæšM(^HÚ_˜h§ý"®™ äÇ™«…š|å~Aîr9ñ @‚ýB€ž¦Šƒz¹Ü1DhCp~ŽƒžÒa·k¦Û5(þÂ~‘°Ð9ªb<;ä³wúþââý;ñéìõßÞ}ü(ÎÞývqöáõ1Z«"Íbïòß‚ñ}:3¶˜M-¡Ì•éÚŸSᘑCHUå}Kó‰³vÚªžãÈœBØïÇ5µQæý^rØ5:n‰Zlꊖ£5H‡ ÝÍHøìQƒ±Çîkvœ=ßåjh8/®LûBõ¬«ÐÀPáç(ÅÂÀw,¾WÆ™´½Á<)õ†r‰”Aì’94TýN=¢-Н¨ªoÛÓc(Tow¢¨c38‘Uò,AŸ£gI —ÓMW„\y‹퓹iv•êñQ¹á EY•Ùjɹò‹7nÞ½ÕÜ?…!ÜPÔ( Ô#—E÷¿ˆjd÷ ”ø© "w4 $«9ìaµ`åBrvAÁïZÐ0…‰\Šþ~}, öË!Sg¯Ä =éÜÒUÝÎ(¹ÁËŒÒ,I\êf_wÈyQÝ©J¡þ—¢’R·àobh-¡zê§2þ9ÈiàKy_.‹×iSC]‰?“: 7Ôx¼g ¥q¯ÌœúªÿÞ9SïMŸùy1wa‰‘ý%Ñy{ $ºéqys@—LQ¸†Ãî£öËKœÜòyµSI)¤ ¥‰M»Ó´|”š *œìŸ}½-)½¨z+º‡JPSÐùk¦ð—Ë‹_Ý0–J*àæ¬|LR¸éˆêGS ý|ÁoGšßÞ–TS¨mÔ·¶fĺëè`QŽÜ8¡m˜o»,¸_œ_~8³öŒQqÜîÙõM÷º¯y\ö¨5ÇNœÕ“i lºìþãi a“.È[¥F«Òú=·½ú2Õ½¦ æ:# yã¢^\0@à×$7^•‹Vêîç² @˜ïPÐ쇉Q;&¹E*_ÆIëúÑ\?ˆìä+Aš•&Šæùi,Ú º$™Îox¦]nïà,´EóZSâ0á-v0·+ €èqÈ`/ØÑ(ÓcQ”™íÒ­!HCâçÛ]ß¡§ ÿëø%Еˆ'L½©7šرQJרVEÞv ¾ ð4˜”Ö³du…2SÖLÛ Äfé%Gͳ/Æx´žç(à1ôCPŽè$"a#þ:¡b†ÑŠ .M]Ôz·ÀÜuiÙØå«wäÊ<ÊæÛ^µÑáæR¢AƒÉEÎ<¹hz#[Ç(€ºË8 éŠS75ª~[·º éŽ(òÎu°v½­z™Œø¾Š¦éööuµQ5„9lÙ¦Óè×Ý)nvÉÿTêJjЇô8¸5ãÍXbç…üâÝe£×Ü#ê¹ÌZuS³aAÕhš”k¶)—SŠ#Ð^œû'èv#U(½ò ÚTÕÓ”ëíÔVzæÞ«ð8šV@é—T(³ Y¼zaj"’Áßåñs‘{Z2º‡…> stream xœ¥ZÙnÜF}×WŒˆm¨iVqwžlÅxÅcÉ ¤D±«»±É6·;È[^íOÉ?ιµp‘äøavšµÜåÜs—Ê湜yôù3ß<{³M{â±Íɇ®>2óG¾c//± ¡.×'zg±`qê»IÊ.w'Îë^,.=á±›&i‚—«înÌÙåáäÊùåõ›Ÿ¾õîÚá× öºÌ2IË<µ&†bvÍ Œ#«ºßlYQ­ëf—uE]±®fü\IúKÆV²ËŠR®Øù/¯X)͵<¤3÷¡¡02}TIà„>¦®€Yó±ìIR7/%I”$Û¬£;´éà%?Ù’ ½(´éòmVmdË î¹S§îËëŽû"ÏJ˜.[+³qHæe7P»µÌ;—]nµœô³'¬ö‚²h;V¯•¶ÅJV]ñY6Ã}Aäd-ÛÈJ6Y›d}W“ÕôÝ}[Töd—Ý)DŒ-©Ñ_.± µœv[+únä[¶^ Ä=,óƒlŸœ±¶fÝV6’-Ëëê3ÄÊá2X·ÅoJfõ ˜‚Št¦¾Ëýt<Ó×ú½-eÖJ8x_7ÊÞ hÜ“Üû¦¾-å®eÐðv! »¤N¿iY¡mº~䯄h-¾§¤<Ö=CP°¬2Ј4`ÞĸØ9ºƒï—ú÷%7ôâŠL `ë0ϽX‹kâm—Ùz‘êP šêRö±/É·EYtG“® Ý@|˜¸AbÑy6‡n ˆ’xÝaçºUa?*\iQõ—Ù±Ðóžt²Ã}Ü ¹Eé§1¯µËëÙ~è&"á3Ѽ‡b•5‚X8àRòåAfw•l[Ù*“óÈ ­8—ŒF!.Üè&<ÔÖn³buƾL™Ž¨H™zjèBjÐ!nt=]ÞA•!¢ÄåâªòM{ ­è¤CQ–¬ª; Õ²¨(î‹n[÷Z ÇnÀ­0¼ÐaŽ0Ç}y‹ (ª4C…´’œ<æ9棷|ðAdÙ#4çfdVÐGßžÑʈàÂDÝ›UøC_408•w*hÅøq`…ãÈŠ@ŽïY<Öu ;Y­(2ö[íß¼ÞíA7ˆÓ3cábàIç‹ ¦t=¤îk2ÑîÜB¼ŒypÖj5¢ÄŸAh=Jq_·°Þ –â>çÇ\Ê26¼®]¸°ó­Ìïˆ .ŠßT¾Óè·Î:/³¶-r}'‘Tì«;þ¨`Jœ%›/µ–(=h¬%ÁÌ}XÄ_U)z¨’=·ÉF×þøë²‘ÙjF÷‚Ýòsö¾w (|­Ú$ ÕN² ¢Ú<},’yJ$€"G÷Àd3JBñ¨RD¡µçܪuš_Ô2eu‘Nºy1pCˆ{ªSP€‚¯§=g¯>éëÑX"³)(x¡d%sÔðú‰Ôï#Zc"ô¤éè‹j¥Æû˦¾£êF">.E{7S/Ä_,Wϧ8âc‚oŽû®Þ@¯-Pò¢ÜÔȾÛQ/‚zÉ×I&°]•-“ž×•DtJsã:«¹îg/¶Õ²ˆîºoÐw*{ Aq¬òmSW–ŸnM"çæ]†õ¸cUüé<ŒAÏSCÆ1E•,¥FÔÒ09å59â/ ÅÑà‰·uG½êÙ¿§y Ò²×}¥¸ëQ°Æ>åÊtØì­lv ¿h©ÜQµ•ûçð{éãpÖéÄ¡7hºGÑ4ü_e£³ªØ÷¥¶¬•Ïö@øú©Øõ»e &Y !MVѤ™o‹ref/Nü ¬¬œ1¥J:™k—Â{fÄü&_&ÜôN–EF ÈúÌЫFQñœjÃ2va«Æï‘ÉÚÁæ_q]"Reû²oMj±¦È¨égë¦ÞM.:×l„4I3K‰ºÚvþSÈ3]S¥;V@ý¤¤~n,=S#Á¶(t¹”…?ç¬ío[iGF­ž©ÒðÖ„(í©rL ³Ã¡ ºùóÏfJ~ñ}:µ¼ ÅôS—S…ÓkgZ|ÃXÁY¢hfõž,£º°]"x:j¡;»Kr·^Ʋ<—û®ÕÈ¡f4~ˆŽÆ1UÖÌgÜ#a™Jn/…Pì§Bƒn˜Ñ4òOûFªØQyšæGùhØ]_vžÔuñ“îÆ=ƒõ”=¨ãÉWͧ‡?ª>Íhà2¸öÓ“iqëÅÖµ6Éÿn2ãU!')´{ý¡â9uÙ›µž­¹i̇¾îÍT%F6òDZŠ'tëý˜fšEu‘NÍÆÐkÞünŠôPj^ jô3§”õÐós§ÊòYÖ‹“aºä =M1UMN”™ÕHe•VѼ~èÁ‡ ¥H–¨œ;x¢u*(†ÍX#ÕúIp¯àê+µwElBòO’¶‰¡‘‚ø”9SUå·Ý(>ͦ“qIRì%k»Ûº¤mzžjͬ»MƒTP÷Hü«5ÙIÙÙNdy!³&ßf·¥´"iÝî-©k¦ÀS઻õ7k2VÃ65X¼˜Ftö Ø©m£FΠù}.å™þB°¾… AÄóžÝ÷#7õç3`*}Ø´_9+x<…{Ó.?Ú \…vÀëTŧeYÜÍ‘Ž…ƒlgÃqÀxl—¿¸%&cÁTã·“»ûLq\žþ5‘¡„2Dæ»>õ€Èf󉩒Tø.úØÑoCäOyª ËO=²'ÖÓãa‹Y‰59o±›Œswsë•"ZÛŽœWP«¯uC¹½±TŽ,Æôˉ;oyNF¯¯ë¹À@ÛHÛœJ `=ó)Ûíí¤=F èh7¼‘›on†Íá”*ŒÑ[‡Ñtб”ìo(€Sè˯ƦA¨†©pýxÀÈéaÊŸ©g}¯__†YHeK3…~5)¢¸TÄ¢æ@dM ½¼`ç7$€¦=ß­Ë‚0¼G»ÜMG]ôGÚIó šÉÕÜR~ÌÝ$I¾mª{IÀ°’…ôR–<à¯ÐéúåšM¼q$¢ £,b¬£ £l¢#©Ö#{=¨§T¯dVÉ`:'x1™IÒ*oR”èÙ‹~¯£?:3§q&×Ú¡Ü8u"Bzt¸_樂u}×ÌQ^N[SS5”8z N°G¤fo8ƒH~À (ƒ8³éKÙ{§zç 7YkÑ"N†y{jÎ7ý ,«¦ò¨;‚!¤ô¬Wi–nÙÌ`÷;52)§¾ ÆŸÙÚ–Ü4P‚ò×GV¢1V&S]"ÿúã»ÍÕt¨Áégê•\›GÇIžN¹y2@eÀ´ƒ÷ßWßM<>Û}lèTêW{7ý»:÷ žÍP‹ Œ«z×ν#=ù¢¢FöœmãH3jÛìýÓNIÇAd£¼Šï±[ÀãGØm2WÔ¯ †9Zó%PYLª¦X˜&uß7{I;Lr²å¢}¯^ëŠF)ä¡4Wó_š÷ÌKò#±@/ïX¥  +Lôl0À¤-">>UUù­',ß ½Ð> stream xœ¥ZÛrÜF’}çWÔÁn÷ËèÉkY1Þ˜ÛJt(&ĉب&avmÍVoì'h>eþqOfV€mycC‹"€ª¬¼œ<™Y¿¨ÀU@Ìß›ýÕ«w¹z®õpõËUÈ•ùk³Wÿ~‹ úÅíöJ¾ U©¼Œý¢T·û+ï퟾»¹ýù*Ìý²( ¼p[_…qâ硺=]}ô>¼ýñ/o~xwç…w7êí®º Sïô¥­u¯èÓÜþÇU\F¾ùrñ:­»Žs¬UªuœÑsHž¥´°7hÝ´j|ÔªÖ[z5Mý<+KYˆ^LøÅê¸Uß Oj§yE<›«$ò#+±÷ÌÏ"?£¯6W¥á4‰<üèíº›(Ëü¸È½¾f™z+ ý$.bû–«f§kuº)¡Œ4N½ªoYHSûA%Þçq¥úc«>ñ*aûQš>ý³bUÆ~X¡ù¥ÑÕ¿þµk†±?îô þG=ôú ¾ÿðÃ:ŽrüssÕz^ó×Eà—±=ÖµÏGapÈ»N¢Ìsµ#~ú÷ŽžÆ~Päô8Äk¡U wÜÐC>gù)62ŠMémRl«ªÝÐ)X‚Í0vOôEžúiVL/âºÔ©;ÈZ‘ìj_bÂf•iyÕYÝŸIG¬:ÑS~F¿COë7j½¾T•8RøIâøYžñ9ÖϬJÖ^\úY’™5±¾yåÚWd]E±Ÿä™ä´t(è/ ƒháQxøµC…´/ܯpr§æÔ/"»¸“ï£÷¯Z8ý4@ù;Öã 7ǾÏJïô^·ã°Rͨºvw6/Ú ø`RJDí¬ßuIç†xN9AÉòmûnÿò&07?hjü«ù¢û]- "lÚ3¥GUw½íFÕ´›Ý±§éõ—Ö.øXꟕ„ Ä4…œ»F9íòVNYüÎÓþƒ¿"¿A¤%¾$ô>Wû†]h{l7cÓµêPõÕ^õîÆ—øË<·‚A˜aåöß êV»#ìðqòÖÚFvÕÖJb9L2ì°qzT÷zôÝ=,€òê]©È4)ÕWT⬓€ }ÿÃ÷?½ûñöïòš­Áè«è¼—!hF"„ć镲,kfìºÇZ§õîÀ»?w„ ÷Ía«ݤ®¨`p‹²ØÏœGŸø•G¡ó¡¼mp¯Õ—ϼ¬M8fA¼¡kGŸKv½ÿ/{NÍÂ`ϵy-JIó00&]G¼2 ð¬ôÜìI|uŒ]w@6¤d(˜DÎ 4Úþèõšñ%Ècï¹1¤ éÕÅ6å'YéDëìÉyžZ—XµiÁF3Ç\ŠŽÅóI»…Y¬;©q±øX8œê.ÎϯEÿ—ó[©q~¢4Û‘«”¼a2aTœŠÃ1ãêÔqГ£|ëME¿ê(sžšA¯¬Ü M¯Þ…m$@Ed=¬ZæàØ ÞË9¾â L3ëåñ2ä Á06(†ÿÍ‹©ìh£&)ýÙÕÆX S´yŒ½Æà ”«6z ÞO‰…¬®w ê*° dáÔ𒼘%€(’þ@¯ëãF¸x³?P­©/ˆQ0LñQnùÛoÃÂË"›ðEnb§Hmáe*ƒ4èò#j ÜŸ5¸5•YþJ¤ÂöIæ²SnŽ;EªY‘šäù¯jn;*¿/N£¨øõ8M©F³âÂðz ,9ç2XHAñM“ƒIÁóü8‹-ƧZü,AO*‹LœP>h)¿œÍ©å6¼`r[­ ã¤ÚÓ„F`'A\hxoš­iôN°`dâÅð¼ùúçõázF&ݲܔú˜!_ø’q <(ŠG”Ô 0â2%$sD?‰„ó"C$9¶ÇEží5¨¨2ÖHý8¾l]<÷H &¹„ié’‹±NÂå—Ýå4ct‰fÖl‰ÉUêÙ­‚z[\p³"¨ ‚ÀÇt¤`èöúRÀó›Zr(s#mî]µÜw2³mE0†˜Âj²ÜT/ÔDü$Ì“Yô«vXݤÕü%EÀmœ"¦*ñL`PíÎÿ­U%ÊåŸ4òÀÞ¦;œ—$+ )]X2ru¾Áu¸y™Ù¡^qµTÁÇz#]ê»n´ïêFª‰>Ž6«i‰ü/ˆ/è˜ZMËuN}ìâèG똘`¤–¡é¥…¥ë¸S7F÷T÷ØÞ9Ÿ`hØCPÅÅe$^ÒHÃm¦µˆÛ†ƒÇ‰®p¡»6-(ýQSqIqTw­©‹„99ÍÄþÇîP%î:Øš2h/ r?•‰E MTj-a«aüZ” W7ýšþ¬ÚŒ©_¶1i¨€haABj~cµyâ^侬pþvìaÝEæÍ ™r!@'øªˆgR&áÌ·‹@R ¡'õÅÌÐ“ö¬’× /š¡ŽO9‘=EÎeü`¿o#…£ˆŽ´áPÜ_œ&LS}©“+.lóéËdÆ|¦zÚ×ä/È]õݸƒznƒ‚íóEÓ³êlÛëÐ_Ðè/O³o’Š4„š´ÞçC7Pž$²$òS§!œ¥DPîÜL“LñkÊ3Ô¾$]¯‰èƒ*x ¾ s/ûè×ônš´šº d]нÒÙ.ÈÍ DÚË×7©éÆãÓkÍw=€ÐwOcнÆ4 íb®×„¢ÎMÓë±{"4l†?Öäꪕ*M‹%½³ÙMu–9ò/Ãu„§¤³ºŸc-mXr3Ûæ_m©udEN))$ö@\[C"ž¹EO‰E÷ÍÖ@%é˜ÊeëgB“¸ß_ä®èý%inŒGÂ'·™–äœÕ]P3ÿÌübâs¡Y|·ºé°]ŠÃ`Í9óiÚ'Õ¤×ݪZ›jÐÃkLœÌjäYDëš„ÛKz&áfüŽì/öÎûûÿP´ÇÇ?œdhjmpë¢ïâRQ ‡$.½ÒãæÕ¡†Smt~¤¦ùô~ö9hIõÀ ì>ŒzOý ]óts ˜æVZúSNÖïçä$pÍ-ÔO´ì[ìÀÝP8°»Íçµ(`˜¼¿¯<ù²˜ˆøs5 ûpѰs¦¶­ïn¸™ÜŒÖß:¤â©iG›ÊLe)=> eSÔ4v²ÌÎYƳKˆ³&šéG“²°p%ã& €„†Fu+a» ¶]'­â‚ˆ»›Ÿ»›˜8W˜zOSæd :¸'ïùyì© m&às¡BÔÔÂõŒˆÜy–ŠHú POY‹Æ¡Ñ%1½×6•í 7™r‘§hH‘[ê»Ùi­eI6 ˜~™-7b«ª [ïâÃKˆ´J >JR¿Œ'ª¢t4sÒ¿t ÖfŠHc@hÒÊAãP$yð×~f÷#jhÖàÊ©ŒÉ/¹âêÒë_Ž`ÿAs…¯©Õ~jØ–Ù1ãoq6¯7Ê/ü,Ÿp=3)žD•VŠzjÚš )‘ó²<Ž‘fÓÅf¨ ‚ü¥ÜØÜ$D®Pßl«ar°|7sÄa~Hî®VÒÄ$– ¸'Sb#‰‹YûF¾aA%àô+šÖ5í Ap$ÎPAÑ|“ÉTâØ`7Xçƒõïq9n3 †acò£÷ÇÎuéN—½ЭéºÀoöC#G¿Rã"÷å±#Üò çq®“š®F7[ŒlRRâ¢È"¹M‚esÇgY—&"Ž)[^.œÍx]bG¼TmØrbARì$FWƒè\ÿ%xÑÖÂ?.ék ¿Y*/•=/ýÚ¿]¤¢t€™˜êŽgˆUÕñº`ëƒRJÆ ö]Oh<Íq¢˜ÌUCû¦:€ˆåŠ}~8!-vÕHUNz¤±Ïx¤j×Ç“h Y Ëh¾›2ßOmóYé=ð‚…¦cw  ü€„ò$µ3é"§û)—Õ"x£ŒÚQ®±˜ÍŸMÉJôÒPiÀ•]©­æÊÈ£u1 LC.KSáfÖM7³òhúbq¿–Ñ!–fs×ëLãyñàJ¥a"qâSœpˆ7q]ÆãòÕ#Ï*œL|Ñ n¥ÃH2"š&2W¼‡ŽGœš›•Gzí‡|….¥½¨|\†R§Á&Äfœúüå|þn¨i½ оóç÷ë7}Oĉ'â ô¯­!ÂXJÑ߀Ö-¬”[d½•Ú Á&dœk¯²Èä5§ÿ4jïörÇ 9#œúÙ×p,êRUDZ£yæÆVå\îdåìVOVHÅ<2ÁdŒ ›Qñ‹ «ªiB˙ϛÃ#Ý|0¹ÑŽÞ¸Â_f¤™9J’TÐM­*Ývq÷ lsŠišÏíîñ‘ä ŽŸ)¡*Æq³‡å¥Vzð­Ü ŒÉ¥Œh}Å6dìÐÍ LM•ã~`sÛ¢üF„ÏL 8åâCºð¶}NZ»¯j1O*ÛÐb`±îb»ko;`@AVNee’'󮱫ܳ3›QbëÍ“mBFEîÏ;(™©àx\ͲUwÿ3Õgo¢#–C‘§Ìè’íº3å æ¬ îLÏ@œ¤p ÁÏýµ»%Ÿ~Z ò5‘EΉíV1«)ç¾ãÃra‡“Ê<‰Èçð•l*1–Y$™’’E”€þk¾'0ª®cÒÚ“ù¥ËÿÀcSûöÔà(1IŸ›¯X!i2Ç@F–S˹ÓÚ„Eé¦[ž8YéÒ Ef×ì‚j_sçËÞ}ªéêÆ¾i¹çÆÆ”{=¨ª##És³JŽI)Ûç-/šWíƒo˜I.WZè*NæÈw35§+-P£éì˜XMx’ÎÎ×w½·âÄP6¡sfo [/Ž¥RøÙ +üô»ãƒBý’ðS˜ÖNK½0 _ýp{õŸøó¿ICendstream endobj 56 0 obj 4713 endobj 60 0 obj <> stream xœZí®Ü8rýŸ‚ð°næ¶Fßk`€]ï:™d23ñÜÁð °¼»[kµÔ£_wžÁû(ûŽ9Å")öµ'°áE‹§N*ê…±ˆèù·9Ý|ý¶‡ù&‡›_nbýP˜š“øã=TôÃýþ†ß‰E™ˆ²Nê÷§›àÍw¸½ÿÛM\†uUWpßÞÄi–±¸ºyüåÍ·ßÿéÏo‚øáV¼éåmœOŸ†VM‚^ýïû»Ië$4o^ §ywi‰¹j±K =sXd5M,£hU¯%ÆILj'%ä@¯daLcš›:Ó(¯ÍÌ—Oô0¢1¦Œìï½~wËQ.BNJtâ¦ó„©[!g¬¢÷—Åa^äf°¢ÒV|è%øýGµñöYMø÷Ô ÌH&Éþ2ws¨7“䘥»8¡iÈŠ\OsT³ó¸kdßcÙ¿Òè²€K£Ø˜ù× C¦ô )Ã"Žóõ/õ;aBS67&¯r;æ¥ô÷^—fì}ýÃ÷wâÇ·øKŸc…½Å™9 2°Ðþü_wâõw?¼þ÷ºßÿüþóÃÄ;üUßa‹-o.ËÃ.2»‹qlcà»ïãþÂàñ¼t#|Ò_Ä~ìûñ6ÉÃ(*Óà ûx¼`2¡ü–dÁÇE 3†‹‡@…‡ð~!¼$iVqaÓŒ§8\>.Ú8&·é‡Û;¦CEBæ47Àf•vÐ¥õ=“Xݤšeœ.ׯFaf]wç¹k¦¥ÅÓÐ^/Zê7ó°(¬Å—f{5 Ë´´g,gµ]ט1¶žŒØ‹Á_n³ˆ½Õ -\‡£¬“2xšE7‹oïºa&—-vÔ®ÑGE˜ÚU>(·<–AÐfæÁÃ-£4†ÿ ,^ *é÷?ôó×oãÈ2Î'©ì|øðój{œWÖbc¥eKÁÚv{â°Š´W³³¹Ù}¿Æ›_»¥ïæeûi<‰uX¦u¦ÇujÇW än&ÕÕ:0Ëîôâ^&ïÝéÜ«“hîu¶aüãe9‡ç®yß+qÛµWwŒzm]o ¯cæ'D…~óê:'¸KS (#Fð†˜U³biyÐö¦q˜¦–hê˜'q²‹PÓ4j\gòãIö]Óá?ˆ¥fÄãimÈêV.ÒÐ Oea&f²Ÿ€l ‹öq€t‹PjÆV:‘Dß ï$žuüHYFЧ›¤HuÕþp&Ÿ'»áÑ7ÞniíúÖJ5(ÚÒË‚_¦…ªÐ:×cP9äèRÖQÄ$ÿúë×_}Å9ªH|V¬X_}‹èlÛŽ"ŽÈB ,ÿ‡bo‚.ÀË ™º“œÀÄ<„ñל´¡“‹tóihtò¼>ÎJ‡ŽµÀ¹ªÈÃÄÊ™7#{ª® F³MaNÊï&=ß%‡„#[Hh&æF¢<­ë̘@âLÂŽ¢÷½‰^9Ah%`¯ª¢®íÂH6ß|xÊ‰È X÷ÚkHcüÍS ÙcÝ›0K È[>,Ùû85©ßD&œ¤Ö|9?lnò"Ì7ÞûÒ­ªrga•r‚bÊ2$A*öK$Qòä1²UžXH.Gs<‰qužÛùw •„w…WáÐ~xÌr9SB§:D2¤(p^|óÍ 2q–{%žºå¸1JY²L,!¬m‘\®Â»tE1…‘©E˜eµ¹ÌÄ=0¿2gOÆñCó³ OH ¬bǵou2¢÷hƒ 2&ÐyÙc¼ì¯´aYZÝìe#àPË™ôk²×¬E¡B™TjFNSðÙ–I3;Bv-j .5èE-,“Åpa!2·W M7!œ™¢Qgc-]MщȬƒP¿duþLùÏëYI3&ê™•ÄØ|Ô^„Š„f¸˜( u±xñ¶ìX«@L#)P'ɹýJ…~…Ö(ò äÀÑŒ÷3ÞËÏ/N}£‰°ö‰ƒ³‰DæÉη×X³ìZõ‰öµÑh}¡•¬‚º6e,»ä›@‚,•ôt4ER ᕹ—3+F¿YƒuQ*ßÊhèÕÙ_QqÆOxÔò²»Mtj­‚•Ÿ%@“ÛòcꀣIo“{9Êž:àœsäíá@âjdSÇû}@™'žFá_bô‡[#¿ŒCth.\¼ìª¥®¶]Ö¶¨Ö!—‘ê©kè‡" !¨UÔe‡.²¯´³Ðk\í’Þ6U×¥ÍF<ŠdŸ5ÌÙ%ÜÊ´i* žÈË>¹0§Þí»ÇIN1+øÀ¼Í^B)«õ‰9yZ }–ÒÁ’qòaŒòòÌ X«q,¥–Tä[ ×|lOS§y ´ÿ™¦"‰*ÀƒWT&¦*Ô3_莑榺D¡àüq, <9Ë‹ö?E²|ìún¹楮ejŠÓVóìçÜ4wû—ZÕЃåf!²Hb€5ynPp˜ä‰¨aД+ý|C}6—y?Œž—]O¤…S·šxƒ¶e*í\³ö.Eîó¹’J¶~*I6²äVQì4Qš3 ÷Š„”8¯¸]!p°tCÞ:*™4¨‚=ôã#jpP«¸Ãþ/œ*3«\ûåá–¨^1DrÈ?¯j²«Ó”¨sçqˆ1¶í†PCA)e¡ÂÉv#”J  ]¹hƒáÝ„ÀÌLzû°öƒšô"”­gß#0f]útójÙe9®¨È¼S€_¦µW:ꥱ—lÍðø‘ Ñ+ÙL aYT9Q÷¯~Sîºt‚~J·–ä¦Ùgш¨3«Mwbñ¡ŒL?'Ñ£n_éD"ÅiE~:Q+™„Ú޽èà¡…umÀõQi'9Šþd«>ªÒ4g{0y/güˇVˆˆ­a“æ¹kØh0®p2ƒÍ‡—£ S.ÈPÏ8Šºµ®=¼Õ”'·yê3$®4aé ™®$ Iÿx‰mûÎÌIÉ𘑠$É´Š©&þñ=çw0[R:>vú‚tŸçiô…–á³:P™Æ·võAUÖ…šîQVuð¤åñÀêT’m1N­Î‚o÷ü³Fð³3¿{¥z±Ÿ”ŽÓØv{îH2»ƒ~à]%¤Y´`ºÿçw)tõPSTYlU Bð¼R$#Ç«â«Lê4>Ã}R†ÙÆOöl=`SãÑj£Ú°òÞIÝ_m˜äyø›©Íܤj‘d+I1µ) ~ô+{Êh’¸CUK-½Ž ÅS×Rm J‘Ô‡’©ËGýþƒ>>.aÌÌô:†ãÜ1ͧ¦Å–®Y{9A*f¨ˆt.ÉQ»l„r×ÝfRxU{9o’*¥Ëw?µJǵ~ã*¬éGÒ®'ðv§Ûlºøg„±¿ëöà{†âwŠœìZ¡ÜŸ­P´&Áß%§Ï*ß²czÕØ;(h:ÛwÑ¥+ø‰hÉÍÍç•˼\z_ú™7½R&§èò9È%Øëâ*·yÿ]pÅÑ®_å&—q…æÅôPÀÒIV<«¸oÒ"{?õJ§ CÂ?’bM-ê›cü ‡÷º°F³æ­C{ò%õ8­ €Ì=ú*Ì×Ù#<¢ÂuY™†ûCðBT+è©èjÌ„HØëÜÕey ÓÔ®YOjè{€8`Ö¢\KôãÂD®OD‹®N€˜8çê„’(Å`8F}_U[2I #–hYL,ü¨i«sÓH;»,¸Bwz®itðÏ)Ù.€µ™ú*W“«C¹çؽ@ö•“•øéñ¢^ÐØ®@j›QUtž$“š×Ëké-¦cQ‡…»œ\®d|æ®úh§,R„ —¹,(À­!õ ®£Úpñ+çlm6Lîˆ W]ê=MT4ƒ8‘ÔÌåÔ@7yÇu›aw]éC’G±½ˆv5š¾a_T³€ãäbêIS\S³ ®P¦cÆ…¬wò1¸§V|'öêÇ^‰¼Òò€I€ÛÓWòcg^·W¿œ{l?qK_ݢ崭Á'] Ûÿ®ƒ¹e†/>žÝ›Q ÄôKØ;;»Òoõ€“$¾Š™~ßϺ֛1u÷©Ùû~ðĵío˜¤µHÓ Í *ð¬÷ÊÄ”ws(Œ €¢Šêg&X ,îš{Il™u–¸{ï+QžG®¾Dæ±ñE¯j2KèbßÝ(¨Î; L{V˜™i.†]ÜeõŠ­,<øI6Ô[R6WWãØêl¨Ý‰Íi@W•î3w Ê…ýTàþ6¥ÓŒ’`ÿF’tœt¯å•÷‚Ñ'51pžÝºiƒ®ãî×§Å»žxÖÌ$Œ=*7ÌZš)¨˜Ó×WØ £ëËݵÔ^Šýÿ¡D9âW Tœ‹*PZÃQ›BM‹tÝÚå(²ºBØSYÙiê¶ù é;¶=_Õ_Ü— ¥×æ)ÊÌ~ƒÕ{RÜ\{gž"±õÃÞ¸®/b.O·´ã &ïjˆR7Æ®å.F¶~†ùtgxirp™qúFF´ù0X¤ø´Þ*þÂ*ÀÍA»^^¨»é#Šý™ÇIÿ«žê›´~¿ƒ¢¢†c'ÑÝiWzC÷²§WLïA; Yܳ#5£€ãÐý²âبÒÄÄÜ(à†í«ë’Ê¿—¦PµHÑi­Óºe•öºÎ@¤»)>L³ü5Äéó +MA©?¹è6Á€—*,ý-×ե̈́Q¡ GädÒì Þ8¬]C äc®Ð¸&ãK 8ý˜õ{’©|K͇kfÓ:Œ2;ûÝv3@Eå¦Îô7FDÙ¨ƒ·_éc#ïK$úîHü¾ûõ4ðR 0Ó î‹é¨€d^¯%˜›/[°÷y!¦‚ßm]ñG'H¸U¾}ƒ6ûNp"$Ðß°hµþ¼¯gHƒÛ OeVDœxÕb_}pcÍš  T7µÂ¸’ËÈ* 3¯#šG¦|ÓÙ/á¸näöèÀµÎ+x¢“øšþ= `0_@ñÒÇ&Ù¯§Ê¸°ßZ~Ku‚€L /¡X’$³]¼ØIÓO¾¿ùOüù_ZÖHÓendstream endobj 61 0 obj 4462 endobj 65 0 obj <> stream xœXË’Û¸Ýë+P³1;ÕBIö&žØ®é);é–Ë•rgÁ&!‰1EjÒ²ò žνxPS•ò¶÷qî9ü0Ê Ã?îïê°º¹—d§WŒìV¿¯¸yHÜ_Õü¼9þ°Ù®ì;œÈ˜ÈBм ›Ã*z÷þõÕæß+.i‘9,ØÔ+.*9ÙœVŸ£Oïn?¼y{ÿñÇ+ò®-¯x¾wµ¾ú¯Í¯+QÄÔ½y±÷] {d-2|ÎhRvãSÓ¶¤*'­H_×äiPå}MÊ®&ß[Õ•¥IÓUíT7ÝŽT}Ûwä1z Q”ƒ"móåŠ3Êx’Eª=“±'OŠ=ahzìûšÚà2NÓ,µááñ9mö l¯‰ÒGU5eÛžm´nõšÇv=7eˆšÃ±ƲI³%”¸6ƒÓ3HÆæmKòÄ4ƒ—ª•TÆÝÝã3†8œáãáÜÕyÓˆ=)ÌÊ59“~ÜC¥!j£§jOJ õ!GÒÃ…ýø6U7c?hzµNa{–Ñí–œûéÅUR@gYaÑúþ lnê²æ,¡Å’h–Å&Ór$ÂPåø„[ÐTò9ÑjÉ#¡yì|ŽúZ]ˆ¶Í¹Œ¾•‡¦SâÇ~j²…pMÕ¾Ê 3°âRÒ˜'nÿÛñÅÅé9Í—þ©næÓ š‹˜ ÷ «(Á aêN ` ±7}ZC‘Só4†¥…¯|áþªˆ^RʨHâØ¯É2Û~ {eÙ™öçTä±Ïý|2hdE•çW¶À “°¯pt°ïÁ¨°Ä%CüœÇ%FSŸ0£WCˆ—îÅÅ&"£)~“qÿÃM"˜©VÙâ/YŒPOÍìCËÒÌ­ý ìO4á,ö=o±“8™ø­hâ öÛQu©%Î*´´+[R—cIjÕ6µ6 ˆ:‰}%p,„ÉÉ`€löæÈ„Ó,]ÚÍ5kìàÃ\\žæÆ6`€vÖ£:è—ä·²º{ÀõðdÄW ¨fPŒÉ™hu„÷àŸk¹¤s­®fLy×I\e,MüÔ„Sœó¹]mæ*)çÙf±åš“¾ùíaý&ˆÀÙÔª›í™ÔCsS= Úïö”¶áफ़«—cÔˆe¸&ŸLN)•qîɧñáIšÎ”„oÏÂí;Ý@ »géñBå][§ñpë¨Ýt¦VWq -yôµ©`¤lÃÈ0¦\[H)]Œêoa~Ræ¾´w^ZY(Ƕ©Ê± €ÂMÔ¼ äóqÙÏ,qicœ¶`m9)4¦ixÊb-Löãý­¾ùxÿ^ÛA)rš$þ€wMë*‘Àœå ™ ix.búXV†@êäîòI“ºŸ'ZZ4ç¹ ç™ÍúÕ<ýS P7Ìj5)OAP–±5šî. ÈÐÆÉ—_÷ý´Û“®±"Àþ€ºîö£m}ä5‹Gôœh¡ EaàcH³rΆ™ç>™S3î±jOÊ¥Ž‚©°\kLˆLKïD€ dOA²mþ£jÌñ[MÃ`]÷Ê®ÕÓ%4±Âµæ%§Gæ¤÷(Ζ§6ùÝvd§:5”í5ÖÚˆ\\øóK½ÃqÔˆ5 NÄ“o¡ËÁí_™QR]mÖ Êœ¿oFmÂ4冷L UÂÈŸ T‰'§sˆ˜²Y•1T'ßú C¨1€Uø7A=VÚƒ# ‹U öšl§ûí SÌ$…J{Ð4!hdV¤^;àŒ²Æl5Ì…©u³ëúqoÛ¹NEA%“à½&m«ˆüǾŠÇ´eÐNº†zHÅi \!f].fVÜ.IA³fVnIÙâ¨ôº/i6Š_ò«ò9çÁ¡éxŒÂ9äþȶP›ÖYû˜ƒ|©®Lœ½§¡#ýd¨á÷´Ì/8Z"3f{hßvqz§|%˜•‡Ý’gˆ]ø!Äü,Û” Îxv‘­ qÂÿg¶øªK8ɘ?o»œ‡æfÐ×[Z›Ò´Ó xÃ$” ¶0€Íx&_§gè©iáW–Te ¹ýžF‡RPª¥®†Î³—~a“W~60ª¥Á²· dMEö NÇêµOÎÖKÙY³ƒÞå¾³ã.ìxœÏ6^v¸¹¦ÅB¹¶²ìÏUÎ=ŒÂO’èO–ÜÀ¿R‘-܆7 k8~T±F9ö²2õÝ9"´wpc°J'¤ªø¤îvJAˆ¢”q.g‡àL2” ŒÁEâÀÌÙÿ‘·Vöj…ÛëDpt­B)Rî %êÊp#:M/‘n‡TB‹é‚2ÉçªùV—Y¢µœJÊ,éý˜Pf L¯H¼kHYvqs‡Ié…cˆKDÚ¼ŸtuÆ!â.î™Ë‹VUÑá4‚YÊ2_6‹±$Æ)˜}Ed[ ŸÅb&Âݦ-ôˆ 9(-ÌÁ5Ú"ø¦b)Û³nìQ´€”æCßsìÑ¢ûSeì®~™X¢°Ãÿ0ÂþTÎFÏð+‚ü!w–XN«á«3oÜ ]¤Ï­óϸӺ¤ð·²H—ÓÜq 4gcç/ÓZm'H·©M÷8EhÅ^µG#GA¢“]zl3Cù¶lÂbõšè¬+wÓìée8?xïJ¹ÊŒyq‘ Øf1¿ªÇgDãa½÷@Ø_atìÁè ÒBt}F0ØÞܶ‚AÚlñƒYƒ0ô=¼}K^¿¸³Ëüw!Xø$‘¶‚ÊZb§Ò(Gb'õbªð¹ÇãË››ÓéäŒ\–äìh}Ú+ÕBéÒ4¢U¸ù#øzdÞÈ옻‰Ø¦Nÿj:ËäÜà$±¢ÞODƒSmøZ°NÚkÓâÌåB™‹™h £Ú>‰y¨ì³Ï²‰óE‹ûÝ3WïCÊ "2¨ÈA_" ¬¦X¤“ºíR[þg8•S`õõÇq&¼Ýürwy €ÙL4Ÿ£7€3üê•àÕ³&¯)ùd A#_“¿.èD/Ÿ&¦@èILAp(Dæ.z­I˜£)÷ÙðÌ"õs!ŒF1Œ5¼×¼žv$f<±¢l>(Ú]yŒ?½Ý¬þþ ûùÚ®endstream endobj 66 0 obj 2466 endobj 4 0 obj <> /Contents 5 0 R >> endobj 13 0 obj <> /Contents 14 0 R >> endobj 18 0 obj <> /Contents 19 0 R >> endobj 24 0 obj <> /Contents 25 0 R >> endobj 29 0 obj <> /Contents 30 0 R >> endobj 34 0 obj <> /Contents 35 0 R >> endobj 39 0 obj <> /Contents 40 0 R >> endobj 44 0 obj <> /Contents 45 0 R >> endobj 49 0 obj <> /Contents 50 0 R >> endobj 54 0 obj <> /Contents 55 0 R >> endobj 59 0 obj <> /Contents 60 0 R >> endobj 64 0 obj <> /Contents 65 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 13 0 R 18 0 R 24 0 R 29 0 R 34 0 R 39 0 R 44 0 R 49 0 R 54 0 R 59 0 R 64 0 R ] /Count 12 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 11 0 obj <> endobj 12 0 obj <> endobj 16 0 obj <> endobj 17 0 obj <> endobj 22 0 obj <> endobj 23 0 obj <> endobj 27 0 obj <> endobj 28 0 obj <> endobj 32 0 obj <> endobj 33 0 obj <> endobj 37 0 obj <> endobj 38 0 obj <> endobj 42 0 obj <> endobj 43 0 obj <> endobj 47 0 obj <> endobj 48 0 obj <> endobj 52 0 obj <> endobj 53 0 obj <> endobj 57 0 obj <> endobj 58 0 obj <> endobj 62 0 obj <> endobj 63 0 obj <> endobj 67 0 obj <> endobj 68 0 obj <> endobj 10 0 obj <> endobj 69 0 obj <> endobj 21 0 obj <> endobj 70 0 obj <> endobj 9 0 obj <> endobj 71 0 obj <> endobj 8 0 obj <> endobj 72 0 obj <> endobj 73 0 obj <>stream 2014-08-03T14:49:09-04:00 2014-08-03T14:49:09-04:00 groff version 1.22.2 Untitled endstream endobj 2 0 obj <>endobj xref 0 74 0000000000 65535 f 0000048302 00000 n 0000051418 00000 n 0000048165 00000 n 0000046223 00000 n 0000000015 00000 n 0000004685 00000 n 0000048367 00000 n 0000049823 00000 n 0000049673 00000 n 0000049348 00000 n 0000048408 00000 n 0000048438 00000 n 0000046383 00000 n 0000004705 00000 n 0000010053 00000 n 0000048488 00000 n 0000048518 00000 n 0000046545 00000 n 0000010074 00000 n 0000013945 00000 n 0000049488 00000 n 0000048568 00000 n 0000048598 00000 n 0000046707 00000 n 0000013966 00000 n 0000017445 00000 n 0000048659 00000 n 0000048689 00000 n 0000046869 00000 n 0000017466 00000 n 0000019546 00000 n 0000048739 00000 n 0000048769 00000 n 0000047031 00000 n 0000019567 00000 n 0000022284 00000 n 0000048819 00000 n 0000048849 00000 n 0000047193 00000 n 0000022305 00000 n 0000026147 00000 n 0000048899 00000 n 0000048929 00000 n 0000047355 00000 n 0000026168 00000 n 0000030555 00000 n 0000048979 00000 n 0000049009 00000 n 0000047517 00000 n 0000030576 00000 n 0000034282 00000 n 0000049048 00000 n 0000049078 00000 n 0000047679 00000 n 0000034303 00000 n 0000039088 00000 n 0000049108 00000 n 0000049138 00000 n 0000047841 00000 n 0000039109 00000 n 0000043643 00000 n 0000049188 00000 n 0000049218 00000 n 0000048003 00000 n 0000043664 00000 n 0000046202 00000 n 0000049268 00000 n 0000049298 00000 n 0000049432 00000 n 0000049566 00000 n 0000049754 00000 n 0000049905 00000 n 0000049995 00000 n trailer << /Size 74 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 51572 %%EOF flawfinder-1.31/flawfinder.ps0000644003056700244210000026103512367502045017141 0ustar dwheelerDomain Users%!PS-Adobe-3.0 %%Creator: groff version 1.22.2 %%CreationDate: Sun Aug 3 14:49:09 2014 %%DocumentNeededResources: font Times-Roman %%+ font Times-Bold %%+ font Times-Italic %%+ font Symbol %%DocumentSuppliedResources: procset grops 1.22 2 %%Pages: 12 %%PageOrder: Ascend %%DocumentMedia: Default 595 842 0 () () %%Orientation: Portrait %%EndComments %%BeginDefaults %%PageMedia: Default %%EndDefaults %%BeginProlog %%BeginResource: procset grops 1.22 2 %!PS-Adobe-3.0 Resource-ProcSet /setpacking where{ pop currentpacking true setpacking }if /grops 120 dict dup begin /SC 32 def /A/show load def /B{0 SC 3 -1 roll widthshow}bind def /C{0 exch ashow}bind def /D{0 exch 0 SC 5 2 roll awidthshow}bind def /E{0 rmoveto show}bind def /F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def /G{0 rmoveto 0 exch ashow}bind def /H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /I{0 exch rmoveto show}bind def /J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def /K{0 exch rmoveto 0 exch ashow}bind def /L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /M{rmoveto show}bind def /N{rmoveto 0 SC 3 -1 roll widthshow}bind def /O{rmoveto 0 exch ashow}bind def /P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /Q{moveto show}bind def /R{moveto 0 SC 3 -1 roll widthshow}bind def /S{moveto 0 exch ashow}bind def /T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def /SF{ findfont exch [exch dup 0 exch 0 exch neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /MF{ findfont [5 2 roll 0 3 1 roll neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /level0 0 def /RES 0 def /PL 0 def /LS 0 def /MANUAL{ statusdict begin/manualfeed true store end }bind def /PLG{ gsave newpath clippath pathbbox grestore exch pop add exch pop }bind def /BP{ /level0 save def 1 setlinecap 1 setlinejoin 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 7.184(][)C F2(\255\255columns)-7.184 E F0(|)A F2A F0 7.184(][)C F2 (\255\255dataonly)-7.184 E F0(|)A F2A F0 7.184(][)C F2 (\255\255html)-7.184 E F0(|)A F2A F0 7.184(][)C F2 (\255\255immediate)-7.184 E F0(|)A F2(-i)A F0 7.184(][)C F2 (\255\255singleline)-7.184 E F0(|)A F2A F0(])A([)108 208.8 Q F2 (\255\255omittime)A F0 2.5(][)C F2(\255\255quiet)-2.5 E F0(|)A F2A F0(])A([)108 220.8 Q F2(\255\255loadhitlist=)A F3(F)A F0 2.5(][)C F2 -2.5 E -.1(ve)-.25 G(hitlist=).1 E F3(F)A F0 2.5(][)C F2 (\255\255diffhitlist=)-2.5 E F3(F)A F0(])A([)108 232.8 Q F2A F0(]) A F3 2.5([s)2.79 G(our)-2.5 E(ce code \214le or sour)-.37 E(ce r)-.37 E (oot dir)-.45 E(ectory ]+)-.37 E F1(DESCRIPTION)72 249.6 Q F0(Fla)108 261.6 Q 1.383(w\214nder searches through C/C++ source code looking for \ potential security \215a)-.15 F 3.883(ws. T)-.15 F 3.883(or)-.8 G 1.384 (un \215a)-3.883 F(w\214nder)-.15 E(,)-.4 E .509(simply gi)108 273.6 R .809 -.15(ve \215)-.25 H -.15(aw).15 G .509 (\214nder a list of directories or \214les.).15 F -.15(Fo)5.508 G 3.008 (re).15 G .508(ach directory gi)-3.008 F -.15(ve)-.25 G .508 (n, all \214les that ha).15 F .808 -.15(ve C)-.2 H .508(/C++ \214le-).15 F 1.347(name e)108 285.6 R 1.348 (xtensions in that directory \(and its subdirectories, recursi)-.15 F -.15(ve)-.25 G 1.348(ly\) will be e).15 F 3.848(xamined. Thus,)-.15 F 1.348(for most)3.848 F 1.03(projects, simply gi)108 297.6 R 1.33 -.15 (ve \215)-.25 H -.15(aw).15 G 1.03 (\214nder the name of the source code').15 F 3.53(st)-.55 G 1.03 (opmost directory \(use `)-3.53 F(`.)-.74 E 2.51 -.74('' f)-.7 H 1.03 (or the current).74 F .94(directory\), and \215a)108 309.6 R .94 (w\214nder will e)-.15 F .94(xamine all of the project')-.15 F 3.44(sC) -.55 G .94(/C++ source code.)-3.44 F .94(If you only w)5.94 F .94 (ant to ha)-.1 F -.15(ve)-.2 G F3 -.15(ch)108 321.6 S(ang).15 E(es)-.1 E F0(re)2.72 E(vie)-.25 E .22(wed, sa)-.25 F .52 -.15(ve a u)-.2 H .22 (ni\214ed dif).15 F 2.72(fo)-.25 G 2.72(ft)-2.72 G .219 (hose changes \(created by GNU "dif)-2.72 F 2.719(f-)-.25 G .219 (u" or "svn dif)-2.719 F .219(f" or "git dif)-.25 F(f"\))-.25 E (in a patch \214le and use the \255\255patch \(\255P\) option.)108 333.6 Q(Fla)108 350.4 Q .272(w\214nder will produce a list of `)-.15 F(`hits') -.74 E 2.772('\()-.74 G .272(potential security \215a)-2.772 F .273 (ws\), sorted by risk; the riskiest hits are sho)-.15 F(wn)-.25 E 2.73 (\214rst. The)108 362.4 R .23(risk le)2.73 F -.15(ve)-.25 G 2.73(li).15 G 2.73(ss)-2.73 G(ho)-2.73 E .23(wn inside square brack)-.25 F .23 (ets and v)-.1 F .229(aries from 0, v)-.25 F .229 (ery little risk, to 5, great risk.)-.15 F(This)5.229 E .373(risk le)108 374.4 R -.15(ve)-.25 G 2.873(ld).15 G .373 (epends not only on the function, b)-2.873 F .374(ut on the v)-.2 F .374 (alues of the parameters of the function.)-.25 F -.15(Fo)5.374 G 2.874 (re).15 G(xam-)-3.024 E .612(ple, constant strings are often less risk) 108 386.4 R 3.111(yt)-.15 G .611(han fully v)-3.111 F .611 (ariable strings in man)-.25 F 3.111(yc)-.15 G(onte)-3.111 E .611 (xts, and in those conte)-.15 F(xts)-.15 E .156(the hit will ha)108 398.4 R .456 -.15(ve a l)-.2 H -.25(ow).15 G .156(er risk le).25 F -.15 (ve)-.25 G 2.656(l. Fla).15 F .156(w\214nder kno)-.15 F .156 (ws about gette)-.25 F .157(xt \(a common library for internationalized) -.15 F .73 (programs\) and will treat constant strings passed through gette)108 410.4 R .73(xt as though the)-.15 F 3.23(yw)-.15 G .73 (ere constant strings; this)-3.23 F .873(reduces the number of f)108 422.4 R .873(alse hits in internationalized programs.)-.1 F(Fla)5.873 E .873(w\214nder will do the same sort of thing)-.15 F 1.06(with _T\(\) a\ nd _TEXT\(\), common Microsoft macros for handling internationalized pr\ ograms.)108 434.4 R(Fla)6.06 E(w\214nder)-.15 E 1.264 (correctly ignores most te)108 446.4 R 1.264 (xt inside comments and strings.)-.15 F 1.264(Normally \215a)6.264 F 1.264(w\214nder sho)-.15 F 1.264(ws all hits with a risk)-.25 F(le)108 458.4 Q -.15(ve)-.25 G 3.329(lo).15 G 3.329(fa)-3.329 G 3.328(tl)-3.329 G .828(east 1, b)-3.328 F .828(ut you can use the \255\255minle)-.2 F -.15(ve)-.25 G 3.328(lo).15 G .828(ption to sho)-3.328 F 3.328(wo)-.25 G .828(nly hits with higher risk le)-3.328 F -.15(ve)-.25 G .828 (ls if you).15 F 4.815(wish. Hit)108 470.4 R 2.316 (descriptions also note the rele)4.815 F -.25(va)-.25 G 2.316 (nt Common W).25 F 2.316 (eakness Enumeration \(CWE\) identi\214er\(s\) in)-.8 F (parentheses, as discussed belo)108 482.4 Q 3.8 -.65(w. F)-.25 H(la).65 E(w\214nder is of)-.15 E(\214cially CWE-Compatible.)-.25 E .734(Not e) 108 499.2 R -.15(ve)-.25 G .734 (ry hit is actually a security vulnerability).15 F 3.234(,a)-.65 G .734 (nd not e)-3.234 F -.15(ve)-.25 G .734 (ry security vulnerability is necessarily found.).15 F(Ne)108 511.2 Q -.15(ve)-.25 G .412(rtheless, \215a).15 F .412 (w\214nder can be an aid in \214nding and remo)-.15 F .413 (ving security vulnerabilities.)-.15 F 2.913(Ac)5.413 G .413(ommon w) -2.913 F .413(ay to)-.1 F .371(use \215a)108 523.2 R .371 (w\214nder is to \214rst apply \215a)-.15 F .371 (w\214nder to a set of source code and e)-.15 F .37 (xamine the highest-risk items.)-.15 F(Then,)5.37 E .714 (use \255\255inputs to e)108 535.2 R .714 (xamine the input locations, and check to mak)-.15 F 3.215(es)-.1 G .715 (ure that only le)-3.215 F -.05(ga)-.15 G 3.215(la).05 G .715 (nd safe input v)-3.215 F(alues)-.25 E (are accepted from untrusted users.)108 547.2 Q .893(Once you')108 564 R 1.193 -.15(ve a)-.5 H .892(udited a program, you can mark source code l\ ines that are actually \214ne b).15 F .892(ut cause spurious)-.2 F -.1 (wa)108 576 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 .923(arnings are)-.1 F 1.398(sup\ pressed, put a specially-formatted comment either on the same line \(af\ ter the source code\) or all by)108 588 R(itself in the pre)108 600 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 616.8 Q(// Fla)144 616.8 Q(w\214nder: ignore)-.15 E<83>108 633.6 Q (/* Fla)144 633.6 Q(w\214nder: ignore */)-.15 E -.15(Fo)108 650.4 S 2.813(rc).15 G(ompatibility')-2.813 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 .525(ted comments.)108 662.4 R .525(Since it')5.525 F 3.025(sp)-.55 G .524 (ossible that such lines are wrong, you can use the \255\255ne)-3.025 F -.15(ve)-.25 G .524(rignore option, which).15 F .958(causes \215a)108 674.4 R .958(w\214nder to ne)-.15 F -.15(ve)-.25 G 3.458(ri).15 G .958 (gnore an)-3.458 F 3.459(yl)-.15 G .959 (ine no matter what the comment directi)-3.459 F -.15(ve)-.25 G 3.459 (ss).15 G .959(ay \(more confusingly)-3.459 F(,)-.65 E108 686.4 Q -.15(ve)-.25 G(rignore ignores the ignores\).).15 E(Fla)108 703.2 Q .702(w\214nder uses an internal database called the `)-.15 F (`ruleset')-.74 E .701 ('; the ruleset identi\214es functions that are common)-.74 F 1.678 (causes of security \215a)108 715.2 R 4.178(ws. The)-.15 F 1.679 (standard ruleset includes a lar)4.178 F 1.679(ge number of dif)-.18 F 1.679(ferent potential problems,)-.25 F .028 (including both general issues that can impact an)108 727.2 R 2.528(yC) -.15 G .027(/C++ program, as well as a number of speci\214c Unix-lik) -2.528 F(e)-.1 E(Fla)72 768 Q 164.71(w\214nder 3)-.15 F(Aug 2014)2.5 E (1)205.39 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 1.054(and W)108 84 R(indo)-.4 E 1.054(ws functions that are especially problematic.)-.25 F 1.055 (The \255\255listrules option reports the list of current)6.054 F 1.075 (rules and their def)108 96 R 1.075(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.574(wf)-.15 G 1.074(ound in a gi)-3.574 F -.15(ve)-.25 G 3.574(ns).15 G(ource)-3.574 E .401(code \214le \(matching an entry in the ruleset\) is called a `)108 108 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 120 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.288 (hitlist\), reloaded back for).15 F .965 (redisplay \(using \255\255loadhitlist\), and you can sho)108 132 R 3.465(wo)-.25 G .965(nly the hits that are dif)-3.465 F .965 (ferent from another run \(using)-.25 F108 144 Q (fhitlist\).)-.25 E(Fla)108 160.8 Q .169 (w\214nder is a simple tool, leading to some fundamental pros and cons.) -.15 F(Fla)5.169 E .168(w\214nder w)-.15 F .168(orks by doing simple)-.1 F(le)108 172.8 Q .234(xical tok)-.15 F .234 (enization \(skipping comments and correctly tok)-.1 F .235 (enizing strings\), looking for tok)-.1 F .235(en matches to the)-.1 F .467(database \(particularly to \214nd function calls\).)108 184.8 R (Fla)5.466 E .466(w\214nder is thus similar to RA)-.15 F .466 (TS and ITS4, which also use)-1.11 F .573(simple le)108 196.8 R .573 (xical tok)-.15 F 3.073(enization. Fla)-.1 F .573(w\214nder then e)-.15 F .573(xamines the te)-.15 F .574 (xt of the function parameters to estimate risk.)-.15 F(Unlik)108 208.8 Q 2.958(et)-.1 G .458(ools such as splint, gcc')-2.958 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 .757 -.15(ve a)-.2 H .457(ccess to infor).15 F(-)-.2 E .052 (mation about control \215o)108 220.8 R 1.352 -.65(w, d)-.25 H .052 (ata \215o).65 F 1.353 -.65(w, o)-.25 H 2.553(rd).65 G .053 (ata types when searching for potential vulnerabilities or estimating) -2.553 F .484(the le)108 232.8 R -.15(ve)-.25 G 2.984(lo).15 G 2.984(fr) -2.984 G 2.984(isk. Thus,)-2.984 F<8d61>2.984 E .483 (w\214nder will necessarily produce man)-.15 F 2.983(yf)-.15 G .483 (alse positi)-3.083 F -.15(ve)-.25 G 2.983(sf).15 G .483 (or vulnerabilities and f)-2.983 F(ail)-.1 E .453(to report man)108 244.8 R 2.953(yv)-.15 G 2.953(ulnerabilities. On)-2.953 F .453 (the other hand, \215a)2.953 F .454 (w\214nder can \214nd vulnerabilities in programs that can-)-.15 F .255 (not be b)108 256.8 R .255(uilt or cannot be link)-.2 F 2.755(ed. It)-.1 F .255(can often w)2.755 F .254(ork with programs that cannot e)-.1 F -.15(ve)-.25 G 2.754(nb).15 G 2.754(ec)-2.754 G .254 (ompiled \(at least by)-2.754 F .618(the re)108 268.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 .367(more sophisticated tools ha)108 280.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 292.8 Q(An)108 309.6 Q 2.756<798c>-.15 G .256 (lename gi)-2.756 F -.15(ve)-.25 G 2.756(no).15 G 2.756(nt)-2.756 G .257 (he command line will be e)-2.756 F .257(xamined \(e)-.15 F -.15(ve)-.25 G 2.757(ni).15 G 2.757(fi)-2.757 G 2.757(td)-2.757 G(oesn')-2.757 E 2.757(th)-.18 G -2.25 -.2(av e)-2.757 H 2.757(au)2.957 G .257 (sual C/C++ \214lename)-2.757 F -.15(ex)108 321.6 S .198 (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 .197 (peci\214c \214les you desire.)-2.697 F .197(While searching directo-) 5.197 F 1.602(ries recursi)108 333.6 R -.15(ve)-.25 G(ly).15 E 4.102 <2c8d>-.65 G -.15(aw)-4.102 G 1.602(\214nder only opens and e).15 F 1.602(xamines re)-.15 F 1.602(gular \214les that ha)-.15 F 1.903 -.15 (ve C)-.2 H 1.603(/C++ \214lename e).15 F(xtensions.)-.15 E(Fla)108 345.6 Q .917(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 .916 (xtensions ".c", ".h", ".ec", ".ecp", ".pgc",)-.15 F .963 (".C", ".cpp", ".CPP", ".cxx", ".cc", ".CC", ".pcc", ".hpp", or ".H".) 108 357.6 R .964(The \214lename `)5.963 F(`\255')-.74 E 3.464('m)-.74 G .964(eans the standard)-3.464 F 2.82(input. T)108 369.6 R 2.82(op)-.8 G (re)-2.82 E -.15(ve)-.25 G .32 (nt security problems, special \214les \(such as de).15 F .32 (vice special \214les and named pipes\) are al)-.25 F -.1(wa)-.1 G(ys).1 E(skipped, and by def)108 381.6 Q (ault symbolic links are skipped \(the \255\255allo)-.1 E (wlink option follo)-.25 E(ws symbolic links\).)-.25 E .375(After the l\ ist of hits is a brief summary of the results \(use -D to remo)108 398.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 410.4 R .793(ysical source lines of code \(SLOC\) ana-)-.05 F 3.262 (lyzed. A)108 422.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 434.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 446.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 458.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 470.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 482.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 494.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 506.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 518.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 530.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 542.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 554.4 Q(Fla)108 571.2 Q (w\214nder is released under the GNU GPL license v)-.15 E (ersion 2 or later \(GPLv2+\).)-.15 E(Fla)108 588 Q .047(w\214nder w) -.15 F .046(orks similarly to another program, ITS4, which is not fully\ open source softw)-.1 F .046(are \(as de\214ned in)-.1 F .187 (the Open Source De\214nition\) nor free softw)108 600 R .188 (are \(as de\214ned by the Free Softw)-.1 F .188(are F)-.1 F 2.688 (oundation\). The)-.15 F .188(author of)2.688 F(Fla)108 612 Q (w\214nder has ne)-.15 E -.15(ve)-.25 G 2.5(rs).15 G(een ITS4')-2.5 E 2.5(ss)-.55 G(ource code.)-2.5 E/F2 10.95/Times-Bold@0 SF(BRIEF TUT)72 640.8 Q(ORIAL)-.197 E F0(Here')108 652.8 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 664.8 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 676.8 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 688.8 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 705.6 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 717.6 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 729.6 Q(`less')-.74 E 2.5('j)-.74 G (ust mak)-2.5 E(es sure the results stay on the screen\):)-.1 E(Fla)72 768 Q 164.71(w\214nder 3)-.15 F(Aug 2014)2.5 E(2)205.39 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<8d61>144 84 Q (w\214nder xyzzy | less)-.15 E .615(At this point, you will see a lar) 108 112.8 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 124.8 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 136.8 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 148.8 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 160.8 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 172.8 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 184.8 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 1.112 (understand the error message, please see documents such as the)108 196.8 R/F1 10/Times-Italic@0 SF 1.112(Writing Secur)3.402 F 3.612(eP) -.37 G -1.7 -.45(ro g)-3.612 H -.15(ra).45 G 1.112(ms for Linux and).15 F 2.08(Unix HO)108 208.8 R(WT)-.5 E(O)-.18 E/F2 10/Symbol SF4.85 E F0(http://www)A(.dwheeler)-.65 E(.com/secure-programs)-.55 E F2A F0 2.08(at http://www)4.58 F(.dwheeler)-.65 E(.com/secure-programs)-.55 E (which pro)108 220.8 Q (vides more information on writing secure programs.)-.15 E .722 (Once you identify the problem and understand it, you can \214x it.)108 237.6 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 249.6 R F1 (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 261.6 Q(ferent vulnerability)-.25 E(.) -.65 E .516(If you')108 278.4 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 290.4 Q(fending line a comment lik)-.25 E(e)-.1 E(/* Fla)146.5 302.4 Q (w\214nder: ignore */)-.15 E(to k)108 314.4 Q(eep them from sho)-.1 E (wing up in the output.)-.25 E .397(Once you')108 331.2 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 343.2 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 355.2 Q 2.5(et)-.1 G(his:)-2.5 E<8d61>144 367.2 Q (w\214nder \255\255inputs xyzzy)-.15 E(Fla)108 384 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 396 Q(Fla)108 412.8 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 424.8 Q(The ne)5 E(xt section describes those options in more detail.) -.15 E/F3 10.95/Times-Bold@0 SF(OPTIONS)72 453.6 Q F0(Fla)108 465.6 Q .187(w\214nder has a number of options, which can be grouped into optio\ ns that control its o)-.15 F .187(wn documentation,)-.25 F 1.272 (select input data, select which hits to display)108 477.6 R 3.772(,s) -.65 G 1.272(elect the output format, and perform hitlist management.) -3.772 F(Fla)108 489.6 Q .157(w\214nder supports the standard syntax de\ \214ned in the POSIX \(Issue 7, 2013 Edition\) section `)-.15 F .158 (`Utility Con-)-.74 F -.15(ve)108 501.6 S(ntions').15 E 2.672('. It)-.74 F .172(also supports the GNU long options \(double-dash options of form\ \255\255)2.672 F F1(option)A F0 2.672(\)a)C 2.672(sd)-2.672 G .171 (e\214ned in the)-2.672 F F1 .288(GNU C Libr)108 513.6 R .288(ary Refer) -.15 F .288(ence Manual)-.37 F F0 -.74(``)2.788 G .288(Program Ar).74 F .288(gument Syntax Con)-.18 F -.15(ve)-.4 G(ntions').15 E 2.789('a)-.74 G(nd)-2.789 E F1 .289(GNU Coding Standar)2.789 F(ds)-.37 E F0 -.74(``) 108 525.6 S .116(Standards for Command Line Interf).74 F(aces')-.1 E 2.616('. Long)-.74 F .115(option ar)2.615 F .115(guments can be pro)-.18 F .115(vided as `)-.15 F(`--name=v)-.74 E(alue')-.25 E 2.615('o)-.74 G (r)-2.615 E -.74(``)108 537.6 S 1.198(-name v).74 F(alue')-.25 E 3.698 ('. Some)-.74 F 1.199(options can only be accessed using the more reada\ ble GNU long option con)3.698 F -.15(ve)-.4 G(n-).15 E(tions; common op\ tions are also supported by the older single-letter option con)108 549.6 Q -.15(ve)-.4 G(ntion.).15 E/F4 10/Times-Bold@0 SF(Documentation)87 578.4 Q(\255\255help)108 590.4 Q108 607.2 Q F0(Sho)168 607.2 Q 2.5 (wu)-.25 G(sage \(help\) information.)-2.5 E F4108 636 Q(ersion) -.1 E F0(Sho)168 636 Q(ws \(just\) the v)-.25 E(ersion number and e)-.15 E(xits.)-.15 E F4(\255\255listrules)108 664.8 Q F0 2.075 (List the terms \(tok)168 664.8 R 2.075(ens\) that trigger further e)-.1 F 2.075(xamination, their def)-.15 F 2.074(ault risk le)-.1 F -.15(ve) -.25 G 2.074(l, and the).15 F(def)168 676.8 Q .03(ault w)-.1 F .03(arni\ ng \(including the CWE identi\214er\(s\), if applicable\), all tab-sepa\ rated.)-.1 F .03(The terms)5.03 F .067 (are primarily names of potentially-dangerous functions.)168 688.8 R .066(Note that the reported risk le)5.067 F -.15(ve)-.25 G 2.566(la).15 G(nd)-2.566 E -.1(wa)168 700.8 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 712.8 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 724.8 Q(ault w)-.1 E(arning \214eld.)-.1 E(Fla)72 768 Q 164.71(w\214nder 3) -.15 F(Aug 2014)2.5 E(3)205.39 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 SF (Selecting Input Data)87 84 Q(\255\255allo)108 96 Q(wlink)-.1 E F0(Allo) 168 96 Q 2.673(wt)-.25 G .173 (he use of symbolic links; normally symbolic links are skipped.)-2.673 F (Don')5.174 E 2.674(tu)-.18 G .174(se this option)-2.674 F .355(if you') 168 108 R .355(re analyzing code by others; attack)-.5 F .355 (ers could do man)-.1 F 2.855(yt)-.15 G .354 (hings to cause problems for an)-2.855 F 1.083 (analysis with this option enabled.)168 120 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 132 R -.1(wo)168 144 S .428(uld cause \215a).1 F .428 (w\214nder to run `)-.15 F(`fore)-.74 E -.15(ve)-.25 G(r').15 E 2.928 ('. Another)-.74 F .429(problem with enabling this option is that)2.928 F .542(if the same \214le is referenced multiple times using symbolic l\ inks, it will be analyzed multi-)168 156 R 1.525 (ple times \(and thus reported multiple times\).)168 168 R 1.525 (Note that \215a)6.525 F 1.525(w\214nder already includes some)-.15 F 2.957(protection ag)168 180 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 192 Q 1.218 (v/zero or C:\\mystuf)-.25 F 3.718(f\\com1\). Note)-.25 F 1.218 (that for \215a)3.718 F 1.218(w\214nder v)-.15 F 1.219 (ersion 1.01 and before, this w)-.15 F(as)-.1 E(the def)168 204 Q(ault.) -.1 E F1108 232.8 Q(ollo)-.25 E(wdotdir)-.1 E F0 .57 (Enter directories whose names be)168 244.8 R .57(gin with ".".)-.15 F .57(Normally such directories are ignored, since)5.57 F(the)168 256.8 Q 2.654(yn)-.15 G .154(ormally include v)-2.654 F .154(ersion control pri) -.15 F -.25(va)-.25 G .155 (te data \(such as .git/ or .svn/\), con\214gurations, and).25 F(so on.) 168 268.8 Q F1(\255\255nolink)108 297.6 Q F0 5.297 (Ignored. Historically)168 297.6 R 2.797(this disabled follo)5.297 F 2.796(wing symbolic links; this beha)-.25 F 2.796(vior is no)-.2 F 5.296 (wt)-.25 G(he)-5.296 E(def)168 309.6 Q(ault.)-.1 E F1(\255\255patch=)108 338.4 Q/F2 10/Times-Italic@0 SF(patc)A(h\214le)-.15 E F1108 355.2 Q F2(patc)2.5 E(h\214le)-.15 E F0 .227 (Examine the selected \214les or directories, b)168 355.2 R .228 (ut only report hits in lines that are added or modi-)-.2 F .421 (\214ed by the gi)168 367.2 R -.15(ve)-.25 G 2.921(np).15 G .421 (atch \214le.)-2.921 F .42 (The patch \214le must be in a recognized uni\214ed dif)5.421 F 2.92(ff) -.25 G .42(ormat \(e.g.,)-2.92 F .154(the output of GNU "dif)168 379.2 R 2.654(f-)-.25 G 2.655(uo)-2.654 G .155(ld ne)-2.655 F .155(w", "svn dif) -.25 F .155(f", or "git dif)-.25 F 2.655(f[)-.25 G 2.655 (commit]"\). Fla)-2.655 F .155(w\214nder assumes)-.15 F .546 (that the patch has already been applied to the \214les.)168 391.2 R .546(The patch \214le can also include changes)5.546 F .297(to irrele) 168 403.2 R -.25(va)-.25 G .297(nt \214les \(the).25 F 2.797(yw)-.15 G .297(ill simply be ignored\).)-2.797 F .298(The line numbers gi)5.297 F -.15(ve)-.25 G 2.798(ni).15 G 2.798(nt)-2.798 G .298 (he patch \214le are)-2.798 F 1.605 (used to determine which lines were changed, so if you ha)168 415.2 R 1.904 -.15(ve m)-.2 H 1.604(odi\214ed the \214les since the).15 F .583 (patch \214le w)168 427.2 R .583(as created, re)-.1 F .583 (generate the patch \214le \214rst.)-.15 F(Be)5.583 E -.1(wa)-.25 G .583 (re that the \214le names of the ne).1 F(w)-.25 E .468(\214les gi)168 439.2 R -.15(ve)-.25 G 2.968(ni).15 G 2.968(nt)-2.968 G .468 (he patch \214le must match e)-2.968 F(xactly)-.15 E 2.968(,i)-.65 G .468(ncluding upper/lo)-2.968 F .468(wer case, path pre\214x, and)-.25 F .193(directory separator \(\\ vs. /\).)168 451.2 R .194 (Only uni\214ed dif)5.194 F 2.694(ff)-.25 G .194 (ormat is accepted \(GNU dif)-2.694 F .194(f, svn dif)-.25 F .194 (f, and git)-.25 F(dif)168 463.2 Q 3.372(fo)-.25 G .872 (utput is okay\); if you ha)-3.372 F 1.171 -.15(ve a d)-.2 H(if).15 E .871(ferent format, ag)-.25 F .871(ain re)-.05 F .871 (generate it \214rst.)-.15 F .871(Only hits that)5.871 F .522 (occur on resultant changed lines, or immediately abo)168 475.2 R .822 -.15(ve a)-.15 H .522(nd belo).15 F 3.023(wt)-.25 G .523 (hem, are reported.)-3.023 F(This)5.523 E(option implies \255\255ne)168 487.2 Q -.15(ve)-.25 G(rignore.).15 E F1(Selecting Hits to Display)87 528 Q(\255\255inputs)108 540 Q108 556.8 Q F0(Sho)144 556.8 Q 2.5 (wo)-.25 G(nly functions that obtain data from outside the program; thi\ s 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 585.6 Q -.1(ve)-.15 G(l=).1 E F2(X)A F1(-m) 108 602.4 Q F2(X)2.5 E F0 .499(Set minimum risk le)144 602.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 614.4 Q('\); the def) -.74 E(ault is 1.)-.1 E F1(\255\255falsepositi)108 643.2 Q -.1(ve)-.1 G 108 660 Q F0 .437(Do not include hits that are lik)144 660 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 672 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 684 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 696 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 708 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 720 Q(Fla)72 768 Q 164.71(w\214nder 3)-.15 F(Aug 2014)2.5 E(4)205.39 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 108 84 Q -.1(ve)-.15 G(rignor).1 E(e)-.18 E(-n)108 100.8 Q F0(Ne)144 100.8 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 129.6 Q (egexp=)-.18 E/F2 10/Times-Italic@0 SF -1.07 -.9(PA T)D(TERN).9 E F1(-e) 108 146.4 Q F2 -1.07 -.9(PA T)2.5 H(TERN).9 E F0 .413 (Only report hits with te)144 158.4 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 170.4 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 182.4 Q F1(Selecting Output F)87 223.2 Q(ormat)-.25 E(\255\255columns)108 235.2 Q108 252 Q F0(Sho)168 252 Q 4.024(wt)-.25 G 1.524(he column number \(as well as the \214le name a\ nd line number\) of each hit; this is)-4.024 F(sho)168 264 Q .609(wn af\ ter the line number by adding a colon and the column number in the line\ \(the \214rst)-.25 F .562(character in a line is column number 1\).)168 276 R .562(This is useful for editors that can jump to speci\214c)5.562 F 1.374(columns, or for inte)168 288 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 300 Q -.15(ve)-.25 G(s\).).15 E F1 (\255\255context)108 328.8 Q108 345.6 Q F0(Sho)168 345.6 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 357.6 Q(arning.)-.1 E F1(\255\255dataonly) 108 386.4 Q108 403.2 Q F0(Don')168 403.2 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 432 Q108 448.8 Q F0 -.15(Fo)168 448.8 S (rmat the output as HTML instead of as simple te).15 E(xt.)-.15 E F1 (\255\255immediate)108 477.6 Q(-i)108 494.4 Q F0 (Immediately display hits \(don')168 494.4 Q 2.5(tj)-.18 G(ust w)-2.5 E (ait until the end\).)-.1 E F1(\255\255singleline)108 523.2 Q(-S)108 540 Q F0 1.267(Display as single line of te)168 540 R 1.267 (xt output for each hit.)-.15 F 1.267 (Useful for interacting with compilation)6.267 F(tools.)168 552 Q F1 (\255\255omittime)108 580.8 Q F0 .82(Omit timing information.)168 580.8 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 592.8 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 621.6 Q 108 638.4 Q F0(Don')168 638.4 Q 3.152(td)-.18 G .652 (isplay status information \(i.e., which \214les are being e)-3.152 F .653(xamined\) while the analysis is)-.15 F(going on.)168 650.4 Q F1 (Hitlist Management)87 691.2 Q108 703.2 Q -.1(ve)-.25 G (hitlist=).1 E F2(F)A F0(Sa)168 715.2 Q .3 -.15(ve a)-.2 H (ll resulting hits \(the "hitlist"\) to F).15 E(.)-.8 E(Fla)72 768 Q 164.71(w\214nder 3)-.15 F(Aug 2014)2.5 E(5)205.39 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/F1 10/Times-Bold@0 SF (\255\255loadhitlist=)108 84 Q/F2 10/Times-Italic@0 SF(F)A F0 .44 (Load the hitlist from F instead of analyzing source programs.)168 96 R -.8(Wa)5.44 G .44(rning: Do).8 F F2(not)2.94 E F0 .44(load hitlists)2.94 F(from untrusted sources \(for security reasons\).)168 108 Q F1 (\255\255diffhitlist=)108 136.8 Q F2(F)A F0(Sho)168 148.8 Q 3.539(wo) -.25 G 1.039(nly hits \(loaded or analyzed\) not in F)-3.539 F 6.039(.F) -.8 G -.1(wa)-2.5 G 3.54(sp).1 G 1.04(resumably created pre)-3.54 F 1.04 (viously using)-.25 F168 160.8 Q -.15(ve)-.2 G 2.866 (hitlist. W).15 F .366(arning: Do)-.8 F F2(not)2.866 E F0(dif)2.866 E 2.866(fh)-.25 G .366 (itlists from untrusted sources \(for security reasons\).)-2.866 F(If) 5.365 E .668(the \255\255loadhitlist option is not pro)168 172.8 R .668 (vided, this will sho)-.15 F 3.168(wt)-.25 G .668 (he hits in the analyzed source code)-3.168 F .144 (\214les that were not pre)168 184.8 R .144(viously stored in F)-.25 F 5.144(.I)-.8 G 2.644(fu)-5.144 G .144 (sed along with \255\255loadhitlist, this will sho)-2.644 F 2.643(wt) -.25 G(he)-2.643 E .094(hits in the loaded hitlist not in F)168 196.8 R 5.094(.T)-.8 G .094(he dif)-5.094 F .095(ference algorithm is conserv) -.25 F(ati)-.25 E -.15(ve)-.25 G 2.595(;h).15 G .095(its are only con-) -2.595 F .684(sidered the `)168 208.8 R(`same')-.74 E 3.183('i)-.74 G 3.183(ft)-3.183 G(he)-3.183 E 3.183(yh)-.15 G -2.25 -.2(av e)-3.183 H .683(the same \214lename, line number)3.383 F 3.183(,c)-.4 G .683 (olumn position, function)-3.183 F(name, and risk le)168 220.8 Q -.15 (ve)-.25 G(l.).15 E/F3 10.95/Times-Bold@0 SF(EXAMPLES)72 261.6 Q F0 .225 (Here are v)108 273.6 R .225(arious e)-.25 F .225(xamples of ho)-.15 F 2.725(wt)-.25 G 2.725(oi)-2.725 G -1.9 -.4(nv o)-2.725 H .425 -.1 (ke \215).4 H -.15(aw).1 G(\214nder).15 E 5.225(.T)-.55 G .225 (he \214rst e)-5.225 F .226(xamples sho)-.15 F 2.726(wv)-.25 G .226 (arious simple command-)-2.976 F 1.274(line options.)108 285.6 R(Fla) 6.274 E 1.274(w\214nder is designed to w)-.15 F 1.274(ork well with te) -.1 F 1.273(xt editors and inte)-.15 F 1.273(grated de)-.15 F -.15(ve) -.25 G 1.273(lopment en).15 F(viron-)-.4 E(ments, so the ne)108 297.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 326.4 Q(\215aw\214nder /usr/sr)108 338.4 Q(c/linux-3.16)-.18 E F0 1.705(Examine all the C/C++ \214les in the dir\ ectory /usr/src/linux-3.16 and all its subdirectories)168 350.4 R (\(recursi)168 362.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 374.4 Q F1 (\215aw\214nder \255\255minle)108 403.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 415.2 R -.15(ve)-.25 G .154(ly\); only).15 F (report vulnerabilities le)168 427.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 456 Q F0 1.03(E\ xamine all the C/C++ \214les in mydir and its subdirectories \(recursi) 168 468 R -.15(ve)-.25 G 1.03(ly\), and report func-).15 F (tions that tak)168 480 Q 2.5(ei)-.1 G (nputs \(so that you can ensure that the)-2.5 E 2.5<798c>-.15 G (lter the inputs appropriately\).)-2.5 E F1(\215aw\214nder \255\255ne) 108 508.8 Q -.1(ve)-.15 G(rignor).1 E 2.5(em)-.18 G(ydir)-2.5 E F0 .3(E\ xamine all the C/C++ \214les in the directory mydir and its subdirector\ ies, including e)168 520.8 R -.15(ve)-.25 G 2.8(nt).15 G(he)-2.8 E (hits mark)168 532.8 Q(ed for ignoring in the code comments.)-.1 E F1 (\215aw\214nder \255QD mydir)108 561.6 Q F0 .093 (Examine mydir and report only the actual results \(remo)168 573.6 R .092(ving the header and footer of the out-)-.15 F 2.602(put\). This)168 585.6 R .103(form is useful if the output will be piped into other tool\ s for further analysis.)2.603 F(The)5.103 E .78(\255C \(\255\255columns\ \) and \255S \(\255\255singleline\) options can also be useful if you') 168 597.6 R .78(re piping the data)-.5 F(into other tools.)168 609.6 Q F1(\215aw\214nder \255QDSC mydir)108 638.4 Q F0 .553(Examine mydir)168 650.4 R 3.053(,r)-.4 G .553 (eporting only the actual results \(no header or footer\).)-3.053 F .554 (Each hit is reported)5.554 F 1.12 (on one line, and column numbers are reported.)168 662.4 R 1.119 (This can be a useful command if you are)6.119 F(feeding \215a)168 674.4 Q(w\214nder output to other tools.)-.15 E F1 (\215aw\214nder \255\255quiet \255\255html \255\255context mydir > r)108 703.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 715.2 R 3.358(HTML formatted v)168 727.2 R 3.357(ersion of the results.)-.15 F 3.357(Source code management systems \(such as)8.357 F(Fla)72 768 Q 164.71(w\214nder 3)-.15 F(Aug 2014)2.5 E(6)205.39 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(SourceF)168 84 Q(or)-.15 E (ge and Sa)-.18 E -.25(va)-.2 G(nnah\) might use a command lik).25 E 2.5 (et)-.1 G(his.)-2.5 E/F1 10/Times-Bold@0 SF (\215aw\214nder \255\255quiet \255\255sa)108 112.8 Q -.1(ve)-.25 G (hitlist sa).1 E -.1(ve)-.25 G(d.hits *.[ch]).1 E F0 .406 (Examine all .c and .h \214les in the current directory)168 124.8 R 5.406(.D)-.65 G(on')-5.406 E 2.906(tr)-.18 G .407 (eport on the status of processing,)-2.906 F(and sa)168 136.8 Q .3 -.15 (ve t)-.2 H (he resulting hitlist \(the set of all hits\) in the \214le sa).15 E -.15(ve)-.2 G(d.hits.).15 E F1(\215aw\214nder \255\255diffhitlist sa)108 165.6 Q -.1(ve)-.25 G(d.hits *.[ch]).1 E F0 .325 (Examine all .c and .h \214les in the current directory)168 177.6 R 2.825(,a)-.65 G .325(nd sho)-2.825 F 2.825(wa)-.25 G .624 -.15(ny h) -2.825 H .324(its that weren').15 F 2.824(ta)-.18 G .324(lready in) -2.824 F .92(the \214le sa)168 189.6 R -.15(ve)-.2 G 3.42(d.hits. This) .15 F .921(can be used to sho)3.42 F 3.421(wo)-.25 G .921(nly the `) -3.421 F(`ne)-.74 E(w')-.25 E 3.421('v)-.74 G .921 (ulnerabilities in a modi\214ed)-3.421 F(program, if sa)168 201.6 Q -.15 (ve)-.2 G(d.hits w).15 E(as created from the older v)-.1 E (ersion of the program being analyzed.)-.15 E F1 (\215aw\214nder \255\255patch r)108 230.4 Q(ecent.patch .)-.18 E F0 .642 (Examine the current directory recursi)168 242.4 R -.15(ve)-.25 G(ly).15 E 3.142(,b)-.65 G .641(ut only report lines that were changed or added) -3.342 F(in the already-applied patch\214le named)168 254.4 Q/F2 10 /Times-Italic@0 SF -.37(re)2.5 G(cent.patc).37 E(h)-.15 E F0(.)A F1 (\215aw\214nder \255\255r)108 283.2 Q(egex "CWE-120|CWE-126" sr)-.18 E (c/)-.18 E F0(Examine directory)168 295.2 Q F2(sr)2.5 E(c)-.37 E F0 (recursi)2.5 E -.15(ve)-.25 G(ly).15 E 2.5(,b)-.65 G (ut only report hits where CWE-120 or CWE-126 apply)-2.7 E(.)-.65 E F1 (In)87 324 Q -.1(vo)-.4 G(king fr).1 E(om vim)-.18 E F0 .177(The te)108 336 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 348 Q 2.5(wt)-.25 G(he w)-2.5 E(arning messages and jump to the rele)-.1 E -.25(va)-.25 G (nt source code.).25 E .323(First, you need to in)108 364.8 R -.2(vo)-.4 G .523 -.1(ke \215).2 H -.15(aw).1 G .322 (\214nder to create a list of hits, and there are tw).15 F 2.822(ow)-.1 G .322(ays to do this.)-2.922 F .322(The \214rst w)5.322 F(ay)-.1 E .218 (is to start \215a)108 376.8 R .218 (w\214nder \214rst, and then \(using its output\) in)-.15 F -.2(vo)-.4 G .418 -.1(ke v).2 H 2.718(im. The).1 F .218(second w)2.718 F .218 (ay is to start \(or continue to)-.1 F(run\) vim, and then in)108 388.8 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 405.6 S 3.072 (rt).15 G .572(he \214rst w)-3.072 F(ay)-.1 E 3.072(,r)-.65 G .572 (un \215a)-3.072 F .572(w\214nder and store its output in some FLA)-.15 F .572(WFILE \(say "\215a)-.9 F .571(w\214le"\), then in)-.15 F -.2(vo) -.4 G .771 -.1(ke v).2 H(im).1 E .485(using its -q option, lik)108 417.6 R 2.986(et)-.1 G .486(his: "vim -q \215a)-2.986 F 2.986(w\214le". The) -.15 F .486(second w)2.986 F .486(ay \(starting \215a)-.1 F .486 (w\214nder after starting vim\) can)-.15 F 1.018(be done a le)108 429.6 R 1.018(gion of w)-.15 F 3.518(ays. One)-.1 F 1.018(is to in)3.518 F -.2 (vo)-.4 G 1.217 -.1(ke \215).2 H -.15(aw).1 G 1.017 (\214nder using a shell command, ":!\215a).15 F(w\214nder)-.15 E 1.017 (-command >)-.2 F(FLA)108 441.6 Q .251(WFILE", then follo)-.9 F 2.751 (wt)-.25 G .251(hat with the command ":cf FLA)-2.751 F 2.751 (WFILE". Another)-.9 F -.1(wa)2.751 G 2.752(yi).1 G 2.752(st)-2.752 G 2.752(os)-2.752 G .252(tore the \215a)-2.752 F(w\214nder)-.15 E (command in your mak)108 453.6 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 470.4 R .417 (w\214nder to run.)-.15 F 2.917(Ap)5.417 G .417 (lausible command, which places each hit)-2.917 F(in its o)108 482.4 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 (\215aw\214nder \255SQD .)108 499.2 Q F0 -1.1(Yo)108 528 S 2.96(uc)1.1 G .46(an no)-2.96 F 2.96(wu)-.25 G .46(se v)-2.96 F .46 (arious editing commands to vie)-.25 F 2.96(wt)-.25 G .46(he results.) -2.96 F .46(The command ":cn" displays the ne)5.46 F .46(xt hit;)-.15 F .012(":cN" displays the pre)108 540 R .012(vious hit, and ":cr" re)-.25 F .012(winds back to the \214rst hit.)-.25 F .011 (":copen" will open a windo)5.011 F 2.511(wt)-.25 G 2.511(os)-2.511 G (ho)-2.511 E(w)-.25 E .202 (the current list of hits, called the "quick\214x windo)108 552 R .202 (w"; ":cclose" will close the quick\214x windo)-.25 F 4.003 -.65(w. I) -.25 H 2.703(ft).65 G .203(he b)-2.703 F(uf)-.2 E(fer)-.25 E .25 (in the used windo)108 564 R 2.75(wh)-.25 G .25(as changed, and the err\ or 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 576 Q 2.587(es)-.1 G .087(ure the windo)-2.587 F 2.587(wc)-.25 G .087 (ontains a b)-2.587 F(uf)-.2 E .088 (fer which can be abandoned before trying to jump to a ne)-.25 F 2.588 <778c>-.25 G .088(le, say by)-2.588 F(sa)108 588 Q (ving the \214le; this pre)-.2 E -.15(ve)-.25 G (nts accidental data loss.).15 E F1(In)87 616.8 Q -.1(vo)-.4 G(king fr) .1 E(om emacs)-.18 E F0 .27(The te)108 628.8 R .269(xt editor / operati\ ng system emacs includes "grep mode" and "compile mode" mechanisms that\ w)-.15 F(ork)-.1 E .824(well with \215a)108 640.8 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 652.8 Q 2.5(yp)-.15 G (roblems you \214nd.)-2.5 E 1.427(First, you need to in)108 669.6 R -.2 (vo)-.4 G 1.627 -.1(ke \215).2 H -.15(aw).1 G 1.427 (\214nder to create a list of w).15 F 1.427(arning messages.)-.1 F -1.1 (Yo)6.426 G 3.926(uc)1.1 G 1.426(an use "grep mode" or)-3.926 F 2.645 ("compile mode" to create this list.)108 681.6 R 2.645 (Often "grep mode" is more con)7.645 F -.15(ve)-.4 G 2.646 (nient; it lea).15 F -.15(ve)-.2 G 5.146(sc).15 G 2.646(ompile mode) -5.146 F .537(untouched so you can easily recompile once you')108 693.6 R .837 -.15(ve c)-.5 H .537(hanged something.).15 F(Ho)5.537 E(we)-.25 E -.15(ve)-.25 G 1.337 -.4(r, i).15 H 3.037(fy).4 G .537(ou w)-3.037 F .536(ant to jump to)-.1 F .509(the e)108 705.6 R .509 (xact column position of a hit, compile mode may be more con)-.15 F -.15 (ve)-.4 G .51(nient because emacs can use the col-).15 F (umn output of \215a)108 717.6 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(Fla)72 768 Q 164.71 (w\214nder 3)-.15 F(Aug 2014)2.5 E(7)205.39 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 2.065 -.8(To u)108 84 T .465(s\ e grep mode, enter the command "M-x grep" and then enter the needed \ \215a).8 F .464(w\214nder command.)-.15 F 2.064 -.8(To u)5.464 H(se).8 E 1.307(compile mode, enter the command "M-x compile" and enter the neede\ d \215a)108 96 R 1.308(w\214nder command.)-.15 F 1.308(This is a)6.308 F (meta-k)108 108 Q .437 -.15(ey c)-.1 H .137(ommand, so you').15 F .137 (ll need to use the meta k)-.1 F .437 -.15(ey f)-.1 H .137(or your k).15 F -.15(ey)-.1 G .137(board \(this is usually the ESC k).15 F -.15(ey)-.1 G 2.636(\). As).15 F 1.015(with all emacs commands, you')108 120 R 1.016 (ll need to press RETURN after typing "grep" or "compile".)-.1 F 1.016 (So on man)6.016 F(y)-.15 E(systems, the grep mode is in)108 132 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 148.8 S 3.564(ut)1.1 G 1.063(hen need to enter a command, remo)-3.564 F 1.063(ving whate)-.15 F -.15(ve)-.25 G 3.563(rw).15 G 1.063(as there before if necessary)-3.663 F 6.063(.A)-.65 G 1.063(plausible com-)-2.5 F(mand is:)108 160.8 Q/F1 10 /Times-Bold@0 SF(\215aw\214nder \255SQDC .)108 177.6 Q F0 .134 (This command mak)108 194.4 R .134(es e)-.1 F -.15(ve)-.25 G .135 (ry hit report a single line, which is much easier for tools to handle.) .15 F .135(The quiet and)5.135 F .546(dataonly options remo)108 206.4 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 218.4 Q(ws.)-.15 E 1.311(Once you')108 235.2 R 1.611 -.15(ve i)-.5 H -1.9 -.4 (nv o).15 H -.1(ke).4 G 3.811<648d>.1 G -.15(aw)-3.811 G(\214nder).15 E 3.811(,y)-.4 G 1.311(ou can use emacs to jump around in its results.) -3.811 F 1.312(The command C-x \222)6.311 F 1.248 (\(Control-x backtick\) visits the source code location for the ne)108 247.2 R 1.247(xt w)-.15 F 1.247(arning message.)-.1 F 1.247 (C-u C-x \222 \(control-u)6.247 F .807 (control-x backtick\) restarts from the be)108 259.2 R 3.307(ginning. Y) -.15 F .807(ou can visit the source for an)-1.1 F 3.308(yp)-.15 G .808 (articular error message)-3.308 F 1.641(by mo)108 271.2 R 1.641 (ving to that hit message in the *compilation* b)-.15 F(uf)-.2 E 1.64 (fer or *grep* b)-.25 F(uf)-.2 E 1.64(fer and typing the return k)-.25 F -.15(ey)-.1 G(.)-.5 E(\(T)108 283.2 Q 2.852 (echnical note: in the compilation b)-.7 F(uf)-.2 E(fer)-.25 E 5.352(,t) -.4 G 2.852(his in)-5.352 F -.2(vo)-.4 G -.1(ke).2 G 5.352(sc).1 G (ompile-goto-error)-5.352 E 5.352(.\) Y)-.55 F 2.853 (ou can also click the)-1.1 F(Mouse-2 b)108 295.2 Q (utton on the error message \(you don')-.2 E 2.5(tn)-.18 G (eed to switch to the *compilation* b)-2.5 E(uf)-.2 E(fer \214rst\).) -.25 E .238(If you w)108 312 R .238 (ant to use grep mode to jump to speci\214c columns of a hit, you')-.1 F .237(ll need to specially con\214gure emacs)-.1 F 1.278(to do this.)108 324 R 2.878 -.8(To d)6.278 H 3.779(ot).8 G 1.279 (his, modify the emacs v)-3.779 F 1.279(ariable "grep-re)-.25 F(ge)-.15 E 3.779(xp-alist". This)-.15 F -.25(va)3.779 G 1.279 (riable tells Emacs ho).25 F 3.779(wt)-.25 G(o)-3.779 E .349 (parse output of a "grep" command, similar to the v)108 336 R .348 (ariable "compilation-error)-.25 F(-re)-.2 E(ge)-.15 E .348 (xp-alist" which lists v)-.15 F(ari-)-.25 E (ous formats of compilation error messages.)108 348 Q F1(In)87 376.8 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 388.8 S 2.5(r\().15 G(other\) IDEs, consult your IDE')-2.5 E 2.5(ss)-.55 G (et of plug-ins.)-2.5 E/F2 10.95/Times-Bold@0 SF (COMMON WEAKNESS ENUMERA)72 417.6 Q(TION \(CWE\))-1.04 E F0 1.217 (The Common W)108 429.6 R 1.218(eakness Enumeration \(CWE\) is `)-.8 F 1.218(`a formal list or dictionary of common softw)-.74 F 1.218 (are weak-)-.1 F .212(nesses that can occur in softw)108 441.6 R(are') -.1 E 2.711(sa)-.55 G .211 (rchitecture, design, code or implementation that can lead to e)-2.711 F (xploitable)-.15 E 1.185(security vulnerabilities...)108 453.6 R 1.185 (created to serv)6.185 F 3.685(ea)-.15 G 3.685(sac)-3.685 G 1.186 (ommon language for describing softw)-3.685 F 1.186(are security weak-) -.1 F(nesses')108 465.6 Q 2.5('\()-.74 G(http://cwe.mitre.or)-2.5 E (g/about/f)-.18 E 2.5(aq.html\). F)-.1 F (or more information on CWEs, see http://cwe.mitre.or)-.15 E(g.)-.18 E (Fla)108 482.4 Q .423(w\214nder supports the CWE and is of)-.15 F .422 (\214cially CWE-Compatible.)-.25 F .422 (Hit descriptions typically include a rele-)5.422 F -.25(va)108 494.4 S .762(nt Common W).25 F .763(eakness Enumeration \(CWE\) identi\214er in\ parentheses where there is kno)-.8 F .763(wn to be a rele-)-.25 F -.25 (va)108 506.4 S .068(nt CWE.).25 F -.15(Fo)5.068 G 2.568(re).15 G .068 (xample, man)-2.718 F 2.568(yo)-.15 G 2.567(ft)-2.568 G .067(he b)-2.567 F(uf)-.2 E(fer)-.25 E .067 (-related hits mention CWE-120, the CWE identi\214er for `)-.2 F(`b)-.74 E(uf)-.2 E(fer)-.25 E(cop)108 518.4 Q 2.535(yw)-.1 G .036 (ithout checking size of input')-2.535 F 2.536('\()-.74 G .036(aka `) -2.536 F .036(`Classic Buf)-.74 F .036(fer Ov)-.25 F(er\215o)-.15 E(w') -.25 E 2.536('\). In)-.74 F 2.536(af)2.536 G .536 -.25(ew c)-2.536 H .036(ases more than one CWE).25 F .66(identi\214er may be listed.)108 530.4 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 542.4 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(Man)108 559.2 Q 6.858(yo)-.15 G 6.858(ft)-6.858 G 4.358 (he CWEs reported by \215a)-6.858 F 4.359 (w\214nder are identi\214ed in the CWE/SANS top 25 list 2011)-.15 F (\(http://cwe.mitre.or)108 571.2 Q 3.768(g/top25/\). Man)-.18 F 3.768 (yp)-.15 G 1.267(eople will w)-3.768 F 1.267 (ant to search for CWEs in this list, such as CWE-120)-.1 F .188 (\(classic b)108 583.2 R(uf)-.2 E .188(fer o)-.25 F -.15(ve)-.15 G (r\215o).15 E .188(w\), When \215a)-.25 F .188(w\214nder maps to a CWE \ that is more general than a top 25 item, it lists it)-.15 F 1.1(as more\ -general:more-speci\214c \(e.g., CWE-119:CWE-120\), where more-general \ is the actual mapping.)108 595.2 R(If)6.1 E<8d61>108 607.2 Q .288(w\214\ nder maps to a more speci\214c CWE item that is a speci\214c case of a \ top 25 item, it is listed in the form)-.15 F .621(top-25/more-speci\214\ c \(e.g., CWE-362/CWE-367\), where the real mapping is the more speci\ \214c CWE entry)108 619.2 R(.)-.65 E 1.461(If the same entry maps to mu\ ltiple CWEs, the CWEs are separated by commas \(this often occurs with) 108 631.2 R(CWE-20, Improper Input V)108 643.2 Q 2.5(alidation\). This) -1.11 F(simpli\214es searching for certain CWEs.)2.5 E .771(CWE v)108 660 R .771(ersion 2.7 \(released June 23, 2014\) w)-.15 F .771 (as used for the mapping.)-.1 F .77(The current CWE mappings select)5.77 F .213(the most speci\214c CWE the tool can determine.)108 672 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 684 R 1.016(tion\), b)108 696 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 708 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 s\ peci\214c)-.15 F .966(than the mappings currently implemented.)108 720 R .966(This also means that it is unlik)5.966 F .967 (ely to need much updating for)-.1 F(Fla)72 768 Q 164.71(w\214nder 3) -.15 F(Aug 2014)2.5 E(8)205.39 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 1.689(map currenc)108 84 R 1.689(y; it simply doesn')-.15 F 4.189(th)-.18 G -2.25 -.2(av e)-4.189 H 1.689(enough information to re\214ne to a detailed CWE le)4.389 F -.15 (ve)-.25 G 4.188(lt).15 G 1.688(hat CWE)-4.188 F 1.96(changes w)108 96 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 108 Q .104 (w-cwes", so there is con\214dence that this list is correct.)-.25 F .103(Please report CWE mapping problems as b)5.103 F .103(ugs if)-.2 F (you \214nd an)108 120 Q -.65(y.)-.15 G(Fla)108 136.8 Q .707 (w\214nder may f)-.15 F .707(ail to \214nd a vulnerability)-.1 F 3.207 (,e)-.65 G -.15(ve)-3.457 G 3.207(ni).15 G 3.208<668d>-3.207 G -.15(aw) -3.208 G .708(\214nder co).15 F -.15(ve)-.15 G .708 (rs one of these CWE weaknesses.).15 F(That)5.708 E .815(said, \215a)108 148.8 R .815 (w\214nder does \214nd vulnerabilities listed by the CWEs it co)-.15 F -.15(ve)-.15 G .814(rs, and it will not report lines without).15 F 2.026 (those vulnerabilities in man)108 160.8 R 4.526(yc)-.15 G 4.526 (ases. Thus,)-4.526 F 2.027(as required for an)4.527 F 4.527(yt)-.15 G 2.027(ool intending to be CWE compatible,)-4.527 F<8d61>108 172.8 Q 2.213(w\214nder has a rate of f)-.15 F 2.212(alse positi)-.1 F -.15(ve) -.25 G 4.712(sl).15 G 2.212(ess than 100% and a rate of f)-4.712 F 2.212 (alse ne)-.1 F -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G 4.712(sl).15 G 2.212(ess than 100%.)-4.712 F(Fla)108 184.8 Q .28(w\214nder almost al) -.15 F -.1(wa)-.1 G .28(ys reports whene).1 F -.15(ve)-.25 G 2.78(ri).15 G 2.781<748c>-2.78 G .281 (nds a match to a CWE security element \(a signature/pattern)-2.781 F(a\ s de\214ned in its database\), though certain obscure constructs can ca\ use it to f)108 196.8 Q(ail \(see B)-.1 E(UGS belo)-.1 E(w\).)-.25 E (Fla)108 213.6 Q .207(w\214nder can report on the follo)-.15 F .206 (wing CWEs \(these are the CWEs that \215a)-.25 F .206(w\214nder co)-.15 F -.15(ve)-.15 G .206(rs; `).15 F(`*')-.74 E 2.706('m)-.74 G .206 (arks those)-2.706 F(in the CWE/SANS top 25 list\):)108 225.6 Q<83>108 242.4 Q(CWE-20: Improper Input V)118 242.4 Q(alidation)-1.11 E<83>108 259.2 Q(CWE-22: Improper Limitation of a P)118 259.2 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 276 Q .365(CWE-78: I\ mproper Neutralization of Special Elements used in an OS Command \(`)118 276 R .365(`OS Command Injec-)-.74 F(tion')118 288 Q('\)*)-.74 E<83>108 304.8 Q 1.991(CWE-119: Improper Restriction of Operations within the Bo\ unds of a Memory Buf)118 304.8 R 1.99(fer \(a parent of)-.25 F (CWE-120*, so this is sho)118 316.8 Q(wn as CWE-119:CWE-120\))-.25 E<83> 108 333.6 Q(CWE-120: Buf)118 333.6 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 350.4 Q(CWE-126: Buf) 118 350.4 Q(fer Ov)-.25 E(er)-.15 E(-read)-.2 E<83>108 367.2 Q (CWE-134: Uncontrolled F)118 367.2 Q(ormat String*)-.15 E<83>108 384 Q (CWE-190: Inte)118 384 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 400.8 Q(CWE-250: Ex)118 400.8 Q (ecution with Unnecessary Pri)-.15 E(vile)-.25 E(ges)-.15 E<83>108 417.6 Q(CWE-327: Use of a Brok)118 417.6 Q(en or Risk)-.1 E 2.5(yC)-.15 G (ryptographic Algorithm*)-2.5 E<83>108 434.4 Q .407 (CWE-362: Concurrent Ex)118 434.4 R .407 (ecution using Shared Resource with Improper Synchronization \(`)-.15 F .407(`Race Condi-)-.74 F(tion')118 446.4 Q('\))-.74 E<83>108 463.2 Q (CWE-377: Insecure T)118 463.2 Q(emporary File)-.7 E<83>108 480 Q (CWE-676: Use of Potentially Dangerous Function*)118 480 Q<83>108 496.8 Q(CWE-732: Incorrect Permission Assignment for Critical Resource*)118 496.8 Q<83>108 513.6 Q .596(CWE-785: Use of P)118 513.6 R .596 (ath Manipulation Function without Maximum-sized Buf)-.15 F .596 (fer \(child of CWE-120*, so)-.25 F(this is sho)118 525.6 Q (wn as CWE-120/CWE-785\))-.25 E<83>108 542.4 Q (CWE-807: Reliance on Untrusted Inputs in a Security Decision*)118 542.4 Q<83>108 559.2 Q (CWE-829: Inclusion of Functionality from Untrusted Control Sphere*)118 559.2 Q -1.1(Yo)108 576 S 2.581(uc)1.1 G .081 (an select a speci\214c subset of CWEs to report by using the `)-2.581 F <60adad7265>-.74 E(ge)-.15 E(x')-.15 E 2.581('\()-.74 G .081 (-e\) option.)-2.581 F .082(This option accepts)5.081 F 3.992(ar)108 588 S -.15(eg)-3.992 G 1.492(ular e).15 F 1.492 (xpression, so you can select multiple CWEs, e.g., `)-.15 F<60adad7265> -.74 E(ge)-.15 E 3.991(x")-.15 G(CWE-120|CWE-126"')-3.991 E 3.991('. If) -.74 F(you)3.991 E .023(select multiple CWEs with `)108 600 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 612 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 628.8 R -.15(ve)-.25 G 2.998(do).15 G 2.998(naU)-2.998 G(nix-lik)-2.998 E 2.998(es)-.1 G(ys-)-2.998 E .893 (tem using the `)108 640.8 R<60adad7265>-.74 E(ge)-.15 E(x')-.15 E 3.393 ('a)-.74 G .894(ka `)-3.393 F(`\255e')-.74 E 3.394('o)-.74 G 3.394 (ption. The)-3.394 F .894(\214le must be in re)3.394 F .894(gular e)-.15 F .894(xpression format.)-.15 F -.15(Fo)5.894 G 3.394(re).15 G(xample,) -3.544 E -.74(``)108 652.8 S<8d61>.74 E .956 (w\214nder -e $\(cat \214le1\)')-.15 F 3.456('w)-.74 G .956 (ould report only hits that matched the pattern in `)-3.556 F(`\214le1') -.74 E 3.455('. If)-.74 F .955(\214le1 contained)3.455 F -.74(``)108 664.8 S(CWE-120|CWE-126').74 E 2.5('i)-.74 G 2.5(tw)-2.5 G (ould only report hits matching those CWEs.)-2.6 E 2.58(Al)108 681.6 S .08 (ist of all CWE security elements \(the signatures/patterns that \215a) -2.58 F .081(w\214nder looks for\) can be found by using)-.15 F .449 (the `)108 693.6 R(`\255\255listrules')-.74 E 2.949('o)-.74 G 2.949 (ption. Each)-2.949 F .449(line lists the signature tok)2.949 F .449 (en \(typically a function name\) that may lead to a)-.1 F .916 (hit, the def)108 705.6 R .917(ault risk le)-.1 F -.15(ve)-.25 G .917 (l, and the def).15 F .917(ault w)-.1 F .917 (arning \(which includes the def)-.1 F .917(ault CWE identi\214er\).)-.1 F -.15(Fo)5.917 G 3.417(rm).15 G(ost)-3.417 E .727 (purposes this is also enough if you w)108 717.6 R .727 (ant to see what CWE security elements map to which CWEs, or the)-.1 F (re)108 729.6 Q -.15(ve)-.25 G 3.505(rse. F).15 F 1.005(or e)-.15 F 1.006(xample, to see the most of the signatures \(function names\) that\ map to CWE-327, without)-.15 F(Fla)72 768 Q 164.71(w\214nder 3)-.15 F (Aug 2014)2.5 E(9)205.39 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 .165(seeing the def)108 84 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 96 S 3.087(uc)1.1 G .587(an also see the tok)-3.087 F .588 (ens without a CWE mapping this w)-.1 F .588(ay by running `)-.1 F (`\215a)-.74 E .588(w\214nder -D --listrules | grep)-.15 F .676 (-v CWE-')108 108 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 eleme\ nts, it only lists the def).4 F .676(ault mappings)-.1 F .09 (from CWE security elements to CWE identi\214ers.)108 120 R .091 (It does not include the re\214nements that \215a)5.091 F .091 (w\214nder applies)-.15 F(\(e.g., by e)108 132 Q (xamining function parameters\).)-.15 E 1.135(If you w)108 148.8 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 160.8 Q 1.178 (w\214nder source code \(included in the distrib)-.15 F 1.179 (ution\) is the best place for that information.)-.2 F 1.179 (This detailed)6.179 F 1.459 (information is primarily of interest to those fe)108 172.8 R 3.959(wp) -.25 G 1.459(eople who are trying to re\214ne the CWE mappings of)-3.959 F<8d61>108 184.8 Q 1.02(w\214nder or re\214ne CWE in general.)-.15 F 1.02(The source code documents the mapping between the security ele-) 6.02 F .992(ments to the respecti)108 196.8 R 1.292 -.15(ve C)-.25 H .992(WE identi\214ers, and is a single Python \214le.).15 F .992(The `) 5.992 F(`c_rules')-.74 E 3.492('d)-.74 G .991(ataset de\214nes most) -3.492 F .359(rules, with reference to a function that may mak)108 208.8 R 2.859(ef)-.1 G .359(urther re\214nements.)-2.859 F -1.1(Yo)5.359 G 2.859(uc)1.1 G .359(an search the dataset for func-)-2.859 F .044 (tion names to see what CWE it generates by def)108 220.8 R .043 (ault; if \214rst parameter is not `)-.1 F(`normal')-.74 E 2.543('t)-.74 G .043(hen that is the name)-2.543 F .64 (of a re\214ning Python method that may select dif)108 232.8 R .64 (ferent CWEs \(depending on additional information\).)-.25 F(Con-)5.64 E -.15(ve)108 244.8 S(rsely).15 E 3.192(,y)-.65 G .692 (ou can search for `)-3.192 F(`CWE-number')-.74 E 3.192('a)-.74 G .691 (nd \214nd what security elements \(signatures or patterns\) refer) -3.192 F .594(to that CWE identi\214er)108 256.8 R 5.594(.F)-.55 G .595 (or most people, this is much more than the)-5.744 F 3.095(yn)-.15 G .595(eed; most people just w)-3.095 F .595(ant to scan)-.1 F (their source code to quickly \214nd problems.)108 268.8 Q/F1 10.95 /Times-Bold@0 SF(SECURITY)72 309.6 Q F0 .782 (The whole point of this tool is to help \214nd vulnerabilities so the) 108 321.6 R 3.281(yc)-.15 G .781(an be \214x)-3.281 F 3.281(ed. Ho)-.15 F(we)-.25 E -.15(ve)-.25 G 1.581 -.4(r, d).15 H -2.15 -.25(ev e).4 H .781(lopers and).25 F(re)108 333.6 Q(vie)-.25 E .351(wers must kno)-.25 F 2.851(wh)-.25 G .851 -.25(ow t)-2.851 H 2.851(od).25 G -2.15 -.25 (ev e)-2.851 H .351(lop secure softw).25 F .352 (are to use this tool, because otherwise,)-.1 F/F2 10/Times-Italic@0 SF 2.852(af)2.852 G .352(ool with a tool)-2.852 F(is still a fool)108 345.6 Q F0 5(.M)C 2.5(yb)-5 G(ook at http://www)-2.5 E(.dwheeler)-.65 E (.com/secure-programs may help.)-.55 E .214 (This tool should be, at most, a small part of a lar)108 362.4 R .214 (ger softw)-.18 F .214(are de)-.1 F -.15(ve)-.25 G .214 (lopment process designed to eliminate or).15 F .227 (reduce the impact of vulnerabilities.)108 374.4 R(De)5.227 E -.15(ve) -.25 G .227(lopers and re).15 F(vie)-.25 E .227(wers need kno)-.25 F 2.727(wh)-.25 G .727 -.25(ow t)-2.727 H 2.727(od).25 G -2.15 -.25(ev e) -2.727 H .228(lop secure softw).25 F(are,)-.1 E(and the)108 386.4 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 403.2 Q 1.924 (ferent vulnerability-\214nding tools tend to \214nd dif)-.25 F 1.924 (ferent vulnerabilities.)-.25 F 1.924(Thus, you are best of)6.924 F 4.423(fu)-.25 G(sing)-4.423 E(human re)108 415.2 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 432 S 2.858(us)1.1 G .358 (hould al)-2.858 F -.1(wa)-.1 G .359(ys analyze a).1 F F2(copy)2.859 E F0 .359(of the source program being analyzed, not a directory that can \ be modi-)2.859 F .345(\214ed by a de)108 444 R -.15(ve)-.25 G .344 (loper while \215a).15 F .344(w\214nder is performing the analysis.)-.15 F .344(This is)5.344 F F2(especially)2.844 E F0 .344(true if you don') 2.844 F 2.844(tn)-.18 G(ecess-)-2.844 E .806(ily trust a de)108 456 R -.15(ve)-.25 G .806(loper of the program being analyzed.).15 F .806 (If an attack)5.806 F .806(er has control o)-.1 F -.15(ve)-.15 G 3.306 (rt).15 G .807(he \214les while you')-3.306 F(re)-.5 E .539 (analyzing them, the attack)108 468 R .539(er could mo)-.1 F .838 -.15 (ve \214)-.15 H .538(les around or change their contents to pre).15 F -.15(ve)-.25 G .538(nt the e).15 F .538(xposure of a)-.15 F .077(securi\ ty problem \(or create the impression of a problem where there is none\ \).)108 480 R .078(If you')5.078 F .078(re w)-.5 F .078 (orried about mali-)-.1 F 1.018(cious programmers you should do this an) 108 492 R(yw)-.15 E(ay)-.1 E 3.518(,b)-.65 G 1.017 (ecause after analysis you')-3.518 F 1.017(ll need to v)-.1 F 1.017 (erify that the code)-.15 F -2.15 -.25(ev e)108 504 T .71 (ntually run is the code you analyzed.).25 F .711 (Also, do not use the \255\255allo)5.71 F .711 (wlink option in such cases; attack)-.25 F(ers)-.1 E(could create malic\ ious symbolic links to \214les outside of their source code area \(such\ as /etc/passwd\).)108 516 Q 1.592(Source code management systems \(lik) 108 532.8 R 4.092(eS)-.1 G(ourceF)-4.092 E(or)-.15 E 1.592(ge and Sa) -.18 F -.25(va)-.2 G 1.591(nnah\) de\214nitely f).25 F 1.591 (all into this cate)-.1 F 1.591(gory; if)-.15 F(you')108 544.8 Q .699 (re maintaining one of those systems, \214rst cop)-.5 F 3.199(yo)-.1 G 3.199(re)-3.199 G .7 (xtract the \214les into a separate directory \(that can')-3.349 F(t) -.18 E(be controlled by attack)108 556.8 Q(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 573.6 R 1.276(w\214nder only opens re)-.15 F 1.276(gular \214les, directories, and \(if requested\) symbolic links; \ it will ne)-.15 F -.15(ve)-.25 G(r).15 E 1.607 (open other kinds of \214les, e)108 585.6 R -.15(ve)-.25 G 4.107(ni).15 G 4.107(fas)-4.107 G 1.607(ymbolic link is made to them.)-4.107 F 1.608 (This counters attack)6.607 F 1.608(ers who insert)-.1 F .363 (unusual \214le types into the source code.)108 597.6 R(Ho)5.363 E(we) -.25 E -.15(ve)-.25 G 1.163 -.4(r, t).15 H .363(his only w).4 F .363 (orks if the \214lesystem being analyzed can')-.1 F 2.862(tb)-.18 G(e) -2.862 E .479(modi\214ed by an attack)108 609.6 R .479 (er during the analysis, as recommended abo)-.1 F -.15(ve)-.15 G 5.479 (.T).15 G .48(his protection also doesn')-5.479 F 2.98(tw)-.18 G .48 (ork on)-3.08 F(Cygwin platforms, unfortunately)108 621.6 Q(.)-.65 E .789(Cygwin systems \(Unix emulation on top of W)108 638.4 R(indo)-.4 E .789(ws\) ha)-.25 F 1.089 -.15(ve a)-.2 H 3.289(na).15 G .789 (dditional problem if \215a)-3.289 F .788(w\214nder is used to)-.15 F 1.053(analyze programs that the analyst cannot trust.)108 650.4 R 1.053 (The problem is due to a design \215a)6.053 F 3.554(wi)-.15 G 3.554(nW) -3.554 G(indo)-3.954 E 1.054(ws \(that it)-.25 F .999 (inherits from MS-DOS\).)108 662.4 R .999(On W)5.999 F(indo)-.4 E .998 (ws and MS-DOS, certain \214lenames \(e.g., `)-.25 F(`com1')-.74 E .998 ('\) are automatically)-.74 F .686(treated by the operating system as t\ he names of peripherals, and this is true e)108 674.4 R -.15(ve)-.25 G 3.186(nw).15 G .686(hen a full pathname is)-3.186 F(gi)108 686.4 Q -.15 (ve)-.25 G 2.975(n. Y).15 F .475(es, W)-1 F(indo)-.4 E .475 (ws and MS-DOS really are designed this badly)-.25 F 5.475(.F)-.65 G(la) -5.475 E .474(w\214nder deals with this by checking)-.15 F .867(what a \ \214lesystem object is, and then only opening directories and re)108 698.4 R .867(gular \214les \(and symlinks if enabled\).)-.15 F (Unfortunately)108 710.4 Q 2.52(,t)-.65 G .02(his doesn')-2.52 F 2.52 (tw)-.18 G .02(ork on Cygwin; on at least some v)-2.62 F .019 (ersions of Cygwin on some v)-.15 F .019(ersions of W)-.15 F(in-)-.4 E (do)108 722.4 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(Fla)72 768 Q 164.71(w\214nder 3)-.15 F(Aug 2014)2.5 E(10)200.39 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 1.649(to delete or rename an) 108 84 R 4.149<798c>-.15 G 1.649(lenames that are interpreted as de) -4.149 F 1.648(vice names before performing the analysis.)-.25 F 4.705 (These so-called `)108 96 R(`reserv)-.74 E 4.705(ed names')-.15 F 7.205 ('a)-.74 G 4.705(re CON, PRN, A)-7.205 F 4.706 (UX, CLOCK$, NUL, COM1-COM9, and)-.55 F 1.798 (LPT1-LPT9, optionally follo)108 108 R 1.798(wed by an e)-.25 F 1.798 (xtension \(e.g., `)-.15 F(`com1.txt')-.74 E 1.798('\), in an)-.74 F 4.298(yd)-.15 G(irectory)-4.298 E 4.298(,a)-.65 G 1.798(nd in an)-4.298 F 4.297(yc)-.15 G(ase)-4.297 E(\(W)108 120 Q(indo)-.4 E (ws is case-insensiti)-.25 E -.15(ve)-.25 G(\).).15 E(Do)108 136.8 Q/F1 10/Times-Italic@0 SF(not)2.808 E F0 .308(load or dif)2.808 F 2.808(fh) -.25 G .308(itlists from untrusted sources.)-2.808 F(The)5.308 E 2.808 (ya)-.15 G .308(re implemented using the Python pickle module,)-2.808 F 1.919(and the pickle module is not intended to be secure ag)108 148.8 R 1.918(ainst erroneous or maliciously constructed data.)-.05 F .218(Stor\ ed hitlists are intended for later use by the same user who created the\ hitlist; in that conte)108 160.8 R .219(xt this restric-)-.15 F (tion is not a problem.)108 172.8 Q/F2 10.95/Times-Bold@0 SF -.11(BU)72 201.6 S(GS).11 E F0(Fla)108 213.6 Q .399 (w\214nder is based on simple te)-.15 F .399(xt pattern matching, which\ is part of its fundamental design and not easily)-.15 F 3.282 (changed. This)108 225.6 R .782(design apporach leads to a number of fu\ ndamental limitations, e.g., a higher f)3.282 F .782(alse positi)-.1 F -.15(ve)-.25 G .055(rate, and is the underlying cause of most of the b) 108 237.6 R .055(ugs listed here.)-.2 F .055(On the positi)5.055 F .354 -.15(ve s)-.25 H .054(ide, \215a).15 F .054(w\214nder doesn')-.15 F 2.554(tg)-.18 G(et)-2.554 E .169(confused by man)108 249.6 R 2.669(yc) -.15 G .169 (omplicated preprocessor sequences that other tools sometimes chok) -2.669 F 2.67(eo)-.1 G .17(n; \215a)-2.67 F .17(w\214nder can)-.15 F (often handle code that cannot link, and sometimes cannot e)108 261.6 Q -.15(ve)-.25 G 2.5(nb).15 G(uild.)-2.7 E(Fla)108 278.4 Q .861 (w\214nder is currently limited to C/C++.)-.15 F .86 (In addition, when analyzing C++ it focuses primarily on the C)5.861 F .49(subset of C++.)108 290.4 R -.15(Fo)5.49 G 2.99(re).15 G .49 (xample, \215a)-3.14 F .49(w\214nder does not report on e)-.15 F .49 (xpressions lik)-.15 F 2.99(ec)-.1 G .49(in >> charb)-2.99 F .49 (uf, where charb)-.2 F(uf)-.2 E .276(is a char array)108 302.4 R 5.276 (.T)-.65 G .276(hat is because \215a)-5.276 F .276(w\214nder doesn')-.15 F 2.776(th)-.18 G -2.25 -.2(av e)-2.776 H .275 (type information, and ">>" is safe with man)2.976 F 2.775(yo)-.15 G (ther)-2.775 E .447(types; reporting on all ">>" w)108 314.4 R .447 (ould lead to too man)-.1 F 2.947(yf)-.15 G .447(alse positi)-3.047 F -.15(ve)-.25 G 2.947(s. That).15 F .447(said, it')2.947 F 2.948(sd)-.55 G .448(esigned so that adding)-2.948 F (support for other languages should be easy where its te)108 326.4 Q (xt-based approach can usefully apply)-.15 E(.)-.65 E(Fla)108 343.2 Q .813(w\214nder can be fooled by user)-.15 F .812(-de\214ned functions o\ r method names that happen to be the same as those)-.2 F .185 (de\214ned as `)108 355.2 R(`hits')-.74 E 2.685('i)-.74 G 2.685(ni) -2.685 G .186(ts database, and will often trigger on de\214nitions \(as\ well as uses\) of functions with the)-2.685 F .998(same name.)108 367.2 R .998(This is typically not a problem for C code.)5.998 F .997 (In C code, a function with the same name as a)5.998 F .495 (common library routine name often indicates that the de)108 379.2 R -.15(ve)-.25 G .495(loper is simply re).15 F .496 (writing a common library rou-)-.25 F .072(tine with the same interf)108 391.2 R .071(ace, say for portability')-.1 F 2.571(ss)-.55 G(ak)-2.571 E 2.571(e. C)-.1 F .071(programs tend to a)2.571 F -.2(vo)-.2 G .071 (id reusing the same name for).2 F 2.857(ad)108 403.2 S(if)-2.857 E .357 (ferent purpose \(since in C function names are global by def)-.25 F 2.857(ault\). There)-.1 F .357(are reasonable odds that these)2.857 F (re)108 415.2 Q .406(written routines will be vulnerable to the same ki\ nds of misuse, and thus, reusing these rules is a reason-)-.25 F .186 (able approach.)108 427.2 R(Ho)5.186 E(we)-.25 E -.15(ve)-.25 G .986 -.4 (r, t).15 H .186 (his can be a much more serious problem in C++ code which hea).4 F .187 (vily uses classes)-.2 F 1.355 (and namespaces, since the same method name may ha)108 439.2 R 1.654 -.15(ve m)-.2 H(an).15 E 3.854(yd)-.15 G(if)-3.854 E 1.354 (ferent meanings.)-.25 F 1.354(The \255\255f)6.354 F(alsepositi)-.1 E -.15(ve)-.25 G 1.189(option can help some)108 451.2 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 463.2 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 480 R 2.382(in particular)108 492 R 4.882(,i) -.4 G 4.882(fas)-4.882 G 2.382(tring is opened and then closed multiple\ times using an #ifdef .. #else construct,)-4.882 F<8d61>108 504 Q .073 (w\214nder gets confused.)-.15 F .073 (Such constructs are bad style, and will confuse man)5.073 F 2.573(yo) -.15 G .073(ther tools too.)-2.573 F .073(If you must)5.073 F (analyze such \214les, re)108 516 Q(write those lines.)-.25 E (Thankfully)5 E 2.5(,t)-.65 G(hese are quite rare.)-2.5 E .602 (Some comple)108 532.8 R 3.102(xo)-.15 G 3.102(ru)-3.102 G .602 (nusual constructs can mislead \215a)-3.102 F(w\214nder)-.15 E 5.602(.I) -.55 G 3.102(np)-5.602 G(articular)-3.102 E 3.102(,i)-.4 G 3.102(fap) -3.102 G .602(arameter be)-3.102 F .602(gins with get-)-.15 F(te)108 544.8 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 556.8 R 3.766(eg)-.1 G(ette) -3.766 E 1.266(xt\("hi"\) + function\("bye"\).)-.15 F 1.266 (In practice, this doesn')6.266 F 3.767(ts)-.18 G 1.267(eem to be a) -3.767 F(problem; gette)108 568.8 Q (xt\(\) is usually wrapped around the entire parameter)-.15 E(.)-.55 E 2.201(The routine to detect statically de\214ned character arrays uses \ simple te)108 585.6 R 2.2(xt matching; some complicated)-.15 F -.15(ex) 108 597.6 S(pressions can cause it to trigger or not trigger une).15 E (xpectedly)-.15 E(.)-.65 E(Fla)108 614.4 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 626.4 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 638.4 Q (ould not be detected by this kind of tool.)-.1 E(Fla)108 655.2 Q .355 (w\214nder looks for speci\214c patterns kno)-.15 F .355 (wn to be common mistak)-.25 F .355(es in application code.)-.1 F .355 (Thus, it is lik)5.355 F(ely)-.1 E .674(to be less ef)108 667.2 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 679.2 R .367(te\ chniques may still be useful; feel free to replace the database if your\ situation is signi\214cantly)2.867 F(dif)108 691.2 Q (ferent from normal.)-.25 E(Fla)108 708 Q(w\214nder')-.15 E 3.061(so) -.55 G .561(utput format \(\214lename:linenumber)-3.061 F 3.061(,f)-.4 G (ollo)-3.061 E .561(wed optionally by a :columnnumber\) can be misun-) -.25 F .508(derstood if an)108 720 R 3.008(ys)-.15 G .508 (ource \214les ha)-3.008 F .808 -.15(ve ve)-.2 H .508 (ry weird \214lenames.).15 F .509(Filenames embedding a ne)5.509 F .509 (wline/linefeed character)-.25 F(Fla)72 768 Q 164.71(w\214nder 3)-.15 F (Aug 2014)2.5 E(11)200.39 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 .499 (will cause odd breaks, and \214lenames including colon \(:\) are lik) 108 84 R .499(ely to be misunderstood.)-.1 F .498(This is especially) 5.498 F .11(important if \215a)108 96 R(w\214nder')-.15 E 2.61(so)-.55 G .111(utput is being used by other tools, such as \214lters or te)-2.61 F .111(xt editors.)-.15 F .111(If you')5.111 F .111(re looking)-.5 F .662 (at ne)108 108 R 3.162(wc)-.25 G .662(ode, e)-3.162 F .662 (xamine the \214les for such characters.)-.15 F(It')5.662 E 3.162(si) -.55 G .662(ncredibly unwise to ha)-3.162 F .962 -.15(ve s)-.2 H .661 (uch \214lenames an).15 F(yw)-.15 E(ay;)-.1 E(man)108 120 Q 2.804(yt) -.15 G .304(ools can')-2.804 F 2.804(th)-.18 G .304 (andle such \214lenames at all.)-2.804 F(Ne)5.304 E .304 (wline and linefeed are often used as internal data delime-)-.25 F 3.333 (ters. The)108 132 R .832(colon is often used as special characters in \ \214lesystems: MacOS uses it as a directory separator)3.333 F(,)-.4 E -.4(Wi)108 144 S(ndo).4 E .028(ws/MS-DOS uses it to identify dri)-.25 F .328 -.15(ve l)-.25 H .028(etters, W).15 F(indo)-.4 E .029 (ws/MS-DOS inconsistently uses it to identify spe-)-.25 F 1.169(cial de) 108 156 R 1.169(vices lik)-.25 F 3.669(eC)-.1 G 1.169 (ON:, and applications on man)-3.669 F 3.669(yp)-.15 G 1.168 (latforms use the colon to identify URIs/URLs.)-3.669 F(File-)6.168 E .37(names including spaces and/or tabs don')108 168 R 2.87(tc)-.18 G .37 (ause problems for \215a)-2.87 F(w\214nder)-.15 E 2.87(,t)-.4 G .37 (hough note that other tools might)-2.87 F(ha)108 180 Q .3 -.15(ve p)-.2 H(roblems with them.).15 E(Fla)108 196.8 Q(w\214nder is not internation\ alized, so it currently does not support localization.)-.15 E .133 (In general, \215a)108 213.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.632(yc)-.15 G .132(an be e)-2.632 F(xam-)-.15 E .397(ined further)108 225.6 R 2.897 (,i)-.4 G .397(nstead of silently ignoring them.)-2.897 F .397 (Thus, \215a)5.397 F .397(w\214nder prefers to ha)-.15 F .698 -.15(ve f) -.2 H .398(alse positi).05 F -.15(ve)-.25 G 2.898(s\().15 G .398 (reports that)-2.898 F .741(turn out to not be problems\) rather than f) 108 237.6 R .741(alse ne)-.1 F -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G 3.241(s\().15 G -.1(fa)-3.241 G .74 (ilure to report on a security vulnerability\).).1 F(But)5.74 E (this is a generality; \215a)108 249.6 Q (w\214nder uses simplistic heuristics and simply can')-.15 E 2.5(tg)-.18 G(et e)-2.5 E -.15(ve)-.25 G(rything "right".).15 E .061 (Security vulnerabilities might not be identi\214ed as such by \215a)108 266.4 R(w\214nder)-.15 E 2.561(,a)-.4 G .062(nd con)-2.561 F -.15(ve)-.4 G(rsely).15 E 2.562(,s)-.65 G .062(ome hits aren')-2.562 F 2.562(tr)-.18 G(eally)-2.562 E 1.507(security vulnerabilities.)108 278.4 R 1.506(This\ is true for all static security scanners, and is especially true for t\ ools lik)6.507 F(e)-.1 E<8d61>108 290.4 Q .043 (w\214nder that use a simple le)-.15 F .043(xical analysis and pattern \ analysis to identify potential vulnerabilities.)-.15 F .044(Still, it) 5.044 F 1.112(can serv)108 302.4 R 3.612(ea)-.15 G 3.611(sau)-3.612 G 1.111(seful aid for humans, helping to identify useful places to e) -3.611 F 1.111(xamine further)-.15 F 3.611(,a)-.4 G 1.111(nd that') -3.611 F 3.611(st)-.55 G(he)-3.611 E(point of this simple tool.)108 314.4 Q/F1 10.95/Times-Bold@0 SF(SEE ALSO)72 343.2 Q F0 1.447 (See the \215a)108 355.2 R 1.447(w\214nder website at http://www)-.15 F (.dwheeler)-.65 E(.com/\215a)-.55 E(w\214nder)-.15 E 6.447(.Y)-.55 G 1.448(ou should also see the)-7.547 F/F2 10/Times-Italic@0 SF(Secur) 4.278 E 3.948(eP)-.37 G -.45(ro)-3.948 G(-).45 E(gr)108 367.2 Q (amming for Unix and Linux HO)-.15 E(WT)-.5 E(O)-.18 E F0(at)2.77 E F2 (http://www)2.5 E(.dwheeler)-.74 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 396 S(THOR) .548 E F0(Da)108 408 Q(vid A. Wheeler \(dwheeler@dwheeler)-.2 E(.com\).) -.55 E(Fla)72 768 Q 164.71(w\214nder 3)-.15 F(Aug 2014)2.5 E(12)200.39 E 0 Cg EP %%Trailer end %%EOF flawfinder-1.31/flawfinder.spec0000644003056700244210000000234412365266251017451 0ustar dwheelerDomain UsersName: flawfinder Summary: Examines C/C++ source code for security flaws Version: 1.31 Release: 1%{?dist} License: GPLv2+ Group: Development/Tools URL: http://www.dwheeler.com/flawfinder/ Source: http://www.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 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-1.31/flawfinder.spec.orig0000644003056700244210000000243312362610411020373 0ustar dwheelerDomain UsersName: flawfinder Summary: Examines C/C++ source code for security flaws Version: 1.30 Release: 1 License: GPL Group: Development/Tools URL: http://www.dwheeler.com/flawfinder/ Source: http://www.dwheeler.com/flawfinder/%{name}-%{version}.tar.gz Packager: David A. Wheeler Requires: python BuildArch: noarch BuildRoot: %{_tmppath}/%{name}-%{version}-root %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. Flawfinder is released under the GNU Public License (GPL). %prep %setup -q %build make %install [ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && 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 [ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT" %files %defattr(-,root,root) %doc README ChangeLog COPYING flawfinder.ps %{_bindir}/* %{_mandir}/man1/* %changelog * 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-1.31/flawtest.c0000644003056700244210000000135612206405744016447 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-1.31/INSTALL.txt0000644003056700244210000001012612367316732016322 0ustar dwheelerDomain UsersTo install flawfinder on a Unix-like system (including Cygwin): If you use an RPM-based system (e.g., Red Hat) or deb-based system (e.g., Debian), 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. QUICK START: The quick way to install flawfinder from the tarball is to unpack the tarball and type in something like this on the commmand line: sudo make prefix=/usr install Omit prefix=/usr to install in /usr/local instead. Omit "sudo" if you are already root. You don't even have to install it; running it as "./flawfinder ..." will work just fine if you have Python 2 installed (though it's probably more convenient to install it). 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 "cd" into the directory created. 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. * Windows systems should be able to run this on the command line (cmd.exe) directly, but I haven't tried that. * 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-1.31/junk.c0000644003056700244210000000023112360361334015551 0ustar dwheelerDomain Users #include main() { char abuf[1000]; FILE *FR = stdin; fscanf(FR, "%2000s", abuf); printf("Result = %s\n", abuf); strcpy(new,old); } flawfinder-1.31/makefile0000644003056700244210000001462412367514515016161 0ustar dwheelerDomain Users# Flawfinder. Released under the General Public License (GPL). # (C) 2001-2014 David A. Wheeler. # To change version number, edit this here, the beginning of the # "flawfinder" script, flawfinder.spec, setup.py, and index.html. # Then "make test-is-correct" to get the updated version number. # To distribute, "make distribute && su && make rpm". # Then use make my_install to install to website image. # Eventually switch to using DistUtils to autogenerate. NAME=flawfinder VERSION=1.31 RPM_VERSION=1 VERSIONEDNAME=$(NAME)-$(VERSION) ARCH=noarch SAMPLE_DIR=/usr/src/linux-2.2.16 # Flawfinder has traditionally used INSTALL_DIR, INSTALL_DIR_BIN, and # INSTALL_DIR_MAN. Here we add support for GNU variables like prefix, etc.; # users who override the older flawfinder-specific variable names will # not notice any changes. We define exec_prefix oddly so we can # quietly merge these 2 systems: prefix=/usr/local INSTALL_DIR=$(prefix) exec_prefix=$(INSTALL_DIR) bindir=$(exec_prefix)/bin INSTALL_DIR_BIN=$(bindir) datarootdir=$(INSTALL_DIR)/share mandir=$(datarootdir)/man man1dir=$(mandir)/man1 INSTALL_DIR_MAN=$(man1dir) FLEX=flex # For Cygwin on Windows, set PYTHONEXT=.py # (EXE=.exe would be needed on some systems, but not for flawfinder) EXE= PYTHONEXT= # EXE=.exe # PYTHONEXT=.py # The rpm build command. "rpmbuild" for rpm version 4.1+ # (e.g., in Red Hat Linux 8), "rpm" for older versions. RPMBUILD=rpmbuild DESTDIR= 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$(PYTHONEXT) $(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 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 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: flawfinder test.c test2.c # Omit time report so that results are always the same textually. ./flawfinder --omittime test.c test2.c > test-results.txt echo >> test-results.txt echo "Testing for no ending newline:" >> test-results.txt ./flawfinder --omittime no-ending-newline.c | \ grep 'Lines analyzed' >> test-results.txt ./flawfinder --omittime --html --context test.c test2.c > test-results.html @echo "Differences from expected results:" @diff -u correct-results.txt test-results.txt @diff -u correct-results.html test-results.html check: test # Run "make test-is-correct" if the results are as expected. test-is-correct: test-results.txt mv test-results.txt correct-results.txt mv test-results.html correct-results.html 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 *.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 .PHONY: install clean test check profile test-is-correct rpm uninstall distribute my-install show-cwes # 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-1.31/MANIFEST.in0000644003056700244210000000036412206405744016206 0ustar dwheelerDomain Usersinclude COPYING include README 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-1.31/no-ending-newline.c0000644003056700244210000000067012360206524020125 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-1.31/README0000644003056700244210000000502312367501426015327 0ustar dwheelerDomain UsersThis is "flawfinder" by David A. Wheeler, . 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: http://www.dwheeler.com/flawfinder Flawfinder is designed for use on Unix/Linux/POSIX systems (including Cygwin, Linux-based systems, MacOS, and *BSDs) as a command line tool. It requires Python 2 (version 2.5 or later). You can typically install flawfinder from its source code by doing this: tar xvzf FILENAME.tar.gz # Uncompress distribution file cd flawfinder-* # cd into it. sudo make prefix=/usr install # Install in /usr This installs the program as "/usr/bin/flawfinder" as well as the man page. You can omit the "prefix=/usr"; it will then install under "/usr/local". The file INSTALL.txt has more detailed installation instructions; flawfinder supports the usual conventions (prefix, DESTDIR, etc.). You don't HAVE to install it to run it, but it's easiest that way. 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/ 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. More technically, flawfinder uses lexical scanning to find tokens (such as function names) that suggest likely vulnerabilities, estimates their level of risk (e.g., by the text of function calls), and reports the results. Flawfinder does not use or have access to information about control flow, data flow, or data types. Thus, flawfinder will necessarily produce many false positives for vulnerabilities and fail to report many vulnerabilities. On the other hand, flawfinder can find vulnerabilities in programs that cannot be built or cannot be linked. Flawfinder also doesn't get as confused by macro definitions and other oddities that more sophisticated tools have trouble with. Flawfinder is released under the GNU GPL license version 2 or later (GPLv2+). See the COPYING file for license information. flawfinder-1.31/setup.cfg0000644003056700244210000000021212206405744016261 0ustar dwheelerDomain Users[bdist_rpm] release = 1 doc_files = ChangeLog README COPYING flawfinder.ps flawfinder.pdf flawfinder-1.31/setup.py0000644003056700244210000000345312365266266016176 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. # Template for creating your own setup.py. See the USAGE file in # the Distutils source distribution for descriptions of all the # options shown below. Brief instructions on what to do: # - set the other metadata: version, description, author, author_email # and url. All of these except 'description' are required, although # you may supply 'maintainer' and 'maintainer_email' in place of (or in # addition to) 'author' and 'author_email' as appropriate. # - fill in or delete the 'packages', 'package_dir', 'py_modules', # and 'ext_modules' options as appropriate -- see USAGE for details # - delete this comment and change '__revision__' to whatever is # appropriate for your revision control system of choice (just make # sure it stores the revision number for your distribution's setup.py # script, *not* the examples/template_setup.py file from Distutils!) """Setup script for the flawfinder tool.""" from distutils.core import setup import commands setup (# Distribution meta-data name = "flawfinder", version = "1.31", description = "a program that examines source code looking for security weaknesses", author = "David A. Wheeler", author_email = "dwheeler@dwheeler.com", license = 'GPL', 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://www.dwheeler.com/flawfinder/", scripts = [ 'flawfinder' ], data_files = [ ('share/man/man1', [ 'flawfinder.1.gz' ]) ], py_modules = [ ], ) flawfinder-1.31/sloctest.c0000644003056700244210000000016512206405744016453 0ustar dwheelerDomain Users/* This is a test. Should produce 6 SLOC. */ #include #define HI 10 main() { a = 1; /* hi */ "hi" } flawfinder-1.31/test-results.html0000644003056700244210000003314212367534640020022 0ustar dwheelerDomain Users Flawfinder Results

        Flawfinder Results

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

        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:56: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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.
            strncat(d,s,sizeof(d)); /* Misuse - this should be flagged as riskier. */
          
        • test.c:57: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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:60: [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:62: [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:73: [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:73: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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 (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:52: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination (CWE-120).
            lstrcat(d,s);
          
        • test.c:75: [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:75: [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:91: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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);
          
        • test.c:51: [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:97: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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:53: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120).
            strncpy(d,s);
          
        • test.c:54: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120).
            _tcsncpy(d,s);
          
        • test.c:55: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings.
            strncat(d,s,10);
          
        • test.c:58: [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:64: [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:66: [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 = 36
        Lines analyzed = 118
        Physical Source Lines of Code (SLOC) = 80
        Hits@level = [0] 0 [1] 9 [2] 7 [3] 3 [4] 10 [5] 7
        Hits@level+ = [0+] 36 [1+] 36 [2+] 27 [3+] 20 [4+] 17 [5+] 7
        Hits/KSLOC@level+ = [0+] 450 [1+] 450 [2+] 337.5 [3+] 250 [4+] 212.5 [5+] 87.5
        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 for Linux and Unix HOWTO' (http://www.dwheeler.com/secure-programs) for more information. flawfinder-1.31/test-results.txt0000644003056700244210000001755312367534640017705 0ustar dwheelerDomain UsersFlawfinder version 1.31, (C) 2001-2014 David A. Wheeler. Number of rules (primarily dangerous function names) in C/C++ ruleset: 169 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:56: [5] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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:57: [5] (buffer) _tcsncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (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:60: [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:62: [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:73: [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:73: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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 (CWE-120). Consider using a function version that stops copying at the end of the buffer. test.c:52: [4] (buffer) lstrcat: Does not check for buffer overflows when concatenating to destination (CWE-120). test.c:75: [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:75: [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:91: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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:51: [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:97: [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 (CWE-120). Consider using strcpy_s, strncpy, or strlcpy (warning, strncpy is 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:53: [1] (buffer) strncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120). test.c:54: [1] (buffer) _tcsncpy: Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers (CWE-120). test.c:55: [1] (buffer) strncat: Easily used incorrectly (e.g., incorrectly computing the correct maximum size to add) (CWE-120). Consider strcat_s, strlcat, or automatically resizing strings. test.c:58: [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:64: [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:66: [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 = 36 Lines analyzed = 118 Physical Source Lines of Code (SLOC) = 80 Hits@level = [0] 0 [1] 9 [2] 7 [3] 3 [4] 10 [5] 7 Hits@level+ = [0+] 36 [1+] 36 [2+] 27 [3+] 20 [4+] 17 [5+] 7 Hits/KSLOC@level+ = [0+] 450 [1+] 450 [2+] 337.5 [3+] 250 [4+] 212.5 [5+] 87.5 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 for Linux and Unix HOWTO' (http://www.dwheeler.com/secure-programs) for more information. Testing for no ending newline: Lines analyzed = 32 flawfinder-1.31/test.c0000644003056700244210000000646412206405744015602 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); 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-1.31/test2.c0000644003056700244210000000005412206405744015651 0ustar dwheelerDomain Users/* Here's a file with no contents to try */