Function Mimicry (-function)
Special Functions
PC-lint/FlexeLint is aware of the properties of some standard functions
which we refer to as special functions. Some properties of these functions
can be transferred to user-defined functions by means of the option
-function. A complete list of such functions is shown in Function
Listing
For example, function fopen() is recognized as a special
function. Its two arguments are checked for the possibility of being the
NULL pointer and its return value is considered possibly NULL. Thus, the
code:
if( name ) printf ( "ok\n" );
f = fopen( name, "r" ); // Warning! name may be NULL
fclose ( f ); // Warning! f may be NULL
will be greeted with the diagnostics indicated. Note that fclose
is also a special function and PC-lint/FlexeLint will complain about
a possibly NULL argument because fopen returned a value that could
be NULL. You may transfer all three properties of fopen to a function
of your own, say myopen, by using the option
-function( fopen, myopen )
Then, PC-lint/FlexeLint would also check myopen's first
and second arguments for NULL and assume that the returned pointer could
possibly be NULL. In general, the syntax of -function is described
as follows:
-function( Function0, Function1 [, Function2] ... )
specifies that Function1, Function2, etc. are like
Function0 in that they exhibit special properties normally associated
with Function0.
The arguments to -function may be subscripted. For example,
if myopen were to check its 2nd and 3rd arguments for NULL rather
than its 1st and 2nd we could do the following:
-function( fopen(1), myopen(2) )
-function( fopen(2), myopen(3) )
This would transfer the properties of NULL checking to the 2nd and
3rd arguments of myopen. This could be simplified to
-function( fopen(1), myopen(2), myopen(3) )
since the property of fopen(1) is identical to that of
fopen(2).
To transfer the return property you may use the r index
as in
-function( fopen(r), myopen(r) )
Some functions have a property that is not decomposable to a single
argument or return value but is rather a combined property of the entire
function. For example
char * fread( char *, size_t, size_t, FILE * );
has, in addition to the check-for-NULL properties on its first and
fourth arguments, an additional check to see if the size of argument 2
multiplied by argument 3 exceeds the buffer size given as the first argument.
Thus
char buf[100];
fread( buf, 100, 2, f ); // Warning
To transfer this function-wide property to some other function
we need to use the 0 (zero) index. Thus
-function( fread(0), myread(0) )
will transfer just the overflow checking (as described above) and
not the NULL pointer checking, that would be available with arguments 1
and 4.
As a convenience, the subscript need not be repeated if it is the
same as the first argument. Thus
-function( fread(0), myread )
is equivalent to the earlier option.
You may remove any or all of these semantics from a special function
by not using a second argument to the -function option. Thus
-function( fread )
will remove all of the semantics of the fread function and
-function( fread(0) )
removes only the special semantics involving arguments 1, 2, and
3 described above.
You may transfer semantics to member functions as well as non-member
functions. Thus
-function( exit, X::quit )
transfers the properties of exit() to X::quit().
The semantics in this case is simply that the function is not expected
to return. Please note that this option must be given prior to the definition
of class X. (Actually, it need only be given prior to the closing
brace that defines class X.) This is usually not a problem as
such options are normally provided in a separate .lnt file preceding
all modules; but such options may also be given in a 'lint' comment at
the class definition.
As another example involving member functions consider the following:
//lint -function( strlen(1), X::X(1), X::g )
// both X::X() and X::g() should have their first
// argument checked for NULL.
//lint +fpn pointer parameters may be NULL
class X
{
public:
char *buf;
X( char * );
void g( char * );
};
void f( char *p ) // p may be NULL because of +fpn
{
X x(p); // Warning 668
x.g( p ); // Warning 668
}
In this example, the semantics associated with the first argument
of strlen are transferred to the first argument of X::X and
to the first argument of X::g. As the example illustrates, when
we speak of the nth argument passed to a member function we are
ignoring in our count the implicit argument that is a pointer to the class
(this is always checked for NULL).
No distinction is made among overloaded functions. Thus, if X::X(
int * ) is checked for NULL then so is X::X( char * ). If
there is an X::X( int ) then its argument is not checked because
its argument is not a pointer. If there is an X::X( int *, char * )
then the first argument is checked, but not the second.
Function listing
Function f(0) f(r) f(1) f(2) f(3) f(4) f(5)
__assert - - S20 - - - -
abort S3 - - - - - -
asctime - - S1 - - - -
atof - - S1 - - - -
atoi - - S1 - - - -
atol - - S1 - - - -
bsearch - S2 S1 S1 - - S1
calloc S4 S2 - - - - -
clearerr - - S1 - - - -
ctime - - S1 - - - -
exit S3 - - - - - -
fclose - - S7 - - - -
feof - - S1 - - - -
ferror - - S1 - - - -
fflush - - S1 - - - -
fgetc - - S1 - - - -
fgetpos - - S1 S1 - - -
fgets S5 S2 S1 - S1 - -
fopen - S2 S1 S1 - - -
fprintf - - S1 S1 - - -
fputc - - - S1 - - -
fputs - - S1 S1 - - -
fread S6 - S1 - - S1 -
free - - S7 - - - -
freopen - S2 S1 S1 S1 - -
frexp - - - S1 - - -
fscanf - - S1 S1 - - -
fseek - - S1 - - - -
fsetpos - - S1 S1 - - -
ftell - - S1 - - - -
fwrite S8 - S1 - - S1 -
getc - - S1 - - - -
getenv - - S1 - - - -
gets S18 S2 S1 - - - -
gmtime - S2 S1 - - - -
localtime - - S1 - - - -
longjmp S3 - S1 - - - -
malloc S9 S2 - - - - -
mbstowcs - - S1 S1 - - -
mbtowc - - S1 - - - -
memchr S10 S2 S1 - - - -
memcmp S11 - S1 S2 - - -
memcpy S12 - S1 S2 - - -
memmove S12 - S1 S2 - - -
memset S13 - S1 - - - -
mktime - - S1 - - - -
modf - - - S1 - - -
operator new S9 S2 - - - - -
operator new[] S9 S2 - - - - -
operator delete - S7 - - - - -
operator delete[] - S7 - - - - -
perror - - S1 - - - -
printf - - S1 - - - -
putc - - - S1 - - -
puts - - S1 - - - -
qsort - - S1 - - S1 -
remove - - S1 - - - -
rename - - S1 S1 - - -
rewind - - S1 - - - -
scanf - - S1 - - - -
setbuf - - S1 - - - -
setjmp S14 - - - - - -
setvbuf - - S1 - - - -
sprintf - - S1 S1 - - -
sscanf - - S1 S1 - - -
strcat S15 - S1 S1 - - -
strchr - S2 S1 - - - -
strcmp - - S1 S1 - - -
strcoll - - S1 S1 - - -
strcpy S15 - S1 S1 - - -
strcspn - - S1 S1 - - -
strftime - - S1 - S1 S1 -
strlen S16 - S1 - - - -
strncat S17 - S1 S1 - - -
strncmp - - S1 S1 - - -
strncpy S17 - S1 S1 - - -
strpbrk - S2 S1 S1 - - -
strrchr - S2 S1 - - - -
strspn - - S1 S1 - - -
strstr - S2 S1 S1 - - -
strtod - - S1 - - - -
strtok - S2 - S1 - - -
strtol - - S1 - - - -
strtoul - - S1 - - - -
strxfrm - - S1 S1 - - -
time - - S1 - - - -
tmpfile - S2 - - - - -
tmpnam - - S1 - - - -
ungetc - - - S1 - - -
vfprintf - - S1 S1 S1 - -
vprintf - - S1 S1 - - -
vsprintf - - S1 S1 S1 - -
wcstombs - - S1 S1 - - -
wctomb - - S1 - - - -
Semantics
S1 Checks the argument and if it is a pointer and can potentially
be NULL issues a warning. The warning number depends on the
likelihood that the pointer is NULL: 418 == certainty, 668 ==
possible, 802 == conceivable.
S2 Indicates that there is a possibility that the return pointer
is NULL.
S3 (abort and exit) the function does not return.
S4 (calloc) the length of the returned buffer is the product
of arguments 1 and 2.
S5 (fgets) complains if the second argument (as a signed or
unsigned integer) exceeds the data area represented by the
first argument.
S6 (fread) complains if the product of the 2nd and 3rd arguments
exceeds the buffer length implied by the first argument.
S7 (free) the argument is a pointer which is subsequently
regarded as uninitialized. See also S19.
S8 (fwrite) complains if the product of the 2nd and 3rd arguments
exceeds the buffer length implied by the first argument.
S9 (malloc, operator new, operator new[]) the length of
the returned buffer is the value of the first argument.
S10 (memchr) if the third argument is greater than the size of
the buffer indicated by the first argument, a diagnostic
(access beyond) is issued.
S11 (memcmp) if the third argument is greater than the size of
data area represented by either the first argument or the
second argument, a diagnostic is issued.
S12 (memcpy) a complaint is issued if the third argument is
greater than the size of the data area represented by either
the first argument (overrun) or second argument (access beyond).
S13 (memset) if the third argument is greater than the size of
the buffer indicated by the first argument, a diagnostic
(data overrun) is issued.
S14 (setjmp) an informational message (748) is issued about
the existence of register variables in any function calling
the function. Also, registers are considered possibly
uninitialized at that point.
S15 (strcat and strcpy) a diagnostic is issued if the size of the
buffer area indicated by the second argument is larger than
the size of the buffer area indicated by the first argument.
S16 (strlen) the value returned by the function is assumed to be the
size of the buffer (minus 1) represented by the first argument.
S17 (strncpy and strncat) issues a complaint (data overrun) if the
value of the third (integral) argument is greater than the
size of the buffer represented by the first argument.
S18 (gets) issues a warning (421) at the very use of the function.
S19 (fclose) the argument is a pointer which should be non
NULL and is subsequently regarded as uninitialized. This
combines properties S1 and S7.
S20 (__assert) the argument can be assumed to be true (i.e.
non zero). See The assert() Remedy
|
|
|
Home | Contact
| Order
PC-lint and FlexeLint are trademarks of Gimpel Software
Copyright © 2011, Gimpel Software, All rights reserved.
|
|