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.
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
. 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).
What an insight!
Posted by Eus on August 10, 2009 – 10:25am
Hi Ho!
Thank you very much for your comment, strcmp!
You have instilled a new knowledge in my mind :-)
—
Best regards,
Eus (FSF member #4445)
In this digital era, where computing technology is pervasive, your
freedom depends on the software controlling those computing devices.
Join free software movement today! It is free as in freedom, not as in
free beer!
Join: http://www.fsf.org/jf?referrer=4445