Re: [PATCH] string: Improve the generic strlcpy() implementation

From: Linus Torvalds
Date: Mon Oct 05 2015 - 16:40:29 EST


On Mon, Oct 5, 2015 at 5:22 PM, Ingo Molnar <mingo@xxxxxxxxxx> wrote:
>
> We could do something like:
>
> c = *(unsigned long *)(src+res);
> *(unsigned long *)(dest+res) = c;
>
> if (has_zero(c, &data, &constants)) {

No, I think we'd be better off just moving the "has_zero()" to to
before the destination write, and instead doing the destination write
for the "word has zero" case one byte at a time. Sure, you'd need to
do it differently for little- and big-endian, but big deal.

So just something like

c = *(unsigned long *)(src+res);
if (has_zero(c, &data, &constants))
return strscpy_final_word(c, dst, res);
*(unsigned long *)(dest+res) = c;
...

where that "strscpy_final_word()" looks something like

static inline strscpy_final_word(unsigned long word, char *dst, long res)
{
for (;;res++) {
char c;
#ifdef LITTLE_ENDIAN
c = word; word >>= 8;
#else
c = word >> 8*(sizeof(unsigned long)-1); word <<= 8;
#endif
dst[res] = c;
if (!c)
return res;
}
}

which really shouldn't be too bad.

I don't think it's much better to use "memset()" than it is to have
the partially filled from the last word of the source.

For "strncpy_from_user()" we do that "partial source word write", and
it's ok there, mainly because (a) that case isn't even trying to be
some generic interface and (b) "strncpy_from_user()" is really
performance-critical. I suspect for strscpy() we're better off just
being slightly more careful. I don't think it's *nearly* as
performance-critical as something like strncpy_from_user() that is
used for every single pathname copy etc.

Alternatively, if we really do expect strscpy() to maybe be
performance-critical, we could just document the fact that it does
things word-at-a-time and that bytes after the terminating NUL
character are *not* reliable. So we *might* just choose to document
this as an implementation issue. But the "memset()" approach just
looks bad.

Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/