X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/42c7f0b4ea09d8971a19beeef743ec8981d4aacc..d447dbd160a0fb503ed1e763f3f23d28744b6ddd:/src/src/search.c diff --git a/src/src/search.c b/src/src/search.c index ebdf8a165..d67bdc59e 100644 --- a/src/src/search.c +++ b/src/src/search.c @@ -41,7 +41,7 @@ static int open_filecount = 0; /* Allow us to reset store used for lookups and lookup caching */ -static void *search_reset_point = NULL; +static rmark search_reset_point = NULL; @@ -269,8 +269,7 @@ open_filecount = 0; for (int i = 0; i < lookup_list_count; i++) if (lookup_list[i]->tidy) (lookup_list[i]->tidy)(); -if (search_reset_point) store_reset(search_reset_point); -search_reset_point = NULL; +if (search_reset_point) search_reset_point = store_reset(search_reset_point); store_pool = old_pool; } @@ -326,8 +325,8 @@ Returns: an identifying handle for the open database; */ void * -search_open(uschar *filename, int search_type, int modemask, uid_t *owners, - gid_t *owngroups) +search_open(const uschar * filename, int search_type, int modemask, + uid_t * owners, gid_t * owngroups) { void *handle; tree_node *t; @@ -336,10 +335,17 @@ lookup_info *lk = lookup_list[search_type]; uschar keybuffer[256]; int old_pool = store_pool; +if (filename && is_tainted(filename)) + { + log_write(0, LOG_MAIN|LOG_PANIC, + "Tainted filename for search: '%s'", filename); + return NULL; + } + /* Change to the search store pool and remember our reset point */ store_pool = POOL_SEARCH; -if (search_reset_point == NULL) search_reset_point = store_get(0); +if (!search_reset_point) search_reset_point = store_mark(); DEBUG(D_lookup) debug_printf_indent("search_open: %s \"%s\"\n", lk->name, filename ? filename : US"NULL"); @@ -350,12 +356,11 @@ type plus '0' concatenated with the file name. There may be entries in the tree with closed files if a lot of files have been opened. */ sprintf(CS keybuffer, "%c%.254s", search_type + '0', - (filename == NULL)? US"" : filename); + filename ? filename : US""); -if ((t = tree_search(search_tree, keybuffer)) != NULL) +if ((t = tree_search(search_tree, keybuffer))) { - c = (search_cache *)(t->data.ptr); - if (c->handle != NULL) + if ((c = (search_cache *)t->data.ptr)->handle) { DEBUG(D_lookup) debug_printf_indent(" cached open\n"); store_pool = old_pool; @@ -371,8 +376,7 @@ we are holding open in the cache. If the limit is reached, close the least recently used one. */ if (lk->type == lookup_absfile && open_filecount >= lookup_open_max) - { - if (open_bot == NULL) + if (!open_bot) log_write(0, LOG_MAIN|LOG_PANIC, "too many lookups open, but can't find " "one to close"); else @@ -380,8 +384,7 @@ if (lk->type == lookup_absfile && open_filecount >= lookup_open_max) search_cache *c = (search_cache *)(open_bot->data.ptr); DEBUG(D_lookup) debug_printf_indent("Too many lookup files open\n closing %s\n", open_bot->name); - open_bot = c->up; - if (open_bot != NULL) + if ((open_bot = c->up)) ((search_cache *)(open_bot->data.ptr))->down = NULL; else open_top = NULL; @@ -389,21 +392,19 @@ if (lk->type == lookup_absfile && open_filecount >= lookup_open_max) c->handle = NULL; open_filecount--; } - } /* If opening is successful, call the file-checking function if there is one, and if all is still well, enter the open database into the tree. */ -handle = (lk->open)(filename, &search_error_message); -if (handle == NULL) +if (!(handle = (lk->open)(filename, &search_error_message))) { store_pool = old_pool; return NULL; } -if (lk->check != NULL && - !lk->check(handle, filename, modemask, owners, owngroups, - &search_error_message)) +if ( lk->check + && !lk->check(handle, filename, modemask, owners, owngroups, + &search_error_message)) { lk->close(handle); store_pool = old_pool; @@ -418,10 +419,10 @@ if (lk->type == lookup_absfile) open_filecount++; insert a new entry. On re-use, leave any cached lookup data and the lookup count alone. */ -if (t == NULL) +if (!t) { - t = store_get(sizeof(tree_node) + Ustrlen(keybuffer)); - t->data.ptr = c = store_get(sizeof(search_cache)); + t = store_get(sizeof(tree_node) + Ustrlen(keybuffer), FALSE); + t->data.ptr = c = store_get(sizeof(search_cache), FALSE); c->item_cache = NULL; Ustrcpy(t->name, keybuffer); tree_insertnode(&search_tree, t); @@ -461,7 +462,7 @@ Returns: a pointer to a dynamic string containing the answer, */ static uschar * -internal_search_find(void *handle, uschar *filename, uschar *keystring) +internal_search_find(void * handle, const uschar * filename, uschar * keystring) { tree_node * t = (tree_node *)handle; search_cache * c = (search_cache *)(t->data.ptr); @@ -495,7 +496,7 @@ if ( (t = tree_search(c->item_cache, keystring)) && (!(e = t->data.ptr)->expiry || e->expiry > time(NULL)) ) { /* Data was in the cache already; set the pointer from the tree node */ - data = e->ptr; + data = e->data.ptr; DEBUG(D_lookup) debug_printf_indent("cached data used for lookup of %s%s%s\n", keystring, filename ? US"\n in " : US"", filename ? filename : US""); @@ -535,13 +536,13 @@ else if (t) /* Previous, out-of-date cache entry. Update with the */ { /* new result and forget the old one */ e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; - e->ptr = data; + e->data.ptr = data; } else { - e = store_get(sizeof(expiring_data) + sizeof(tree_node) + len); + e = store_get(sizeof(expiring_data) + sizeof(tree_node) + len, is_tainted(keystring)); e->expiry = do_cache == UINT_MAX ? 0 : time(NULL)+do_cache; - e->ptr = data; + e->data.ptr = data; t = (tree_node *)(e+1); memcpy(t->name, keystring, len); t->data.ptr = e; @@ -604,8 +605,9 @@ Returns: a pointer to a dynamic string containing the answer, */ uschar * -search_find(void *handle, uschar *filename, uschar *keystring, int partial, - const uschar *affix, int affixlen, int starflags, int *expand_setup) +search_find(void * handle, const uschar * filename, uschar * keystring, + int partial, const uschar * affix, int affixlen, int starflags, + int * expand_setup) { tree_node *t = (tree_node *)handle; BOOL set_null_wild = FALSE; @@ -623,8 +625,8 @@ DEBUG(D_lookup) /* Arrange to put this database at the top of the LRU chain if it is a type that opens real files. */ -if (open_top != (tree_node *)handle && - lookup_list[t->name[0]-'0']->type == lookup_absfile) +if ( open_top != (tree_node *)handle + && lookup_list[t->name[0]-'0']->type == lookup_absfile) { search_cache *c = (search_cache *)(t->data.ptr); tree_node *up = c->up; @@ -634,20 +636,21 @@ if (open_top != (tree_node *)handle && Otherwise there will be a non-NULL up pointer, since we checked above that this block isn't already at the top of the list. */ - if (up != NULL) + if (up) { ((search_cache *)(up->data.ptr))->down = down; - if (down != NULL) + if (down) ((search_cache *)(down->data.ptr))->up = up; - else open_bot = up; + else + open_bot = up; } /* Now put it at the head of the list. */ c->up = NULL; c->down = open_top; - if (open_top == NULL) open_bot = t; else - ((search_cache *)(open_top->data.ptr))->up = t; + if (!open_top) open_bot = t; + else ((search_cache *)(open_top->data.ptr))->up = t; open_top = t; } @@ -668,7 +671,8 @@ entry but could have been partial, flag to set up variables. */ yield = internal_search_find(handle, filename, keystring); if (f.search_find_defer) return NULL; -if (yield != NULL) { if (partial >= 0) set_null_wild = TRUE; } + +if (yield) { if (partial >= 0) set_null_wild = TRUE; } /* Not matched a complete entry; handle partial lookups, but only if the full search didn't defer. Don't use string_sprintf() to construct the initial key, @@ -685,7 +689,8 @@ else if (partial >= 0) if (affixlen == 0) keystring2 = keystring; else { - keystring2 = store_get(len + affixlen + 1); + keystring2 = store_get(len + affixlen + 1, + is_tainted(keystring) || is_tainted(affix)); Ustrncpy(keystring2, affix, affixlen); Ustrcpy(keystring2 + affixlen, keystring); DEBUG(D_lookup) debug_printf_indent("trying partial match %s\n", keystring2); @@ -729,12 +734,12 @@ else if (partial >= 0) DEBUG(D_lookup) debug_printf_indent("trying partial match %s\n", keystring3); yield = internal_search_find(handle, filename, keystring3); if (f.search_find_defer) return NULL; - if (yield != NULL) + if (yield) { /* First variable is the wild part; second is the fixed part. Take care to get it right when keystring3 is just "*". */ - if (expand_setup != NULL && *expand_setup >= 0) + if (expand_setup && *expand_setup >= 0) { int fixedlength = Ustrlen(keystring3) - affixlen; int wildlength = Ustrlen(keystring) - fixedlength - 1; @@ -758,7 +763,7 @@ else if (partial >= 0) replacing everything to the left of @ by *. After a match, the wild part is set to the string to the left of the @. */ -if (yield == NULL && (starflags & SEARCH_STARAT) != 0) +if (!yield && starflags & SEARCH_STARAT) { uschar *atat = Ustrrchr(keystring, '@'); if (atat != NULL && atat > keystring) @@ -772,7 +777,7 @@ if (yield == NULL && (starflags & SEARCH_STARAT) != 0) *atat = savechar; if (f.search_find_defer) return NULL; - if (yield != NULL && expand_setup != NULL && *expand_setup >= 0) + if (yield && expand_setup && *expand_setup >= 0) { *expand_setup += 1; expand_nstring[*expand_setup] = keystring; @@ -788,11 +793,11 @@ if (yield == NULL && (starflags & SEARCH_STARAT) != 0) try that. If we do match, the first variable (the wild part) is the whole key, and the second is empty. */ -if (yield == NULL && (starflags & (SEARCH_STAR|SEARCH_STARAT)) != 0) +if (!yield && starflags & (SEARCH_STAR|SEARCH_STARAT)) { DEBUG(D_lookup) debug_printf_indent("trying to match *\n"); yield = internal_search_find(handle, filename, US"*"); - if (yield != NULL && expand_setup != NULL && *expand_setup >= 0) + if (yield && expand_setup && *expand_setup >= 0) { *expand_setup += 1; expand_nstring[*expand_setup] = keystring; @@ -810,7 +815,7 @@ chopping off any of the domain components, set up the expansion variables fixed part of the domain. The set_null_wild flag is set only when yield is not NULL. */ -if (set_null_wild && expand_setup != NULL && *expand_setup >= 0) +if (set_null_wild && expand_setup && *expand_setup >= 0) { *expand_setup += 1; expand_nstring[*expand_setup] = keystring;