This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Implement C11 annex K?
- From: Russ Allbery <eagle at eyrie dot org>
- To: libc-alpha at sourceware dot org
- Date: Wed, 13 Aug 2014 16:59:46 -0700
- Subject: Re: Implement C11 annex K?
- Authentication-results: sourceware.org; auth=none
- References: <E1XHe8v-0004Ur-Hp at rmm6prod02 dot runbox dot com> <Pine dot LNX dot 4 dot 64 dot 1408132054090 dot 16622 at digraph dot polyomino dot org dot uk> <53EBD7D9 dot 1040008 at cs dot ucla dot edu> <20140813213520 dot GQ12888 at brightrain dot aerifal dot cx> <53EBEACD dot 3070000 at googlemail dot com>
Tolga Dalman <tolga.dalman@googlemail.com> writes:
> Your argumentation appears inconsistent to me. strlcpy is a bad API by
> design and provides no benefits except convenience for some applications
> (how many use these functions, btw ?). If an application chooses to use
> a non-portable and probably buggy function, well, then the application
> should be fixed. Not glibc.
I've heard this statement a lot, and I certainly have a lot of sympathy
with the argument that one should use dynamic strings. And I do use
asprintf by preference. But this argument is applied so universally,
which leaves me wondering if I'm missing something.
At the risk of drifting off into the weeds (and if you feel like this is
inappropriate for this mailing list, please feel free to only respond in
private or tell me that in private), how would you recommend writing this
function without using strlcpy and strlcat?
/*
* Given a vector and a separator string, allocate and build a new string
* composed of all the strings in the vector separated from each other by the
* seperator string. Caller is responsible for freeing.
*/
char *
vector_join(const struct vector *vector, const char *seperator)
{
char *string;
size_t i, size, seplen;
/* If the vector is empty, this is trivial. */
assert(vector != NULL);
if (vector->count == 0)
return xstrdup("");
/* Determine the total size of the resulting string. */
seplen = strlen(seperator);
for (size = 0, i = 0; i < vector->count; i++)
size += strlen(vector->strings[i]);
size += (vector->count - 1) * seplen + 1;
/* Allocate the memory and build up the string using strlcat. */
string = xmalloc(size);
strlcpy(string, vector->strings[0], size);
for (i = 1; i < vector->count; i++) {
strlcat(string, seperator, size);
strlcat(string, vector->strings[i], size);
}
return string;
}
If the answer is "use strcpy and strcat because this code is provably
correct with them," I guess I understand your position, but if I somehow
messed up the length calculation logic, I would prefer to truncate the
string than to create a buffer overflow. The truncation might still be a
security vulnerability; the buffer overflow is almost guaranteed to be
one. Maybe this is just personal preference.
If you have some method that doesn't involve strcpy and strcat either, and
that you think is as readable as the above, I would love to hear what it
is. That's a sincere question: I would be happy to be taught how to be a
better C programmer.
--
Russ Allbery (eagle@eyrie.org) <http://www.eyrie.org/~eagle/>