strl* (was: Re: Advent4 patch, second try)

Luis Javier Merino ljmerino at
Thu Sep 27 22:50:37 CEST 2007

> Can you explain to me why truncating strings and ensuring that the
> truncated result is null-terminated can lead to buffer overflows?
> I've seen Drepper make the same point without explaining why
> this could happen.

Oops, sleep deprivation on my part, I actually meant security
vulnerabilities, such as when dealing with file paths.

> Also the return values of strl* tell you whether a string
> was truncated or not. So you can easily fix the app to behave properly
> if truncation occurs.

I see, didn't know it. Shame on me.

> Second, some functions already in glibc are not in any standard either,
> While porting a Linux program to *BSD, I had to copy dprintf and vdprintf
> from glibc. I was lucky the Linux program I was porting is GPL'd, else
> I would have had to rewrite them myself using the man page as a spec
> and I would have likely gotten them subtly wrong.
> See the dprintf man page:
>   These  functions  are  GNU extensions, not in C or POSIX.  Clearly, the
>   names were badly chosen.  Many systems (like MacOS)  have  incompatible
>   functions called dprintf(), usually some debugging version of printf(),
> So glibc already contains non-standard functions, and they even chose
> names that were already being used somewhere else for something
> completely different.
> Hence I don't see how the "it's not part of any standard" argument applies.
> > Besides, a good API for dynamically allocated buffers is at least as
> > easy to use as str* functions.
> What API do you mean? memcpy?

A custom one, like the ones on Postfix and Qmail.

Actually the reason to avoid pushing strl* is to avoid people thinking
they solve all problems with strings, they don't. If there was any
standard for dynamic strings I'd guess noone would oppose strl* meme

For the record, I'm not pushing for bare memcpy, I'm pushing for
dynamic strings. Something internally similar to the following, but
with a sane API:


#define GROW_SIZE       1000
static void grow(char **dst, int *size, int *nsize, char *src, int slen)
        if (*size == 0) {
                *nsize = ((slen + GROW_SIZE) / GROW_SIZE) * GROW_SIZE;
                *dst = (char *) malloc(*nsize);
                if (*dst == NULL)
                *size = 1;
        } else {
                if ((*size + slen) > *nsize) {
                        *nsize = ((*size + slen + GROW_SIZE - 1) /
                        *dst = (char *) realloc(*dst, *nsize);
                        if (*dst == NULL)

        strcpy(*dst + *size - 1, src);
        *size += slen;

More information about the dslinux-devel mailing list