As you use CCured you might encounter various kinds of problems. Most of these are due to a combination of aggressive coding practices and CCured being less smart than the programmer. (Note: this section is continuously being expanded; if you do not see the answer to your question, or if the answer is not helpful, let us know).
combine20_2.c:11: Warning: uniqueVarNames: Changing the name of local tmp___0 in main to tmp___1
This is nothing to worry about. It means that the merged has discovered a naming error in the merged file and has fixed it.
/usr/include/sys/socket.h:189: Error: Incompatible declaration for accept (4). Previous was at rblsmtpd.c:103 (0) (different type constructors: void vs. int )
This means that the merger has detected two incompatible declarations or definitions of the same external global. You must fix that either by changing all definitions and declarations to have the same type. In fact, in the sources for gcc we found a few bugs like this where one function was defined with one type and was declared and used with another type in some other file.
In some cases however, there is nothing wrong with the program but it just happens to redefine a function already defined in the library (as in the example from which we got the error message). The program redefines accepts in one file and uses the library's accept in another file. When you put the things together it does not make sense anymore. You should change the name of your global in that case.
/home/weimer/cil/include/netdb_wrappers.h:110: Warning: The name gethostent_wrapper is used for two distinct globals
TODO.
chkshsgr.c:8: Warning: Calling function getgroups without proper prototype: will be WILD. getgroups has type void * __attribute__((___ptrnode__(12))) /* /* missing proto */ */()
You should always have prototypes for the functions that you use. In fact, CCured will be happy if you include the prototype in at least one of your modules!
chkshsgr.c:8: Warning: Calling function _exit with 1 arguments when expecting 0: will be WILD. _exit has type void ()
Here what happens is that exit is declared like “void _exit();”. This is legal in C, and it allows you to call _exit with whatever arguments you choose. CCured will accept that but the cost will be that the function becomes a WILD function with some significant run-time cost to ensure that you call it correctly. Better, use a correct prototype!
iopause.c:68: Error: You did not turn on the handling of inline assembly. Better hide this assembly somewhere else!
You can turn on the (unsound) handling of inline assembly by passing the argument –allowInlineAssembly to CCured. But you should try instead to hide that inline assembly from CCured. You can put it in a file that CCured does not see, for example (pass the name of that function with the –leavealone argument to CCured).
pathexec_env.c:42: Warning: Encountered sizeof(char */* __attribute__((___ptrnode__(2595))) */) when type contains pointers. Use sizeof expression. Type has a disconnected node.
Section 9.5 explains what the problem could be here.
Warning: Generated automatic vararg descriptor for log_d: struct autoVarargDescr_log_d : char const */* __attribute__((___ptrnode__(922))) */, uid_t If this is a printf-like function you should declare it!
This means that the function log_d is a variable argument function that was not declared using a ccuredvararg pragma. In absence of such a pragma, CCured examines all the call sites of that function and collects the set of types for the arguments. You must inspect the definition of the function involved to ensure that CCured has inferred correctly. If you see that this is not the case, or if the function is a printf-like function, the you should provide an explicit descriptor, as explained in Section 9.6.
#include <stdio.h>
#include <stdarg.h>
void myprintf(int level, const char *fmt, ...)
{
va_list ap;
char msgbuf[2048];
va_start(ap,fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
puts(msgbuf);
va_end(ap);
}
int main()
{
int i;
myprintf(0, "Hello, %s! 2+2=%d\n", "world", 4);
return 0;
}
Browse the CCured inferred pointer kinds,
or see the CCured output
for this code fragmentHere CCured will infer that the possible argument types for myprintf contain only int and char * (based on the call). Yet, the built-in vsnprintf uses a different set of argument types. To fix this problem you must add:
#pragma ccuredvararg("myprintf", printf(2))
/home/necula/ccured/include/netdb_wrappers.h:329: Warning: Solver: changing User Specified SAFE node 1371 (the local variable p_ith_alias) to WILD
This means that CCured must change a user-specified SAFE pointer into WILD. Open the browser (see Section 5.1) and type in the node number in question. Have you annotated that pointer to be SAFE? If yes, then CCured thinks otherwise. If the message is from a wrapper (like the above example) then most likely is a symptom of a badly written wrapper.
/usr/include/sys/socket.h:156: Warning: sendmsg appears to be external (it has a wrapper), yet it has a mangled name: sendmsg_scsws_. Did you forget to use __ptrof and a version of __mkptr? For more information, consult the online documentation on "Writing Wrappers".
In this case CCured mangles the name of the sendmsg function (see Section 8.1). The type of this function is
struct msghdr {
void *msg_name ;
socklen_t msg_namelen ;
struct iovec *msg_iov ;
int msg_iovlen ;
void *msg_control ;
socklen_t msg_controllen ;
int msg_flags ;
};
int sendmsg(int s, const struct msghdr *fat_msg, int flags);
The particular mangling suffix (_scsws_) means that the msg_iov pointer must be WILD. We can investigate why this happens also using the browser. We press “Show types” and then click on msghdr. We see that indeed the msg_iov field is WILD and when we click on the red pointer type we find out that the __trusted_add_iov issue is the cause of this problem.
main.c:278: Warning: Casting scalar (1) to non-WILD pointer in main!This warning says that the given scalar expression is assigned to a pointer lvalue. This assignment probably has the effect that the lvalue is not SAFE. During the assignment, CCured will produce a fat pointer value whose metadata is NULL, which means that it cannot be used to access memory. In this particular case, this is Ok, since nobody in its right mind would plan to use the number 1 as an address.
But sometimes you have a pointer value that is stored in an integer variable and you want later to use it as a pointer. This is not safe in CCured, because the compiler cannot be sure where this pointer originated. There are several ways to solve this one. First, maybe the scalar variable that is being assigned should be a pointer variable after all. If you cannot do that then you must come up with some other pointer variable that is supposed to be in the same home memory area as the scalar. Then you can change the code, as follows:
int * home; int scalar; int * p = (int*)scalar; // Change the last line: int * p = home + (((int)scalar - (int)home) >> 2); // Or, even int * p = __mkptr(scalar, home);
Anyway, it is best if you keep pointer values into pointer variables at all times.
Error: The suffix for the compatible version of sigaction_COMPAT is ws. This means that you have misused this compatible version. Please check your code.
The sigaction_COMPAT is a copy of struct sigaction that CCured creates automatically for use in wrappers. However, that structure should remain compatible with the external version. When you get this error it means that you have written an incorrect wrapper and somehow the constraints from your program flow into the compatible version of the structure. You should use the browser to find out why this happens.
Warning: isImported for CHECK_FORMATARGS, which is not even declared
TODO.
dnssec.c:236: Warning: Casting SAFE void* to FSEQ. The area is 1 word.
TODO.
mathopd_comb.o: In function `log_request': mathopd_comb.o(.text+0x189fd): undefined reference to `asctime_qs'
If the missing function is one with a mangling suffix (see Section 8.1) then this means that CCured has changed the calling convention of the functions involved (in this case asctime) and you need to provide a wrapper to match the calling convention to the library version. See Chapter 8 for details on how to do that.
If the missing function has a “_t” mangling, then it is a WILD function. You have either used the function without a prototype, or with a type that does not match the prototype, or you have cast its pointer to something strange. See if you can fix the prototypes (and fill in the argument types in the function types).
However, if the missing function does not have a mangled name then it means that somehow CCured has lost an external global. This is probably a bug in CIL, most likely in the module that removes unnecessary locals and prototypes. Try disabling that module by passing the –keepunused flag to CCured.
gcc -D_GNUCC -o tcpserver -s tcpserver_comb.o cdb.a dns.a time.a unix.a byte.a cdb.a: could not read symbols: Archive has no index; run ranlib to add one
You look at cdb.a and it is not a object file at all but, starts like this:
!<arch> cdb.o/ 1042137412 1002 100 100644 20279 ` #pragma merger(0, "./cdb.i", "") # 1 "cdb.c" # 1 "/home/necula/ccured/include/gcc_2.95.3/sys/types.h" 1
You look at cdb.o and, indeed, it is not an object file, but a copy of the cdb.i file. This is normal. What happened is that for merging, compilation means just preprocessing (this explains why cdb.o is as it is). But the problem is that you have just invoked the ar program to build a library out of object files that are actually text file. The solution is to use instead of ar the command ccured –mode=AR. This should create the cdb.a library as needed, but if you look at it, it is a C source file that contains all the stuff from the archived files, with the necessary renaming to avoid conflicts between static variables. You can find more information about the merger at ../cil/merger.html.
ranlib: cdb.a: File format not recognized
You look at cdb.a and find that it is a merged source file. You should not use ranlib on such files.
client.c:2139: warning: second parameter of `va_start' not last named argument
TODO.
When you run the code you might get run-time errors. Make sure you read the Chapter 4 on ways to control the handling of errors.
Failure UBOUND at config.c:924: new_pool(): Ubound Aborted
This says that the code triggered an upper bound check. Investigate the problem first by looking at the line number. Also run the program with gdb; it should stop right where the error arises.
There is one relatively common instance when you get a UBound error. Say that the variable ceiling is intended to be the end of a memory area:
int * ceiling = area + area_length;
The area pointer will be inferred FSEQ but the ceiling pointer will be inferred SAFE. This means that before the assignment, CCured will insert an upper-bound check, which will fail.
There are several solutions:
Failure UBOUND at ping.c:1303: main(): Ubound
Also an upper bound. We look at the code and we find the following:
struct icmp {
int various;
char data[1];
};
char outpack[65536];
char foo() {
// Get the 8th data character
return ((struct icmp*)outpack)->data[8];
}
Browse the CCured inferred pointer kinds, or see the CCured output for this code fragment
This looks good overall, but technically we are accessing the 8th character in a 1 character array. Once you cast the outpack array to struct icmp*, you loose access to some of the trailing characters. If you look at the cured code you will see in fact the CCured uses a length of 1 in doing the bounds check.
Instead you could change the code to express more directly what you mean:
struct icmp {
int various;
char data[1];
};
char outpack[65536];
char foo() {
// Get the 8th data character
return * (outpack + (int) &((struct icmp*)0)->data[8]);
}
Browse the CCured inferred pointer kinds, or see the CCured output for this code fragment
Now the access is in the outpack array and its length is used for bounds checking.
Failure STORE_SP at pathexec_env.c:47: pathexec_qq(): Storing stack address
This means that you are trying to store into the heap, a pointer to some stack location. See Section 3.5 for how to fix this. In rare occasions the pointer is from your argv or envp arguments. Use strdup in that case.