From b8ef681bf93ba393b0ce3168b2af6a6173ae4464 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 7 Dec 2015 18:26:21 +0000 Subject: [PATCH] Fix serializing of hyperscan regexps --- src/hs_helper.c | 8 ++++++-- src/libserver/re_cache.c | 34 ++++++++++++++++++++++++---------- src/libserver/re_cache.h | 2 +- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/hs_helper.c b/src/hs_helper.c index 0e912daa1..220224572 100644 --- a/src/hs_helper.c +++ b/src/hs_helper.c @@ -127,6 +127,7 @@ start_hs_helper (struct rspamd_worker *worker) struct hs_helper_ctx *ctx = worker->ctx; GError *err = NULL; struct rspamd_srv_command srv_cmd; + gint ncompiled; ctx->ev_base = rspamd_prepare_worker (worker, "hs_helper", @@ -136,9 +137,9 @@ start_hs_helper (struct rspamd_worker *worker) msg_warn ("cannot cleanup cache dir '%s'", ctx->hs_dir); } - if (!rspamd_re_cache_compile_hyperscan (ctx->cfg->re_cache, + if ((ncompiled = rspamd_re_cache_compile_hyperscan (ctx->cfg->re_cache, ctx->hs_dir, - &err)) { + &err)) == -1) { msg_err ("failed to compile re cache: %e", err); g_error_free (err); @@ -146,6 +147,9 @@ start_hs_helper (struct rspamd_worker *worker) exit (EXIT_SUCCESS); } + msg_info ("compiled %d regular expressions to the hyperscan tree", + ncompiled); + event_base_loop (ctx->ev_base, 0); rspamd_worker_block_signals (); diff --git a/src/libserver/re_cache.c b/src/libserver/re_cache.c index b6ee1a2c4..e3d7ec075 100644 --- a/src/libserver/re_cache.c +++ b/src/libserver/re_cache.c @@ -631,7 +631,7 @@ rspamd_re_cache_type_from_string (const char *str) return ret; } -gboolean +gint rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, const char *cache_dir, GError **err) @@ -641,7 +641,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, #ifndef WITH_HYPERSCAN g_set_error (err, rspamd_re_cache_quark (), EINVAL, "hyperscan is disabled"); - return FALSE; + return -1; #else GHashTableIter it, cit; gpointer k, v; @@ -654,7 +654,8 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, guint *hs_flags = NULL; const gchar **hs_pats = NULL; gchar *hs_serialized; - gsize serialized_len; + gsize serialized_len, total = 0; + struct iovec iov[3]; g_hash_table_iter_init (&it, cache->re_classes); @@ -667,7 +668,7 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, if (fd == -1) { g_set_error (err, rspamd_re_cache_quark (), errno, "cannot open file " "%s: %s", path, strerror (errno)); - return FALSE; + return -1; } g_hash_table_iter_init (&cit, re_class->re); @@ -740,11 +741,10 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, close (fd); hs_free_compile_error (hs_errors); - return FALSE; + return -1; } g_free (hs_flags); - g_free (hs_ids); g_free (hs_pats); if (hs_serialize_database (test_db, &hs_serialized, @@ -756,31 +756,45 @@ rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, re_class->hash); close (fd); + g_free (hs_ids); hs_free_database (test_db); - return FALSE; + return -1; } hs_free_database (test_db); - if (write (fd, hs_serialized, serialized_len) != (gssize)serialized_len) { + /* Write N, then all ID's and then the compiled structure */ + iov[0].iov_base = &n; + iov[0].iov_len = sizeof (n); + iov[1].iov_base = hs_ids; + iov[1].iov_len = sizeof (*hs_ids) * n; + iov[2].iov_base = hs_serialized; + iov[2].iov_len = serialized_len; + + if (writev (fd, iov, 3) != + (gssize)serialized_len + sizeof (n) + sizeof (*hs_ids) * n) { g_set_error (err, rspamd_re_cache_quark (), errno, "cannot serialize tree of regexp to %s: %s", path, strerror (errno)); close (fd); + g_free (hs_ids); g_free (hs_serialized); - return FALSE; + return -1; } + total += n; + g_free (hs_serialized); + g_free (hs_ids); } close (fd); } - return TRUE; + return total; #endif } diff --git a/src/libserver/re_cache.h b/src/libserver/re_cache.h index 5093689a6..0e1e6ecc8 100644 --- a/src/libserver/re_cache.h +++ b/src/libserver/re_cache.h @@ -129,7 +129,7 @@ enum rspamd_re_type rspamd_re_cache_type_from_string (const char *str); /** * Compile expressions to the hyperscan tree and store in the `cache_dir` */ -gboolean rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, +gint rspamd_re_cache_compile_hyperscan (struct rspamd_re_cache *cache, const char *cache_dir, GError **err); -- 2.39.5