This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [libc-alpha] Re: [open-source] Re: Wish for 2002


On Mon, 7 Jan 2002, David Wheeler wrote:

> Date: Mon, 07 Jan 2002 11:01:00 -0500
> From: David Wheeler <dwheeler@ida.org>
> To: Ben Laurie <ben@algroup.co.uk>
> Cc: Paul Eggert <eggert@twinsun.com>, leclerc@austin.sns.slb.com,
>      libc-alpha@sources.redhat.com, open-source@csl.sri.com
> Subject: [libc-alpha] Re: [open-source] Re: Wish for 2002
> 
> 
> Ben Laurie wrote:
>  > Oh please! What's the first mail I read this morning?
>  > A post to Bugtraq
>  > about a buffer overflow in gzip (which, guess what, is a GNU app) that
>  > was incorrectly fixed using strncpy.
> 
> My point exactly.  Because strncpy/strncat are easily misused,
> mistakes get made.  It's better to provide developers
> with easier-to-use, safer alternatives.  For those of you

Nobody in their right mind would argue that strncpy is other than
braindamaged.  So what? Nobody is forced into using this function. With
some effort, it *can* be used properly, and it's been around for ages
and it's in 1990 ANSI/ISO C which makes it highly portable. You can
write a trivial wrapper around it which is easy to use.

> claiming that the GNU C library shouldn't include strl* because
> all GNU tools only use arbitrary length strings... are you prepared
> to claim that _no_ GNU tool ever uses strncpy/strncat?
> I bet a simple grep will refute that.. Bugtraq is already refuting it.

To use strlcpy in that GNU tool, you have to make sure it's detected
by autoconf, and that you can supply an implementation when it's missing.
So you cannot get around writing it yourself.  The gzip utility cannot
just assume that it will only be compiled under BSD, a few proprietary
Unixes and GNU Libc.

This is not an issue for BSD utitilities, which don't have to be
portable outside of the BSD distribution that they are integrated into.

By the way, what are the correct semantics for strlcat? The OpenBSD
source code has a return value that contradicts various BSD man pages.
According to the man pages, the return value is always the sum of
the length of the two original strings. According to the OpenBSD source
code, if the copy limit is smaller than the destination string that is
to be appended to, then the return value is the limit plus the length
of the second string.

> I'm well aware of the GNU guidance to prefer arbitrary-
> length strings, and for general-purpose tools where the
> user is not an adversary that's good guidance.  However,
> if your input is from an adversary, this can also be
> a disadvantage:  the
> adversary may use this as a denial-of-service attack
> (e.g., constantly send you data until all memory fills up).

Preventing this type of attack does not require a fixed-length string
representation. It requires validation of input. A hard limit on all
strings is not the right way to do it, because then truncation can happen
in arbitrary places in the code. If there must be truncation for the
sake of preventing a DoS, that responsibility should be concentrated in
one place, namely where the untrusted data enters the system.

Validation of input does not necessarily mean silently accepting a
truncated version of the input; some other response might be appropriate.
Sheesh!

> It's better to give the programmer the tools necessary to
> easily and securely implement either option.

The programmer has lots of tools. A myriad of programming languages
to choose from, including C++ which has std::string, and other
languages that have strings as a first-class type, such as Lisp,
Python, etc.

You also have the snprintf() tool in the C99 which is implemented
in glibc.

Lastly, you have the tool of being able to define your own functions.
Some programmers choose to struggle with strncpy() rather than make
a more intelligent wrapper. They have tools, but choose not to use them
as effectively as they could; including that tool known as the brain.

The main purpose of a library like glibc is to be the lowest level
interface to operating system that applications use.  C programming
gadgets don't contribute anything to this purpose. Of what use is
strlcpy() to someone who is making, say, Modula 2 bindings to the
operating system? Or to the C++ user who is using standard C++
strings?

If you want these functions added, do it right. First get them adopted
by ANSI C, POSIX or The Single Unix Specification. Even braindamaged
functions that are added to these standards will end up in glibc.

Here are implementations you can use in your C program. They don't rely
on C99 features like snprintf; they will work in a C90 implementation. 
The advantage of having an implementation like this is that your
program remains highly portable.

In a strictly conforming ANSI C program, you cannot use external names
that begin with ``str'', so I use the alternate names lim_strcpy,
and lim_strcat. (Note that these are not unique in the first six
characters, as C90 requires for strict conformance).

/* Written by Kaz Kylheku, assigned to public domain. */
#include <string.h>

#define MIN(a, b) ((a) < (b) ? (a) : (b))

size_t lim_strcpy(char *dst, const char *src, size_t lim)
{
  size_t src_len = strlen(src);
  size_t copy_size = MIN(lim, src_len + 1);

  if (copy_size > 0) {
    memcpy(dst, src, copy_size);
    dst[copy_size - 1] = 0;
  }

  return src_len;
}

size_t lim_strcat(char *dst, const char *src, size_t lim)
{
  size_t dst_len = strlen(dst);

  if (lim > dst_len + 1)
    return dst_len + lim_strcpy(dst + dst_len, src, lim - dst_len);

  return dst_len + strlen(src);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]