On Fri, 3 Sep 2004 21:55:54 UTC,
ps****@icon.co.za (Paul Sheer) wrote:
I need to automatically search and replace all fixed size
buffer strcpy's with strncpy's (or better yet, strlcpy's)
as a security and stability audit. The code base is large
and it is not feasable to manually perform these changes.
I would like perhaps a C++ parser that can automatically
detect use of a strcpy to a buffer of fixed size. For instance,
struct x {
char member[128];
}
...
struct x X;
...
strcpy (X.member, p); /* <-- should generate a warning here */
but
struct x {
char *member;
}
...
struct x X;
...
strcpy (X.member, p); /* <-- should NOT generate a warning */
(The second case is too complex to fix at this point.)
Is there any way of doing this? Our code is C++ (not C) and I
have, for example, looked at
http://codeworker.free.fr/ScriptsRepository.html
but this does not seem to provide an easy solution.
I am anticipating writing a script that can search and replace
"strcpy (x.member, p);" with "strlcpy (x.member, p, sizeof(x.member));"
provided the script can be guaranteed that the replacement is valid
(and I suppose only a full C++ parser would know if it is valid).
Can GCC be modified to give such a warning?
thanks
-paul
Paul,
I've worked for several companies that have generated their own
macros to watch the string and memory routines and inform at
compiler time if there was going to be a problem. There are
many times though when the code won't give you clues and even at
runtime you can't catch everything. However, it is generally
useful to use such macros occasionally, or as a rule, to test that
your code adheres to some reasonable practice. I've also seen
similar macros used to track memory leaks and similar offenses
that can sometime be checked this way. There are some public
domain versions of these as well. I don't have any to offer,
but I'll describe the general idea for you.
Say that you want to insure that strcpy tries to protect itself
against copying a large space into a smaller space. NULLs could
be detected at compile time. Certain run time conditinos could
also be checked for... such as NULL values.
The general method is to declare macros of the same name as
the function to check. The macro does compile time checking
and generates a call to an equivalent function that you may
fee is more suitable to your needs. A compile time switch is
sometimes used to differentiate when the real or enhanced code
is called. The macros must be defined before they are used
and the original functions reliably removed from view. #ifdefs
and such are generally used.
Consider the strcpy function. It is defined as
char *strcpy (char *destination, const char * const source);
or equivalent. The replacement function could be something
like the following.
char *StrCpy (char *destination, const char * const source);
In this case StrCpy might handle improper parameters a bit
better or provide some form of useful side effect such as
writing to a log file. For memory leak tracers, this is where
you keep a table of allocated memory and watch it get freed.
Upon a final, special call, your code would list memory not
freed and perhaps the module, line, and function that allocated
it.
The macro for strcpy would include comparing the pointers
to the size of a pointer on your system and if they aren't
that length, then they point to a measurable space defined
by sizeof(). You can then write an error/warning at compile
time that the sizeof a source is larger than the sizeof a
destination. There are likely many instances in your code
where it isn't possible to tell though.
As a general rule you should compile with the maximum warning
level and treat all warnings as errors. If the code is correct,
fix it so as not to issue the warning. Otherwise fix the code.
For groups that don't already do this, slowly increase the error
level and correct errors as you go. For very dirty code this may
take a long time. However, if you've seen one mistake, like
using an assignment in a condition, chances are it was also done
elsewhere. Look for all of that specific warning and fix the
code or remove the warning.
David