Mercurial > dovecot > core-2.2
changeset 18562:cfa35069876b
lib-fts: Changed filter's internal APIs to return error_r directly.
It's not very safe to store strings allocated from data stack to any
permanent structs.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 09 May 2015 11:46:09 +0300 |
parents | 7de648f42bc0 |
children | e1d2702eea84 |
files | src/lib-fts/fts-filter-normalizer-icu.c src/lib-fts/fts-filter-normalizer-simple.c src/lib-fts/fts-filter-private.h src/lib-fts/fts-filter-stemmer-snowball.c src/lib-fts/fts-filter-stopwords.c src/lib-fts/fts-filter.c src/lib-fts/fts-filter.h |
diffstat | 7 files changed, 53 insertions(+), 79 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-fts/fts-filter-normalizer-icu.c Sat May 09 11:33:45 2015 +0300 +++ b/src/lib-fts/fts-filter-normalizer-icu.c Sat May 09 11:46:09 2015 +0300 @@ -1,6 +1,7 @@ /* Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "str.h" #include "unichar.h" /* unicode replacement char */ #include "fts-filter.h" #include "fts-filter-private.h" @@ -21,32 +22,6 @@ UTransliterator *transliterator; }; -static void -icu_error(const char **error_r, const UErrorCode err, const char *func) -{ - if (error_r == NULL) - return; - - if (U_FAILURE(err)) { - *error_r = t_strdup_printf("Lib ICU function %s failed: %s\n", - func, u_errorName(err)); - } -} - -/* Thin wrapper for vprintf */ -static void ATTR_FORMAT(2, 3) -fts_filter_normalizer_icu_error(const char **error_r, const char *format, ...) -{ - va_list args; - - if (error_r == NULL) - return; - - va_start(args, format); - *error_r = t_strdup_vprintf(format, args); - va_end(args); -} - /* Helper to create UTF16, which libicu wants as input. On input, if *dst_uchars_r > 0, it indicates the number of UChar @@ -154,7 +129,6 @@ if (np->transliterator != NULL) utrans_close(np->transliterator); pool_unref(&np->pool); - return; } static int @@ -183,13 +157,14 @@ sizeof(struct fts_filter_normalizer)); np = p_new(pp, struct fts_filter_normalizer, 1); np->pool = pp; - np->filter = *fts_filter_normalizer_icu; + np->filter = *fts_filter_normalizer_icu; np->transliterator_id = p_strdup(pp, id); *filter_r = &np->filter; return 0; } -static int fts_filter_normalizer_icu_create_trans(struct fts_filter_normalizer *np) +static int fts_filter_normalizer_icu_create_trans(struct fts_filter_normalizer *np, + const char **error_r) { UErrorCode err = U_ZERO_ERROR; UParseError perr; @@ -203,33 +178,36 @@ np->transliterator = utrans_openU(id_uchar, u_strlen(id_uchar), UTRANS_FORWARD, NULL, 0, &perr, &err); if (U_FAILURE(err)) { + string_t *str = t_str_new(128); + + str_printfa(str, "Failed to open transliterator for id '%s': %s", + np->transliterator_id, u_errorName(err)); if (perr.line >= 1) { - fts_filter_normalizer_icu_error(&np->filter.error, "Failed to open transliterator for id: %s. Lib ICU error: %s. Parse error on line %u offset %u.", - np->transliterator_id, u_errorName(err), perr.line, perr.offset); + /* we have only one line in our ID */ + str_printfa(str, " (parse error on offset %u)", perr.offset); } - else { - fts_filter_normalizer_icu_error(&np->filter.error, "Failed to open transliterator for id: %s. Lib ICU error: %s.", - np->transliterator_id, u_errorName(err)); - } + *error_r = str_c(str); return -1; } return 0; } static int -fts_filter_normalizer_icu_filter(struct fts_filter *filter, const char **token) +fts_filter_normalizer_icu_filter(struct fts_filter *filter, const char **token, + const char **error_r) { + struct fts_filter_normalizer *np = + (struct fts_filter_normalizer *)filter; UErrorCode err = U_ZERO_ERROR; UChar *utext = NULL; int32_t utext_cap = 0; int32_t utext_len = -1; int32_t utext_limit; - struct fts_filter_normalizer *np = - (struct fts_filter_normalizer *)filter; - if (np->transliterator == NULL) - if (fts_filter_normalizer_icu_create_trans(np) < 0) - goto err_exit; + if (np->transliterator == NULL) { + if (fts_filter_normalizer_icu_create_trans(np, error_r) < 0) + return -1; + } make_uchar(*token, &utext, &utext_cap); utext_limit = u_strlen(utext); @@ -238,7 +216,6 @@ /* Data did not fit into utext. */ if (utext_len > utext_cap || err == U_BUFFER_OVERFLOW_ERROR) { - /* This is a crude retry fix... Make a new utext of the size utrans_transUChars indicated */ utext_len++; /* room for '\0' bytes(2) */ @@ -254,16 +231,13 @@ } if (U_FAILURE(err)) { - icu_error(&np->filter.error, err, "utrans_transUChars()"); - goto err_exit; + *error_r = t_strdup_printf("utrans_transUChars() failed: %s\n", + u_errorName(err)); + return -1; } make_utf8(utext, token); return 1; - - err_exit: - *token = NULL; - return -1; } #else @@ -286,7 +260,8 @@ static int fts_filter_normalizer_icu_filter(struct fts_filter *filter ATTR_UNUSED, - const char *token ATTR_UNUSED) + const char **token ATTR_UNUSED, + const char **error_r ATTR_UNUSED) { return NULL; }
--- a/src/lib-fts/fts-filter-normalizer-simple.c Sat May 09 11:33:45 2015 +0300 +++ b/src/lib-fts/fts-filter-normalizer-simple.c Sat May 09 11:46:09 2015 +0300 @@ -50,17 +50,16 @@ static int fts_filter_normalizer_simple_filter(struct fts_filter *_filter, - const char **token) + const char **token, + const char **error_r ATTR_UNUSED) { struct fts_filter_normalizer_simple *filter = (struct fts_filter_normalizer_simple *)_filter; str_truncate(filter->str, 0); if (uni_utf8_to_decomposed_titlecase(*token, strlen(*token), - filter->str) < 0) { - *token = NULL; - return -1; - } + filter->str) < 0) + i_panic("fts-normalizer-simple: Token is not valid UTF-8: %s", *token); *token = str_c(filter->str); return 1; }
--- a/src/lib-fts/fts-filter-private.h Sat May 09 11:33:45 2015 +0300 +++ b/src/lib-fts/fts-filter-private.h Sat May 09 11:46:09 2015 +0300 @@ -17,7 +17,8 @@ const char *const *settings, struct fts_filter **filter_r, const char **error_r); - int (*filter)(struct fts_filter *filter, const char **token); + int (*filter)(struct fts_filter *filter, const char **token, + const char **error_r); void (*destroy)(struct fts_filter *filter); }; @@ -25,7 +26,6 @@ struct fts_filter { const char *class_name; /* name of the class this is based on */ const struct fts_filter_vfuncs *v; - const char *error; int refcount; struct fts_filter *parent; };
--- a/src/lib-fts/fts-filter-stemmer-snowball.c Sat May 09 11:33:45 2015 +0300 +++ b/src/lib-fts/fts-filter-stemmer-snowball.c Sat May 09 11:46:09 2015 +0300 @@ -65,12 +65,14 @@ } static int -fts_filter_stemmer_snowball_create_stemmer(struct fts_filter_stemmer_snowball *sp) +fts_filter_stemmer_snowball_create_stemmer(struct fts_filter_stemmer_snowball *sp, + const char **error_r) { sp->stemmer = sb_stemmer_new(sp->lang->name, NULL); if (sp->stemmer == NULL) { - sp->filter.error = t_strdup_printf("Creating a Snowball stemmer failed." \ - " lang: %s", sp->lang->name); + *error_r = t_strdup_printf( + "Creating a Snowball stemmer for language '%s' failed.", + sp->lang->name); fts_filter_stemmer_snowball_destroy(&sp->filter); return -1; } @@ -79,14 +81,14 @@ static int fts_filter_stemmer_snowball_filter(struct fts_filter *filter, - const char **token) + const char **token, const char **error_r) { struct fts_filter_stemmer_snowball *sp = (struct fts_filter_stemmer_snowball *) filter; const sb_symbol *base; if (sp->stemmer == NULL) { - if (fts_filter_stemmer_snowball_create_stemmer(sp) < 0) + if (fts_filter_stemmer_snowball_create_stemmer(sp, error_r) < 0) return -1; } @@ -125,7 +127,8 @@ static int fts_filter_stemmer_snowball_filter(struct fts_filter *filter ATTR_UNUSED, - const char **token ATTR_UNUSED) + const char **token ATTR_UNUSED, + const char **error_r ATTR_UNUSED) { return -1; }
--- a/src/lib-fts/fts-filter-stopwords.c Sat May 09 11:33:45 2015 +0300 +++ b/src/lib-fts/fts-filter-stopwords.c Sat May 09 11:46:09 2015 +0300 @@ -117,27 +117,30 @@ } static int -fts_filter_stopwords_create_stopwords(struct fts_filter_stopwords *sp) +fts_filter_stopwords_create_stopwords(struct fts_filter_stopwords *sp, + const char **error_r) { int ret; hash_table_create(&sp->stopwords, sp->pool, 0, str_hash, strcmp); ret = fts_filter_stopwords_read_list(sp); - if (ret < 0) - sp->filter.error = t_strdup_printf("Failed to read stopword list %s", - sp->stopwords_dir); + if (ret < 0) { + *error_r = t_strdup_printf("Failed to read stopword list %s", + sp->stopwords_dir); + } return ret; } static int -fts_filter_stopwords_filter(struct fts_filter *filter, const char **token) +fts_filter_stopwords_filter(struct fts_filter *filter, const char **token, + const char **error_r) { const char *stopword; struct fts_filter_stopwords *sp = (struct fts_filter_stopwords *) filter; if (!hash_table_is_created(sp->stopwords)) - if (fts_filter_stopwords_create_stopwords(sp) < 0) + if (fts_filter_stopwords_create_stopwords(sp, error_r) < 0) return -1; stopword = hash_table_lookup(sp->stopwords, *token); if (stopword != NULL) {
--- a/src/lib-fts/fts-filter.c Sat May 09 11:33:45 2015 +0300 +++ b/src/lib-fts/fts-filter.c Sat May 09 11:46:09 2015 +0300 @@ -99,21 +99,15 @@ { int ret = 0; - if (filter->error != NULL) { - *error_r = filter->error; - return -1; - } - /* Recurse to parent. */ if (filter->parent != NULL) ret = fts_filter_filter(filter->parent, token, error_r); /* Parent returned token or no parent. */ - if(ret > 0 || filter->parent == NULL) - ret = filter->v->filter(filter, token); + if (ret > 0 || filter->parent == NULL) + ret = filter->v->filter(filter, token, error_r); - if (filter->error != NULL) - *error_r = filter->error; - + if (ret <= 0) + *token = NULL; return ret; }
--- a/src/lib-fts/fts-filter.h Sat May 09 11:33:45 2015 +0300 +++ b/src/lib-fts/fts-filter.h Sat May 09 11:46:09 2015 +0300 @@ -59,7 +59,7 @@ void fts_filter_unref(struct fts_filter **filter); /* Returns 1 if token is returned in *token, 0 if token was filtered - out and -1 on error. + out (*token is also set to NULL) and -1 on error. Input is also given via *token. */ int