Обсуждение: Coding note: truncating with strlcpy() is not such a hot idea

Поиск
Список
Период
Сортировка

Coding note: truncating with strlcpy() is not such a hot idea

От
Tom Lane
Дата:
There's been some effort to replace uses of strncpy() and our homegrown
StrNCpy() macro with strlcpy().  I had my nose rubbed today in the fact
that that isn't always a good transformation.  The reason why not is that
strlcpy() is defined to return strlen(src), which means that even after
it's transferred all the bytes it's going to, it keeps walking down the
source string looking for a '\0'.  Therefore:

1. Using strlcpy to copy from sources that are not known null-terminated
is outright unsafe: someday, you'll fall off the end of memory and
SIGSEGV.

2. Even with a known null-terminated string, using strlcpy to chop small
pieces out of it is not bright, because each call will traverse all the
rest of the input.  This means for example that extracting N words out
of a long string will spend O(N^2) time in strlcpy.

I ran into the latter effect in tab-complete.c; the old coding there
used strlcpy as a substitute for memcpy and explicit placement of
a trailing '\0'.  We hadn't noticed the problem because it never got
done more than nine times per query, but with the new dispensation
of parsing the whole input line, the O(N^2) cost became obvious.

I did a quick troll looking for places where we might have either an
actual bug or a performance problem worth worrying about, and did not find
others, though it was a very quick scan and I might've missed something.

In general, I would say that it's best to use strlcpy() only as a safety
blanket to protect fixed-length buffers that you're not really intending
to overflow.  If you are expecting it to actually truncate strings in
normal use, there is a significant risk that You're Doing It Wrong.
Caveat programmer.
        regards, tom lane



Re: Coding note: truncating with strlcpy() is not such a hot idea

От
Noah Misch
Дата:
On Mon, Dec 21, 2015 at 03:47:56PM -0500, Tom Lane wrote:
> 1. Using strlcpy to copy from sources that are not known null-terminated
> is outright unsafe: someday, you'll fall off the end of memory and
> SIGSEGV.
> 
> 2. Even with a known null-terminated string, using strlcpy to chop small
> pieces out of it is not bright, because each call will traverse all the
> rest of the input.  This means for example that extracting N words out
> of a long string will spend O(N^2) time in strlcpy.

Good points.