*/
#include "config.h"
+#include "libutil/util.h"
extern const uint8_t base64_table_dec[256];
#define INNER_LOOP_64 do { \
+ uint64_t str, res, dec; \
+ bool aligned = rspamd_is_aligned_as(c, str); \
+ bool oaligned = rspamd_is_aligned_as(o, res); \
while (inlen >= 13) { \
- uint64_t str, res, dec; \
- memcpy(&str, c, sizeof(str)); \
+ if (aligned) { str = *(uint64_t *)c; } else {memcpy(&str, c, sizeof(str)); } \
str = GUINT64_TO_BE(str); \
if ((dec = base64_table_dec[str >> 56]) > 63) { \
break; \
} \
res |= dec << 16; \
res = GUINT64_FROM_BE(res); \
- *(uint64_t *)o = res; \
+ if (oaligned) {*(uint64_t *)o = res;} else {memcpy(o, &res, sizeof(res));} \
c += 8; \
o += 6; \
outl += 6; \
} while (0)
#define INNER_LOOP_32 do { \
+ uint32_t str, res, dec; \
+ bool aligned = rspamd_is_aligned_as(c, str); \
+ bool oaligned = rspamd_is_aligned_as(o, res); \
while (inlen >= 8) { \
- uint32_t str, res, dec; \
- memcpy(&str, c, sizeof(str)); \
+ if (aligned) { str = *(uint32_t *)c; } else {memcpy(&str, c, sizeof(str)); } \
str = GUINT32_TO_BE(str); \
if ((dec = base64_table_dec[str >> 24]) > 63) { \
break; \
} \
res |= dec << 8; \
res = GUINT32_FROM_BE(res); \
- *(uint32_t *)o = res; \
+ if (oaligned) {*(uint32_t *)o = res;} else {memcpy(o, &res, sizeof(res));} \
c += 4; \
o += 3; \
outl += 3; \
break;
}
*o++ = carry | (q >> 4);
- carry = q << 4;
+ carry = (uint8_t)(q << 4);
leftover++;
outl++;
#include "ucl.h"
#include "fstring.h"
+#include <stdalign.h>
+
#ifdef __cplusplus
extern "C" {
#endif
/* https://graphics.stanford.edu/~seander/bithacks.html#HasMoreInWord */
#define rspamd_str_hasmore(x, n) ((((x)+~0UL/255*(127-(n)))|(x))&~0UL/255*128)
+/*
+ * Check if a pointer is aligned; n must be power of two
+ */
+#define rspamd_is_aligned(p, n) (((uintptr_t)(p) & ((uintptr_t)(n) - 1)) == 0)
+#define rspamd_is_aligned_as(p, v) rspamd_is_aligned(p, _Alignof(__typeof((v))))
static inline gboolean
-rspamd_str_has_8bit (const guchar *beg, gsize len) {
+rspamd_str_has_8bit (const guchar *beg, gsize len)
+{
unsigned long *w;
- gsize i, leftover = len % sizeof (*w);
+ gsize i, leftover;
- w = (unsigned long *) beg;
+ if (rspamd_is_aligned_as (beg, *w)) {
+ leftover = len % sizeof (*w);
+ w = (unsigned long *) beg;
- for (i = 0; i < len / sizeof (*w); i++) {
- if (rspamd_str_hasmore (*w, 127)) {
- return TRUE;
+ for (i = 0; i < len / sizeof (*w); i++) {
+ if (rspamd_str_hasmore (*w, 127)) {
+ return TRUE;
+ }
+
+ w++;
}
- w++;
+ beg = (const guchar *) w;
+ }
+ else {
+ leftover = len;
}
-
- beg = (const guchar *) w;
for (i = 0; i < leftover; i++) {
if (beg[i] > 127) {