Gimpel Software
  Order        Patches        Discussion Forum        Blog 
Contact      Site Map       
   Home
   Bug of the Month
   Products
   Order
   Support
   Company
   Links
   Interactive Demo
Google Search box  
Search gimpel.com:

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 © 2013, Gimpel Software, All rights reserved.