From 3ebceeece2204d3755df1f1cc8210f7e97b6daad Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 16 Nov 2010 22:00:29 +0300 Subject: [PATCH] Make own strlcpy that does not calculate remaining string length (faster and more safe) Allow only ASCII symbols in logs, escape control chars --- src/binlog.c | 4 +- src/cfg_utils.c | 8 +- src/cfg_xml.c | 10 +-- src/evdns/evdns.c | 2 +- src/expressions.c | 10 +-- src/fuzzy_storage.c | 4 +- src/html.c | 2 +- src/lmtp_proto.c | 4 +- src/logger.c | 15 ++-- src/map.c | 6 +- src/plugins/custom/regmark/prefix_tree.c | 4 +- src/plugins/custom/regmark/regmark.c | 2 +- src/plugins/fuzzy_check.c | 10 +-- src/plugins/surbl.c | 4 +- src/smtp.c | 4 +- src/smtp_proto.c | 20 ++--- src/spf.c | 4 +- src/statfile.c | 4 +- src/statfile_sync.c | 2 +- src/symbols_cache.c | 4 +- src/util.c | 94 ++++++++++++++++++++++-- src/util.h | 23 ++++++ test/rspamd_memcached_test.c | 2 +- 23 files changed, 176 insertions(+), 66 deletions(-) diff --git a/src/binlog.c b/src/binlog.c index 955ddc68a..76cfa0cca 100644 --- a/src/binlog.c +++ b/src/binlog.c @@ -167,8 +167,8 @@ binlog_open (memory_pool_t *pool, const gchar *path, time_t rotate_time, gint ro } new->filename = memory_pool_alloc (pool, len + sizeof (BINLOG_SUFFIX)); - g_strlcpy (new->filename, path, len + 1); - g_strlcpy (new->filename + len, BINLOG_SUFFIX, sizeof (BINLOG_SUFFIX)); + rspamd_strlcpy (new->filename, path, len + 1); + rspamd_strlcpy (new->filename + len, BINLOG_SUFFIX, sizeof (BINLOG_SUFFIX)); if (stat (new->filename, &st) == -1) { /* Check errno to check whether we should create this file */ diff --git a/src/cfg_utils.c b/src/cfg_utils.c index 27af7911a..6432b2474 100644 --- a/src/cfg_utils.c +++ b/src/cfg_utils.c @@ -591,7 +591,7 @@ parse_err (const gchar *fmt, ...) gint r; va_start (aq, fmt); - g_strlcpy (readbuf, yytext, sizeof (readbuf)); + rspamd_strlcpy (readbuf, yytext, sizeof (readbuf)); r = snprintf (logbuf, sizeof (logbuf), "config file parse error! line: %d, text: %s, reason: ", yylineno, readbuf); r += vsnprintf (logbuf + r, sizeof (logbuf) - r, fmt, aq); @@ -608,7 +608,7 @@ parse_warn (const gchar *fmt, ...) gint r; va_start (aq, fmt); - g_strlcpy (readbuf, yytext, sizeof (readbuf)); + rspamd_strlcpy (readbuf, yytext, sizeof (readbuf)); r = snprintf (logbuf, sizeof (logbuf), "config file parse warning! line: %d, text: %s, reason: ", yylineno, readbuf); r += vsnprintf (logbuf + r, sizeof (logbuf) - r, fmt, aq); @@ -647,7 +647,7 @@ parse_comma_list (memory_pool_t * pool, gchar *line) while (*p) { if (*p == ',' && *c != *p) { str = memory_pool_alloc (pool, p - c + 1); - g_strlcpy (str, c, p - c + 1); + rspamd_strlcpy (str, c, p - c + 1); res = g_list_prepend (res, str); /* Skip spaces */ while (g_ascii_isspace (*(++p))); @@ -774,7 +774,7 @@ parse_lua_normalizer (struct config_file *cfg, struct statfile *st, const gchar /* Put function name */ len = code_begin - line; code_begin = memory_pool_alloc (cfg->cfg_pool, len + 1); - g_strlcpy (code_begin, line, len + 1); + rspamd_strlcpy (code_begin, line, len + 1); params = g_list_prepend (params, code_begin); } memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_list_free, params); diff --git a/src/cfg_xml.c b/src/cfg_xml.c index 2e762ba1e..67523c845 100644 --- a/src/cfg_xml.c +++ b/src/cfg_xml.c @@ -456,7 +456,7 @@ xml_asciiz_string (memory_pool_t *pool, const gchar *text, gsize len) gchar *val; val = memory_pool_alloc (pool, len + 1); - g_strlcpy (val, text, len + 1); + rspamd_strlcpy (val, text, len + 1); return val; } @@ -1336,7 +1336,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam ud->section_pointer = check_worker_conf (ud->cfg, NULL); } else if (g_ascii_strcasecmp (element_name, "lua") == 0) { - g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); + rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values); if (! handle_lua (ud->cfg, ud, ud->cur_attrs, NULL, NULL, ud->cfg, 0)) { *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s'", ud->section_name); @@ -1353,7 +1353,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam } else { /* Extract other tags */ - g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); + rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values); ud->state = XML_READ_VALUE; } @@ -1367,7 +1367,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam ud->section_pointer = memory_pool_alloc0 (ud->cfg->cfg_pool, sizeof (struct statfile)); } else { - g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); + rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); /* Save attributes */ ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values); } @@ -1379,7 +1379,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam case XML_READ_WORKER: case XML_READ_LOGGING: case XML_READ_VIEW: - g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); + rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name)); /* Save attributes */ ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values); break; diff --git a/src/evdns/evdns.c b/src/evdns/evdns.c index 5401104b5..ce7c0b429 100644 --- a/src/evdns/evdns.c +++ b/src/evdns/evdns.c @@ -2474,7 +2474,7 @@ request_new(struct evdns_base *base, int type, const char *name, int flags, if (base->global_randomize_case) { unsigned i; char randbits[(sizeof(namebuf)+7)/8]; - g_strlcpy(namebuf, name, sizeof(namebuf)); + rspamd_strlcpy(namebuf, name, sizeof(namebuf)); rand_bytes_function(randbits, (name_len+7)/8); for (i = 0; i < name_len; ++i) { if (g_ascii_isalpha(namebuf[i])) { diff --git a/src/expressions.c b/src/expressions.c index 1f83c2827..21409c81e 100644 --- a/src/expressions.c +++ b/src/expressions.c @@ -419,7 +419,7 @@ parse_expression (memory_pool_t * pool, gchar *line) p++; } str = memory_pool_alloc (pool, p - c + 2); - g_strlcpy (str, c - 1, (p - c + 2)); + rspamd_strlcpy (str, c - 1, (p - c + 2)); g_strstrip (str); msg_debug ("found regexp: %s", str); if (strlen (str) > 0) { @@ -445,7 +445,7 @@ parse_expression (memory_pool_t * pool, gchar *line) func = memory_pool_alloc (pool, sizeof (struct expression_function)); func->name = memory_pool_alloc (pool, p - c + 1); func->args = NULL; - g_strlcpy (func->name, c, (p - c + 1)); + rspamd_strlcpy (func->name, c, (p - c + 1)); g_strstrip (func->name); state = READ_FUNCTION_ARGUMENT; g_queue_push_tail (function_stack, func); @@ -456,7 +456,7 @@ parse_expression (memory_pool_t * pool, gchar *line) /* In fact it is not function, but symbol */ if (c != p) { str = memory_pool_alloc (pool, p - c + 1); - g_strlcpy (str, c, (p - c + 1)); + rspamd_strlcpy (str, c, (p - c + 1)); g_strstrip (str); if (strlen (str) > 0) { insert_expression (pool, &expr, EXPR_STR, 0, str, copy); @@ -469,7 +469,7 @@ parse_expression (memory_pool_t * pool, gchar *line) p++; if (c != p) { str = memory_pool_alloc (pool, p - c + 1); - g_strlcpy (str, c, (p - c + 1)); + rspamd_strlcpy (str, c, (p - c + 1)); g_strstrip (str); if (strlen (str) > 0) { insert_expression (pool, &expr, EXPR_STR, 0, str, copy); @@ -492,7 +492,7 @@ parse_expression (memory_pool_t * pool, gchar *line) if (*p == ',' || (*p == ')' && brackets == 0)) { arg = NULL; str = memory_pool_alloc (pool, p - c + 1); - g_strlcpy (str, c, (p - c + 1)); + rspamd_strlcpy (str, c, (p - c + 1)); g_strstrip (str); /* Recursive call */ arg = maybe_parse_expression (pool, str); diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index 1bbe0dd3c..dc18a694d 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -172,10 +172,10 @@ sync_cache (struct rspamd_worker *wrk) node = *((struct rspamd_fuzzy_node **)pvalue); if (now - node->time > expire) { /* Remove expired item */ - g_strlcpy (tmpindex, indexbuf, sizeof (tmpindex)); + rspamd_strlcpy (tmpindex, indexbuf, sizeof (tmpindex)); pvalue = JudySLNext (jtree, tmpindex, PJE0); JudySLDel (&jtree, indexbuf, PJE0); - g_strlcpy (indexbuf, tmpindex, sizeof (indexbuf)); + rspamd_strlcpy (indexbuf, tmpindex, sizeof (indexbuf)); bloom_del (bf, node->h.hash_pipe); server_stat->fuzzy_hashes_expired ++; server_stat->fuzzy_hashes --; diff --git a/src/html.c b/src/html.c index 810ba963b..1747c7ce2 100644 --- a/src/html.c +++ b/src/html.c @@ -778,7 +778,7 @@ parse_tag_url (struct worker_task *task, struct mime_text_part *part, tag_id_t i } url_text = memory_pool_alloc (task->task_pool, len + 1); - g_strlcpy (url_text, c, len + 1); + rspamd_strlcpy (url_text, c, len + 1); decode_entitles (url_text, NULL); if (g_ascii_strncasecmp (url_text, "http://", sizeof ("http://") - 1) != 0 && diff --git a/src/lmtp_proto.c b/src/lmtp_proto.c index b81daf240..de2305924 100644 --- a/src/lmtp_proto.c +++ b/src/lmtp_proto.c @@ -131,7 +131,7 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) } lmtp->task->helo = memory_pool_alloc (lmtp->task->task_pool, line->len - i + 1); /* Strlcpy makes string null terminated by design */ - g_strlcpy (lmtp->task->helo, c, line->len - i + 1); + rspamd_strlcpy (lmtp->task->helo, c, line->len - i + 1); lmtp->state = LMTP_READ_FROM; if (! out_lmtp_reply (lmtp->task, LMTP_OK, "", "Ok")) { return -1; @@ -203,7 +203,7 @@ read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line) } rcpt = memory_pool_alloc (lmtp->task->task_pool, line->len - i + 1); /* Strlcpy makes string null terminated by design */ - g_strlcpy (rcpt, c, line->len - i + 1); + rspamd_strlcpy (rcpt, c, line->len - i + 1); lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt); lmtp->state = LMTP_READ_MESSAGE; if (! out_lmtp_reply (lmtp->task, LMTP_DATA, "", "Enter message, ending with \".\" on a line by itself")) { diff --git a/src/logger.c b/src/logger.c index 01e0210ec..87217fb87 100644 --- a/src/logger.c +++ b/src/logger.c @@ -318,7 +318,7 @@ flush_log_buf (void) void rspamd_common_log_function (GLogLevelFlags log_level, const gchar *function, const gchar *fmt, ...) { - static gchar logbuf[BUFSIZ]; + static gchar logbuf[BUFSIZ], escaped_logbuf[BUFSIZ]; va_list vp; u_char *end; @@ -326,8 +326,9 @@ rspamd_common_log_function (GLogLevelFlags log_level, const gchar *function, con va_start (vp, fmt); end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, vp); *end = '\0'; + (void)rspamd_escape_string (escaped_logbuf, logbuf, sizeof (escaped_logbuf)); va_end (vp); - rspamd_log->log_func (NULL, function, log_level, logbuf, FALSE, rspamd_log->cfg); + rspamd_log->log_func (NULL, function, log_level, escaped_logbuf, FALSE, rspamd_log->cfg); } } @@ -550,7 +551,7 @@ file_log_function (const gchar * log_domain, const gchar *function, GLogLevelFla void rspamd_conditional_debug (guint32 addr, const gchar *function, const gchar *fmt, ...) { - static gchar logbuf[BUFSIZ]; + static gchar logbuf[BUFSIZ], escaped_logbuf[BUFSIZ]; va_list vp; u_char *end; @@ -560,16 +561,20 @@ rspamd_conditional_debug (guint32 addr, const gchar *function, const gchar *fmt, va_start (vp, fmt); end = rspamd_vsnprintf (logbuf, sizeof (logbuf), fmt, vp); *end = '\0'; + (void)rspamd_escape_string (escaped_logbuf, logbuf, sizeof (escaped_logbuf)); va_end (vp); - rspamd_log->log_func (NULL, function, G_LOG_LEVEL_DEBUG, logbuf, TRUE, rspamd_log->cfg); + rspamd_log->log_func (NULL, function, G_LOG_LEVEL_DEBUG, escaped_logbuf, TRUE, rspamd_log->cfg); } } void rspamd_glib_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg) { + gchar escaped_logbuf[BUFSIZ]; + if (rspamd_log->enabled) { - rspamd_log->log_func (log_domain, NULL, log_level, message, FALSE, rspamd_log->cfg); + (void)rspamd_escape_string (escaped_logbuf, message, sizeof (escaped_logbuf)); + rspamd_log->log_func (log_domain, NULL, log_level, escaped_logbuf, FALSE, rspamd_log->cfg); } } diff --git a/src/map.c b/src/map.c index b5825206a..dab939321 100644 --- a/src/map.c +++ b/src/map.c @@ -134,7 +134,7 @@ parse_http_reply (u_char * chunk, size_t len, struct http_reply *reply) case 2: if (*p == ':') { reply->cur_header = g_malloc (p - s + 1); - g_strlcpy (reply->cur_header, s, p - s + 1); + rspamd_strlcpy (reply->cur_header, s, p - s + 1); reply->parser_state = 3; } else if (*p == '\r' && *(p + 1) == '\n') { @@ -158,7 +158,7 @@ parse_http_reply (u_char * chunk, size_t len, struct http_reply *reply) if (*p == '\r') { if (reply->cur_header != NULL) { tmp = g_malloc (p - s + 1); - g_strlcpy (tmp, s, p - s + 1); + rspamd_strlcpy (tmp, s, p - s + 1); g_hash_table_insert (reply->headers, reply->cur_header, tmp); reply->cur_header = NULL; } @@ -476,7 +476,7 @@ add_map (const gchar *map_line, map_cb_t read_callback, map_fin_cb_t fin_callbac hostend = p; } hdata->host = memory_pool_alloc (map_pool, hostend - def + 1); - g_strlcpy (hdata->host, def, hostend - def + 1); + rspamd_strlcpy (hdata->host, def, hostend - def + 1); hdata->path = memory_pool_strdup (map_pool, p); hdata->rlen = 0; /* Now try to resolve */ diff --git a/src/plugins/custom/regmark/prefix_tree.c b/src/plugins/custom/regmark/prefix_tree.c index 4d593ebbc..5e8607aae 100644 --- a/src/plugins/custom/regmark/prefix_tree.c +++ b/src/plugins/custom/regmark/prefix_tree.c @@ -82,7 +82,7 @@ add_string_common (prefix_tree_t *tree, const char *input, int skip_levels, gboo else { /* Create new tree */ prefix = g_malloc (cur_level * sizeof (char) + 1); - g_strlcpy (prefix, orig, cur_level + 1); + rspamd_strlcpy (prefix, orig, cur_level + 1); cur->leafs[num].data = g_tree_new_full (compare_prefixes, NULL, g_free, NULL); g_tree_insert (cur->leafs[num].data, prefix, GUINT_TO_POINTER (1)); return 1; @@ -90,7 +90,7 @@ add_string_common (prefix_tree_t *tree, const char *input, int skip_levels, gboo } else { /* Got some node, so check it */ - g_strlcpy (tmp, orig, MIN (sizeof (tmp), cur_level + 1)); + rspamd_strlcpy (tmp, orig, MIN (sizeof (tmp), cur_level + 1)); if ((res = (uintptr_t)g_tree_lookup (cur->leafs[num].data, tmp)) != 0) { if (! read_only) { g_tree_insert (cur->leafs[num].data, g_strdup (tmp), GUINT_TO_POINTER (res + 1)); diff --git a/src/plugins/custom/regmark/regmark.c b/src/plugins/custom/regmark/regmark.c index b28c07183..3b0e50903 100644 --- a/src/plugins/custom/regmark/regmark.c +++ b/src/plugins/custom/regmark/regmark.c @@ -141,7 +141,7 @@ parse_line (const char *line, size_t len, char **output, void *user_data) while (p - line <= len) { if (g_ascii_isspace (*p) || p - line == len) { name = g_malloc (p - line + 1); - g_strlcpy (name, line, p - line + 1); + rspamd_strlcpy (name, line, p - line + 1); if (metaphone (name, 0, &metaname)) { /* Skip spaces */ while (p - line <= len && g_ascii_isspace (*p)) { diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c index 34b4cba5b..70abea2cd 100644 --- a/src/plugins/fuzzy_check.c +++ b/src/plugins/fuzzy_check.c @@ -248,7 +248,7 @@ parse_servers_string (gchar *str) port = DEFAULT_PORT; } name = memory_pool_alloc (fuzzy_module_ctx->fuzzy_pool, p - strvec[i]); - g_strlcpy (name, strvec[i], p - strvec[i]); + rspamd_strlcpy (name, strvec[i], p - strvec[i]); if (!inet_aton (name, &addr)) { /* Resolve using dns */ hent = gethostbyname (name); @@ -675,7 +675,7 @@ fuzzy_symbol_callback (struct worker_task *task, void *unused) checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, image->data->data, image->data->len); /* Construct fake fuzzy hash */ fake_fuzzy = memory_pool_alloc0 (task->task_pool, sizeof (fuzzy_hash_t)); - g_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); + rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); register_fuzzy_call (task, fake_fuzzy); g_free (checksum); } @@ -692,7 +692,7 @@ fuzzy_symbol_callback (struct worker_task *task, void *unused) checksum = g_compute_checksum_for_data (G_CHECKSUM_MD5, mime_part->content->data, mime_part->content->len); /* Construct fake fuzzy hash */ fake_fuzzy = memory_pool_alloc0 (task->task_pool, sizeof (fuzzy_hash_t)); - g_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); + rspamd_strlcpy (fake_fuzzy->hash_pipe, checksum, sizeof (fake_fuzzy->hash_pipe)); register_fuzzy_call (task, fake_fuzzy); g_free (checksum); } @@ -833,7 +833,7 @@ fuzzy_process_handler (struct controller_session *session, f_str_t * in) /* Construct fake fuzzy hash */ fake_fuzzy.block_size = 0; bzero (fake_fuzzy.hash_pipe, sizeof (fake_fuzzy.hash_pipe)); - g_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); + rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); if (! register_fuzzy_controller_call (session, task, &fake_fuzzy, cmd, value, flag, saved)) { /* Cannot write hash */ session->state = STATE_REPLY; @@ -863,7 +863,7 @@ fuzzy_process_handler (struct controller_session *session, f_str_t * in) /* Construct fake fuzzy hash */ fake_fuzzy.block_size = 0; bzero (fake_fuzzy.hash_pipe, sizeof (fake_fuzzy.hash_pipe)); - g_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); + rspamd_strlcpy (fake_fuzzy.hash_pipe, checksum, sizeof (fake_fuzzy.hash_pipe)); if (! register_fuzzy_controller_call (session, task, &fake_fuzzy, cmd, value, flag, saved)) { /* Cannot write hash */ session->state = STATE_REPLY; diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c index 8627cbbca..bcaa30021 100644 --- a/src/plugins/surbl.c +++ b/src/plugins/surbl.c @@ -444,7 +444,7 @@ format_surbl_request (memory_pool_t * pool, f_str_t * hostname, struct suffix_it } else if (is_numeric && dots_num == 0) { /* This is number */ - g_strlcpy (num_buf, hostname->begin, MIN (hostname->len + 1, sizeof (num_buf))); + rspamd_strlcpy (num_buf, hostname->begin, MIN (hostname->len + 1, sizeof (num_buf))); errno = 0; ip_num = strtoull (num_buf, NULL, 10); if (errno != 0) { @@ -713,7 +713,7 @@ register_memcached_call (struct uri *url, struct worker_task *task, GTree * url_ cur_param->bufsize = sizeof (gint); sum_str = g_compute_checksum_for_string (G_CHECKSUM_MD5, struri (url), -1); - g_strlcpy (cur_param->key, sum_str, sizeof (cur_param->key)); + rspamd_strlcpy (cur_param->key, sum_str, sizeof (cur_param->key)); g_free (sum_str); selected = (struct memcached_server *)get_upstream_by_hash ((void *)task->cfg->memcached_servers, diff --git a/src/smtp.c b/src/smtp.c index f2d2e790a..859a83917 100644 --- a/src/smtp.c +++ b/src/smtp.c @@ -300,7 +300,7 @@ process_smtp_data (struct smtp_session *session) if (cur) { f = cur->data; s = memory_pool_alloc (session->pool, f->len + 1); - g_strlcpy (s, f->begin, f->len + 1); + rspamd_strlcpy (s, f->begin, f->len + 1); session->task->from = s; } /* Save recipients */ @@ -310,7 +310,7 @@ process_smtp_data (struct smtp_session *session) if (cur) { f = cur->data; s = memory_pool_alloc (session->pool, f->len + 1); - g_strlcpy (s, f->begin, f->len + 1); + rspamd_strlcpy (s, f->begin, f->len + 1); session->task->rcpt = g_list_prepend (session->task->rcpt, s); } t = g_list_next (t); diff --git a/src/smtp_proto.c b/src/smtp_proto.c index 6df3c18c6..5a3ccebd8 100644 --- a/src/smtp_proto.c +++ b/src/smtp_proto.c @@ -229,7 +229,7 @@ parse_smtp_helo (struct smtp_session *session, struct smtp_command *cmd) } arg = cmd->args->data; session->helo = memory_pool_alloc (session->pool, arg->len + 1); - g_strlcpy (session->helo, arg->begin, arg->len + 1); + rspamd_strlcpy (session->helo, arg->begin, arg->len + 1); /* Now try to write reply */ if (cmd->command == SMTP_COMMAND_HELO) { /* No ESMTP */ @@ -399,7 +399,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) r = check_smtp_ustream_reply (in, '2'); if (r == -1) { session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); @@ -438,7 +438,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) r = check_smtp_ustream_reply (in, '2'); if (r == -1) { session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); @@ -468,7 +468,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) r = check_smtp_ustream_reply (in, '2'); if (r == -1) { session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); @@ -492,7 +492,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) r = check_smtp_ustream_reply (in, '2'); if (r == -1) { session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); @@ -518,7 +518,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) r = check_smtp_ustream_reply (in, '2'); if (r == -1) { session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); rspamd_dispatcher_restore (session->dispatcher); if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { goto err; @@ -550,7 +550,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) rspamd_dispatcher_pause (session->upstream_dispatcher); } session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); /* Write to client */ if (! rspamd_dispatcher_write (session->dispatcher, session->error, in->len, FALSE, TRUE)) { goto err; @@ -568,7 +568,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) r = check_smtp_ustream_reply (in, '3'); if (r == -1) { session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); @@ -606,7 +606,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) break; case SMTP_STATE_AFTER_DATA: session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); session->state = SMTP_STATE_DATA; rspamd_dispatcher_restore (session->dispatcher); if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { @@ -625,7 +625,7 @@ smtp_upstream_read_socket (f_str_t * in, void *arg) r = check_smtp_ustream_reply (in, '5'); if (r == -1) { session->error = memory_pool_alloc (session->pool, in->len + 1); - g_strlcpy (session->error, in->begin, in->len + 1); + rspamd_strlcpy (session->error, in->begin, in->len + 1); /* XXX: assume upstream errors as critical errors */ session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); diff --git a/src/spf.c b/src/spf.c index fcfdbd05c..fcbefeab2 100644 --- a/src/spf.c +++ b/src/spf.c @@ -206,7 +206,7 @@ parse_spf_hostmask (struct worker_task *task, const gchar *begin, struct spf_add p = strchr (begin, '/'); if (p != NULL) { /* Extract mask */ - g_strlcpy (mask_buf, p + 1, sizeof (mask_buf)); + rspamd_strlcpy (mask_buf, p + 1, sizeof (mask_buf)); addr->mask = mask_buf[0] * 10 + mask_buf[1]; if (addr->mask > 32) { return FALSE; @@ -214,7 +214,7 @@ parse_spf_hostmask (struct worker_task *task, const gchar *begin, struct spf_add if (host == NULL) { hostlen = p - begin; host = memory_pool_alloc (task->task_pool, hostlen); - g_strlcpy (host, begin, hostlen); + rspamd_strlcpy (host, begin, hostlen); } } else { diff --git a/src/statfile.c b/src/statfile.c index b26664fd5..cf8d12e3f 100644 --- a/src/statfile.c +++ b/src/statfile.c @@ -342,7 +342,7 @@ statfile_pool_open (statfile_pool_t * pool, gchar *filename, size_t size, gboole } - g_strlcpy (new_file->filename, filename, sizeof (new_file->filename)); + rspamd_strlcpy (new_file->filename, filename, sizeof (new_file->filename)); new_file->len = st.st_size; /* Aqquire lock for this operation */ lock_file (new_file->fd, FALSE); @@ -633,7 +633,7 @@ stat_file_t * statfile_pool_is_open (statfile_pool_t * pool, gchar *filename) { static stat_file_t f, *ret; - g_strlcpy (f.filename, filename, sizeof (f.filename)); + rspamd_strlcpy (f.filename, filename, sizeof (f.filename)); ret = lfind (&f, pool->files, (size_t *)&pool->opened, sizeof (stat_file_t), cmpstatfile); return ret; } diff --git a/src/statfile_sync.c b/src/statfile_sync.c index 2d2ead525..5189f1ead 100644 --- a/src/statfile_sync.c +++ b/src/statfile_sync.c @@ -114,7 +114,7 @@ parse_revision_line (struct rspamd_sync_ctx *ctx, f_str_t *in) /* One more character */ p ++; } - g_strlcpy (numbuf, c, MIN (p - c + 1, sizeof (numbuf))); + rspamd_strlcpy (numbuf, c, MIN (p - c + 1, sizeof (numbuf))); errno = 0; *val = strtoull (numbuf, NULL, 10); if (errno != 0) { diff --git a/src/symbols_cache.c b/src/symbols_cache.c index e82e83b87..d549218c2 100644 --- a/src/symbols_cache.c +++ b/src/symbols_cache.c @@ -267,7 +267,7 @@ register_symbol (struct symbols_cache **cache, const gchar *name, double weight, item = memory_pool_alloc0 (pcache->static_pool, sizeof (struct cache_item)); item->s = memory_pool_alloc0 (pcache->static_pool, sizeof (struct saved_cache_item)); - g_strlcpy (item->s->symbol, name, sizeof (item->s->symbol)); + rspamd_strlcpy (item->s->symbol, name, sizeof (item->s->symbol)); item->func = func; item->user_data = user_data; @@ -306,7 +306,7 @@ register_dynamic_symbol (memory_pool_t *dynamic_pool, struct symbols_cache **cac item = memory_pool_alloc0 (dynamic_pool, sizeof (struct cache_item)); item->s = memory_pool_alloc (dynamic_pool, sizeof (struct saved_cache_item)); - g_strlcpy (item->s->symbol, name, sizeof (item->s->symbol)); + rspamd_strlcpy (item->s->symbol, name, sizeof (item->s->symbol)); item->func = func; item->user_data = user_data; /* Handle weight using default metric */ diff --git a/src/util.c b/src/util.c index eb1b77e0c..78be8cbaf 100644 --- a/src/util.c +++ b/src/util.c @@ -224,7 +224,7 @@ make_unix_socket (const gchar *path, struct sockaddr_un *addr, gboolean is_serve addr->sun_family = AF_UNIX; - g_strlcpy (addr->sun_path, path, sizeof (addr->sun_path)); + rspamd_strlcpy (addr->sun_path, path, sizeof (addr->sun_path)); #ifdef FREEBSD addr->sun_len = SUN_LEN (addr); #endif @@ -1124,17 +1124,57 @@ rspamd_snprintf (gchar *buf, size_t max, const gchar *fmt, ...) return p - buf; } +gchar * +rspamd_escape_string (gchar *dst, const gchar *src, gsize len) +{ + gchar *buf = dst, *last = dst + len; + guint8 c; + const gchar *p = src; + + while (*p && buf < last) { + c = *p++; + if (G_UNLIKELY ((c & 0x80))) { + c &= 0x7F; + if (last - buf >= 3) { + *buf++ = 'M'; + *buf++ = '-'; + } + } + + if (G_UNLIKELY ( g_ascii_iscntrl (c))) { + if (c == '\n') { + *buf++ = ' '; + } + else if (c == '\t') { + *buf++ = '\t'; + } + else { + *buf++ = '^'; + if (buf != last) { + *buf++ = c ^ 0100; + } + } + } + else { + *buf++ = c; + } + } + + *buf = '\0'; + + return buf; +} gchar * rspamd_vsnprintf (gchar *buf, size_t max, const gchar *fmt, va_list args) { - gchar *p, zero, *last; - gint d; + gchar *p, zero, *last; + gint d; long double f, scale; size_t len, slen; - gint64 i64; - guint64 ui64; - guint width, sign, hex, max_width, frac_width, i; + gint64 i64; + guint64 ui64; + guint width, sign, hex, max_width, frac_width, i; f_str_t *v; if (max == 0) { @@ -1253,6 +1293,25 @@ rspamd_vsnprintf (gchar *buf, size_t max, const gchar *fmt, va_list args) continue; + case 'S': + p = va_arg(args, gchar *); + if (p == NULL) { + p = "(NULL)"; + } + + if (slen == (size_t) -1) { + buf = rspamd_escape_string (buf, p, last - buf); + + } else { + len = (buf + slen < last) ? slen : (size_t) (last - buf); + + buf = rspamd_escape_string (buf, p, len); + } + + fmt++; + + continue; + case 'O': i64 = (gint64) va_arg (args, off_t); sign = 1; @@ -1559,6 +1618,29 @@ g_ptr_array_unref (GPtrArray *array) } #endif +gsize +rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz) +{ + gchar *d = dst; + const gchar *s = src; + gsize n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') { + break; + } + } + } + + if (n == 0 && siz != 0) { + *d = '\0'; + } + + return (s - src - 1); /* count does not include NUL */ +} + /* * vi:ts=4 */ diff --git a/src/util.h b/src/util.h index f5ce840be..36d650877 100644 --- a/src/util.h +++ b/src/util.h @@ -108,6 +108,7 @@ void g_ptr_array_unref (GPtrArray *array); * %p void * * %V f_str_t * * %s null-terminated string + * %S ascii null-terminated string * %*s length and string * %Z '\0' * %N '\n' @@ -120,4 +121,26 @@ gint rspamd_fprintf (FILE *f, const gchar *fmt, ...); gint rspamd_snprintf (gchar *buf, size_t max, const gchar *fmt, ...); gchar *rspamd_vsnprintf (gchar *buf, size_t max, const gchar *fmt, va_list args); +/* + * Copy src to dest limited to len, in compare with standart strlcpy(3) rspamd strlcpy does not + * traverse the whole string and it is possible to use it for non NULL terminated strings. This is + * more like memccpy(dst, src, size, '\0') + * + * @param dst destination string + * @param src source string + * @param siz length of destination buffer + * @return bytes copied + */ +gsize rspamd_strlcpy (gchar *dst, const gchar *src, gsize siz); + +/* + * Escape rspamd string to write it to log file or other 7 bit prefferable places + * + * @param dst destination string + * @param src source string + * @param len length of destination buffer + * @return pointer to end of buffer + */ +gchar * rspamd_escape_string (gchar *dst, const gchar *src, gsize len); + #endif diff --git a/test/rspamd_memcached_test.c b/test/rspamd_memcached_test.c index 1a65d31c0..3ab62e7e7 100644 --- a/test/rspamd_memcached_test.c +++ b/test/rspamd_memcached_test.c @@ -74,7 +74,7 @@ rspamd_memcached_test_func () ctx->timeout.tv_usec = 0; ctx->sock = -1; ctx->options = MEMC_OPT_DEBUG; - g_strlcpy (param->key, buf, sizeof (param->key)); + rspamd_strlcpy (param->key, buf, sizeof (param->key)); param->buf = buf; param->bufsize = strlen (buf); ctx->param = param; -- 2.39.5