summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-03 17:36:09 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-03 17:36:09 +0100
commit4243eb46d0b8df7ce25963fad14acca1dc0c4fe8 (patch)
tree9dd5f1210fc53ebaa0a05c0e273767d9c6d3d536
parentb28e3b7c783636096e6b6a215c998451293a6e46 (diff)
downloadrspamd-4243eb46d0b8df7ce25963fad14acca1dc0c4fe8.tar.gz
rspamd-4243eb46d0b8df7ce25963fad14acca1dc0c4fe8.zip
[Fix] Change copy strategy in strlcpy
-rw-r--r--src/libutil/str_util.c28
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;