Silencing the warnings in many packages doesn't have to be left to maintainers, and often isn't very complicated. I've had to learn to figure this out for myself, and I'm writting this to hopefully help others learn this faster, smoother, and with less aggravation (I'll add something like this to the warnings.html page in the hlfs book later). I'll use diffutils-2.8.7 as an example:
$ cd diffutils-2.8.7/ $ find . -name "Makefile.in" ./m4/Makefile.in ./ms/Makefile.in ./doc/Makefile.in ./lib/Makefile.in ./man/Makefile.in ./src/Makefile.in ./Makefile.in # Okay, of all these Makefile's only the ones in lib/ and src/ will build # code. Now we can add some warning flags: sed -e 's/^CFLAGS =/& -Wall -Wformat -Wformat-security -Werror/' \ -i {lib,src}/Makefile.in # Don't add the warning flags to the shell environment CFLAGS # because a lot of the time the configure script will fail to detect system # features because tests fail from -Werror. # '-Wall -Wformat -Wformat-security' will detect the majority of serious # programming errors, and some not so serious. Adding more warnings # than this is a bit passed my current skill level... additional warnings # turn up vage issues that get more complicated to fix. The -Werror # will make the build stop right away, so the line of code can be found # usually without scrolling up. # Next run ./configure and make ./configure && make # The first warning/error is from fortify_source. These are reported # because there's no code checking the return values of these lines, # and that can mean bugs/failures in this code will go unreported: c-stack.c: In function 'die': c-stack.c:124: warning: ignoring return value of 'write', declared with attribute warn_unused_result c-stack.c:125: warning: ignoring return value of 'write', declared with attribute warn_unused_result c-stack.c:126: warning: ignoring return value of 'write', declared with attribute warn_unused_result c-stack.c:127: warning: ignoring return value of 'write', declared with attribute warn_unused_result make[3]: *** [c-stack.o] Error 1 make[3]: Leaving directory `/usr/src/diffutils-2.8.7/lib' # Okay. So open lib/c-stack.c and go to line 124 (type 'vi lib/c-stack.c', # type '123', and enter, and you'll be on line 124). Lines 124, 125, 126, # and 127 are: write (STDERR_FILENO, program_name, strlen (program_name)); write (STDERR_FILENO, ": ", 2); write (STDERR_FILENO, message, strlen (message)); write (STDERR_FILENO, "\n", 1); # This is easy, wrap them in assert(). Put "assert(" at the beginning of the # line and a closing ")" at the end but before the ";". So it will look like # this: assert(write (STDERR_FILENO, program_name, strlen (program_name))); assert(write (STDERR_FILENO, ": ", 2)); assert(write (STDERR_FILENO, message, strlen (message))); assert(write (STDERR_FILENO, "\n", 1)); # Now go near the top of the file and find the last "#include". We need to # include <assert.h> for assert(). Underneath '#include "exitfail.h"' add # this: #include <assert.h> # The assert() macro will cause the program to abort if the write() function # returns an error. This is usually overkill, because the write() function is # almost always checked later when it gets used, but using the assert() # macro will fix the compiler warning and add some extra paranoid # security. # And enter 'make' again. The next warning/error is caused because a # variable has not been initialized with a value, and again this can lead # to unexpected results from the program, so its best to define a value # for it: cmp.c: In function 'main': cmp.c:383: warning: 'offset_width' may be used uninitialized in this function make[2]: *** [cmp.o] Error 1 make[2]: Leaving directory `/usr/src/diffutils-2.8.7/src' # Go to line 383 in src/cmp.c: int offset_width; # And initialize this with a value of 0: int offset_width = 0; # Enter 'make' again and the next warning/error is: analyze.c: In function 'compareseq': analyze.c:351: warning: 'part.xmid' may be used uninitialized in this function analyze.c:351: warning: 'part.ymid' may be used uninitialized in this function make[2]: *** [analyze.o] Error 1 make[2]: Leaving directory `/usr/src/diffutils-2.8.7/src' # This is just like the previous warning except this is a structure (struct), # and the previous was an integer (int). Line 351 of src/analyze.c is: struct partition part; # Structures have multiple values, initialize them like this: struct partition part = {0,0}; # Run make again. The next warning is caused because of a missing header. # "implicit declaration" means it wasn't previously declared (from a header). # You can run grep in /usr/include (and its sub directories) to find out which # header is needed: diff.c: In function 'set_mtime_to_now': diff.c:1007: warning: implicit declaration of function 'gettimeofday' make[2]: *** [diff.o] Error 1 make[2]: Leaving directory `/usr/src/diffutils-2.8.7/src' # 'gettimeofday' is defined in <sys/time.h>. So include it near the top of # src/diff.c, under '#include <xalloc.h>': #include <sys/time.h> # There are a few reasons for this warning. Including the header will add a # prototype for 'gettimeofday'. The prototype is compared to how our # code is planning to communicate with the library. If the argument types # in the code don't match the prototype there will be another, different, # warning complaining about it. This helps make sure our code isn't missing # arguments, and it using the library function as it was intended. # And enter 'make' again. The next warning is: ifdef.c: In function 'do_printf_spec': ifdef.c:332: warning: 'value' may be used uninitialized in this function make[2]: *** [ifdef.o] Error 1 make[2]: Leaving directory `/usr/src/diffutils-2.8.7/src' # Line 332 of src/ifdef.c is: char value; # This can be treated just like the integer we initialized with 0 # previously: char value = 0; # And run make again. The next warning is: io.c: In function 'sip': io.c:131: warning: statement with no effect make[2]: *** [io.o] Error 1 make[2]: Leaving directory `/usr/src/diffutils-2.8.7/src' # "statement with no effect" means the line is useless. So # remove it or comment it out with /* */: /* set_binary_mode (current->desc, false); */ # And run make again. And the next warning is: diff3.c: In function 'output_diff3': diff3.c:1409: warning: format not a string literal and no format arguments make[2]: *** [diff3.o] Error 1 # I haven't fixed this warning before, this is a new gcc4 warning I think. # But I was lucky enough to find: # http://sources.redhat.com/ml/bug-gnu-utils/2006-03/msg00036.html # with a small patch for this warning: - fprintf (outputfile, line_prefix); + fputs (line_prefix, outputfile); # And that's it, as far as compiler warnings go. But I'm not done yet, # I still want to use strlcpy/strlcat if possible. So 'make clean' and # search for strcat/strcpy: $ make clean $ find . -type f |xargs grep -n strcat ./lib/fnmatch.c:207:# define STRCAT(D, S) strcat (D, S) ./lib/fnmatch_loop.c:1130: /* I cannot believe it but `strcat' is actually acceptable # STRCAT is a macro for strcat. If you read the comments on line # 1130, the programmer seems fairly confident that that its # implemented safely. So I'll leave this one alone (for now) and move # on to strcpy: $ find . -type f |xargs grep -n strcpy ./lib/time_r.c:34: return strcpy (dest, src); ./lib/hard-locale.c:53: strcpy (locale, p); ./src/diff3.c:1205: strcpy (p, " -a"); ./src/diff3.c:1210: strcpy (p, " --strip-trailing-cr"); ./src/diff3.c:1213: strcpy (p, args); # These are easy to substitute with strlcpy. First the one in lib/time_r.c: return strlcpy (dest, src, sizeof(dest)); # strlcpy needs a third argument to set the max size, which is also the # size of the first argument. Again with lib/hard-locale.c: strlcpy (locale, p, sizeof(locale)); # And src/diff3.c: strlcpy (p, " -a", sizeof(p)); ... strlcpy (p, " --strip-trailing-cr", sizeof(p)); ... strlcpy (p, args, sizeof(p)); # The strcpy functions do not accept a maximum size argument, which is the # reason they're unsafe. strlcpy was designed specifically not to overflow, # so the programmer (and the program) and be more careless without causing # a vulnerability. # All done (for now). Now diffutils surely isn't bug proofed, but its a lot # better off now then it was when we started. # There is one remaining issue, with tmpnam (fixed by the hardened_tmp patch), # but diffutils isn't a typical example of this issue so I don't want to get # into it here. I'm sure I have some holes in my explanations on this page, so feel free to comment or ask questions about these or other compiler warnings. If we can find a way to explain this all clearly it should make a good addition to the book. robert
pgp5lHv0aHnV9.pgp
Description: PGP signature
-- http://linuxfromscratch.org/mailman/listinfo/hlfs-dev FAQ: http://www.linuxfromscratch.org/faq/ Unsubscribe: See the above information page