diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-04-03 17:36:09 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-04-03 17:36:09 +0100 |
commit | 4243eb46d0b8df7ce25963fad14acca1dc0c4fe8 (patch) | |
tree | 9dd5f1210fc53ebaa0a05c0e273767d9c6d3d536 | |
parent | b28e3b7c783636096e6b6a215c998451293a6e46 (diff) | |
download | rspamd-4243eb46d0b8df7ce25963fad14acca1dc0c4fe8.tar.gz rspamd-4243eb46d0b8df7ce25963fad14acca1dc0c4fe8.zip |
[Fix] Change copy strategy in strlcpy
-rw-r--r-- | src/libutil/str_util.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/src/libutil/str_util.c b/src/libutil/str_util.c index 3552caa4e..513c00d85 100644 --- a/src/libutil/str_util.c +++ b/src/libutil/str_util.c @@ -307,10 +307,17 @@ rspamd_gstring_icase_hash (gconstpointer key) return rspamd_icase_hash (f->str, f->len); } +/* https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord */ #define MEM_ALIGN (sizeof(gsize)-1) -#define ONES ((size_t)-1/UCHAR_MAX) -#define HIGHS (ONES * (UCHAR_MAX/2+1)) -#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS) +#if defined(__LP64__) || defined(_LP64) +#define WORD_TYPE guint64 +#define ZEROMASK 0x7F7F7F7F7F7F7F7FLLU +#else +#define WORD_TYPE guint32 +#define ZEROMASK 0x7F7F7F7FU +#endif + +#define HASZERO(x) ~(((((x) & ZEROMASK) + ZEROMASK) | (x)) | ZEROMASK) gsize rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz) @@ -318,24 +325,31 @@ rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz) gchar *d = dst; const gchar *s = src; gsize n = siz; - gsize *wd; - const gsize *ws; + WORD_TYPE *wd; + const WORD_TYPE *ws; /* Copy as many bytes as will fit */ if (n-- != 0) { if (((uintptr_t) s & MEM_ALIGN) == ((uintptr_t) d & MEM_ALIGN)) { + /* Init copy byte by byte */ for (; ((uintptr_t) s & MEM_ALIGN) && n && (*d = *s); n--, s++, d++); if (n && *s) { wd = (void *) d; ws = (const void *) s; - for (; n >= sizeof (gsize) && !HASZERO(*ws); - n -= sizeof (gsize), ws++, wd++) + /* + * Copy by 32 or 64 bits (causes valgrind warnings) + */ + for (; n >= sizeof (WORD_TYPE) && !HASZERO(*ws); + n -= sizeof (WORD_TYPE), ws++, wd++) { *wd = *ws; + } + d = (void *) wd; s = (const void *) ws; } } + /* Copy the rest */ for (; n && (*d = *s); n--, s++, d++); *d = 0; |