/* String library */ #define strpnew(s) do { memset(s + sizeof(s) - 1, 0, 1); memset(s, 0, 1); } while (0) #define strpcpy(a,b) strncpy((char *) a, (char *) b, sizeof(a)) #define strpcat(a,b) strncat((char *) a, (char *) b, sizeof(a) - 1) #define strprintf(a,b,...) snprintf(a, sizeof(a) - 1, b, __VA_ARGS__) #endif
These functions operate on automatic (stack-based) strings and can use the sizeof() operator to pass the length of the string through to the underlying C library function. Strings are never allocated on the heap.
/* Good */ printf("%s", some_user_data); /* Bad */ printf(some_user_data);
Calling functions are expected to check this value and propagate errors upward through the call stack. This produces a complete backtrace of the error in the logfile.
Two macros are defined for exception handling: throw() and catch(). When a function detects an error, it calls throw() and provides a description of the error.
Here is an example that shows a simple and an advanced usage of these macros:
#define throw(s) log_error(s); goto error; #define catch() return 0; \ error: \ return -1; int simple_function() { int fd; if (advanced_function() < 0) throw("advanced function failed"); catch(); } int advanced_function() { int fd = -1; int retval = 0; if (creat(fd, "some.file") < 0) throw("Unable to create some.file"); if (fork() < 0) throw("Unable to fork()"); /* ... */ goto cleanup; error: retval = -1; cleanup: if (fd >= 0) close(fd); return retval; }
Since maild is a BSD-licensed free software program, there is no financial compensation for participating in the code review process. However, by helping maild become a "secure" program, your name and analysis will be made public so that future employers or clients can judge your work.
Please send an email message containing a summary of your code review to devel@heily.com, and make sure to include the following information:
Your complete email message -- including message headers -- will be posted, unedited, on this page.
Thanks in advance for your help,
-Mark Heily