/* 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