strl* (was: Re: Advent4 patch, second try)
Luis Javier Merino
ljmerino at gmail.com
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
propagation.
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:
BEWARE, UGLIEST API EVER FOLLOWS:
#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)
return;
*size = 1;
} else {
if ((*size + slen) > *nsize) {
*nsize = ((*size + slen + GROW_SIZE - 1) /
GROW_SIZE) * GROW_SIZE;
*dst = (char *) realloc(*dst, *nsize);
if (*dst == NULL)
return;
}
}
strcpy(*dst + *size - 1, src);
*size += slen;
}
More information about the dslinux-devel
mailing list