C Programming – Should C Library Functions Always Expect a String’s Length?

apicstrings

I'm currently working on a library written in C. Many functions of this library expect a string as char* or const char* in their arguments. I started out with those functions always expecting the string's length as a size_t so that null-termination wasn't required. However, when writing tests, this resulted in frequent use of strlen(), like so:

const char* string = "Ugh, strlen is tedious";
libFunction(string, strlen(string));

Trusting the user to pass properly terminated strings would lead to less safe, but more concise and (in my opinion) readable code:

libFunction("I hope there's a null-terminator there!");

So, what's the sensible practice here? Make the API more complicated to use, but force the user to think of their input, or document the requirement for a null-terminated string and trust the caller?

Best Answer

Most definitely and absolutely carry the length around. The standard C library is infamously broken this way, which has caused no end of pain in dealing with buffer overflows. This approach is the focus of so much hatred and anguish that modern compilers will actually warn, whine and complain when using this kind standard library functions.

It is so bad, that if you ever come across this question at an interview - and your technical interviewer looks like he's got a few years of experience - pure zealotry may land the job - you can actually get pretty far ahead if you can cite the precedent of shooting someone implementing APIs looking for the C string terminator.

Leaving the emotion of it all aside, there is much that can go wrong with that NULL at the end of your string, in both reading and manipulating it - plus it is really in direct violation of modern design concepts such as defense-in-depth (not necessarily applied to security, but to API design). Examples of C APIs which carry the length abound - ex. the Windows API.

In fact, this problem was settled sometime in the '90s, today's emerging consensus is that you shouldn't even touch your strings.

Later edit: this is quite a live debate so I'll add that trusting everyone below and above you to be nice and use the library str* functions is OK, until you see classic stuff like output = malloc(strlen(input)); strcpy(output, input); or while(*src) { *dest=transform(*src); dest++; src++; }. I can almost hear Mozart's Lacrimosa in the background.

Related Topic