Crafting Function: With or Without Buffer Length Parameter?

Posted in kerneltrap.org on August 4, 2009 – 2:07pm

Developing a C API that deals with writing to external provided buffers, I was wondering whether or not I should include parameter buffer length when the length of the data to be written to the buffer is fixed and known in advance from the documentation of the API.

Specifically, should I write:

/**
 * Function write_to_buffer writes object X into the buffer.
 * The size of object X is 20 bytes.
 * This function return zero if the buffer length suffices.
 * Otherwise, -1 is returned.
 *
 * buffer: a pointer to the buffer where the data will be written to
 * buffer_len: the length of the buffer
 */
int
write_to_buffer (void *buffer, size_t buffer_len);

or

/**
 * Function write_to_buffer writes object X into the buffer.
 * The size of object X is 20 bytes.
 * This function returns a pointer to the address after the last
 * written byte in the buffer.
 *
 * buffer: a pointer to the buffer where the data will be written to.
 *         The buffer must have a length of at least 20 bytes.
 */
void *
write_to_buffer (void *buffer);

I went with the second option since at first there is no need to specify the buffer length when in fact any determined programmer can cause a buffer overflow by lying about the true length of the buffer when using the first option. For example, when the true buffer length is 20 bytes, the programmer can invoke the function like: write_to_buffer (buffer, 100).

But, now I realized that from the maintenance point of view, the first option is the best. It is because when the size of the object needs to be changed to be bigger, the buffers provided to any invocation of the function that is overlooked from being modified to match the new length requirement will fail visibly since any invocation of the function knows that the function may fail because the buffer does not suffice (i.e., the programmer has been forced to anticipate the possibility of API change, particularly in the size of the data to be written to the buffer).

To conclude, it is best to ask for buffer length when crafting a function that write to a buffer so as to not have a maintenance nightmare when the size of the data to be written to the buffer increases since any buffer that fails to adjust its length can be spotted readily.

This entry was posted in C, Programming Languages and tagged . Bookmark the permalink.

2 Responses to Crafting Function: With or Without Buffer Length Parameter?

  1. Eus says:

    constant in header
    Posted by strcmp on August 5, 2009 – 3:07am

    If the buffer size is fixed and can only change, when you update your library’s version, it is common to just place a constant in a header file. E.g. myapi.h could contain

    #define WRITE_TO_BUFFER_MAX 20
    

    . Users of the API have to allocate their buffers using this constant. If you really have to raise the length, you have to increment the ABI version (since already compiled code has to use the old version of your library that only writes 20 bytes), but the API stays the same. Alternatively you could use a typedef in the header, if the data is structured.

    Example man pages: getcwd vs. getwd and PATH_MAX (but there the length is not really fixed as in your situation), bind (the typedef is sockaddrt), gethostname/sethostname (they have a define an a len parameter), readdir (typedef dirent), select (typedef fd_set).

    A typedef is logically equivalent to defining a macro, the type’s size is fixed through the definition in the header, and none of the functions using typedefs have len parameters. If you change the typedef, you have to bump the ABI version (code still compiles, but already compiled code needs to link to the old library).

Leave a comment