This documentation is for Dovecot v2.x, see wiki1 for v1.x documentation.

Code Design

Types

Boolean expressions

Try to use boolean expressions the way they work in Java. C doesn't require this, I think it makes the code easier to understand and reduces bugs in some cases (e.g. if (!foo()) when thinking foo() returns bool/FALSE, but actually returns int/-1 on error). I'm planning on patching clang some day to give warnings when booleans aren't used properly.

So:

Type safety

Memory

Memory allocations can be assumed to be zero-initialized. All of the memory allocation functions do it, except t_malloc() and t_buffer_get(), which you should almost never use directly anyway. The code currently also assumes that pointers in zero-initialized memory area are NULL, which isn't guaranteed by ANSI-C, but practically Dovecot isn't going to be run in systems where it's not true and you're not going to remember to NULL-initialize all of your pointers anyway without compiler/runtime failure.

Double-frees in C are bad. Better to crash with NULL pointer dereference than possibly allow an attacker to exploit heap corruption and run executable code. Most of the pointers are set to NULL when they are freed:

Callback functions

Callback functions make the code more difficult to follow, especially when a callback calls another callback, or when using function pointers to jump to different callbacks depending on state. Of course with asynchronous C code it's pretty much impossible to avoid callbacks. Still, try to avoid them where possible to keep the code readable.

Often callback functions can be avoided by creating iterator functions instead. For example instead of parse(callback, context use ctx = parse_init(); while (parse_next(ctx)) { .. } parse_deinit(&ctx);

context params / type safety