/* Allow us to reset store used for lookups and lookup caching */
-static void *search_reset_point = NULL;
+static rmark search_reset_point = NULL;
{
int old_pool = store_pool;
-DEBUG(D_lookup) debug_printf("search_tidyup called\n");
+DEBUG(D_lookup) debug_printf_indent("search_tidyup called\n");
/* Close individually each cached open file. */
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;
}
*/
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;
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("search_open: %s \"%s\"\n", lk->name,
- (filename == NULL)? US"NULL" : filename);
+DEBUG(D_lookup) debug_printf_indent("search_open: %s \"%s\"\n", lk->name,
+ filename ? filename : US"NULL");
/* See if we already have this open for this type of search, and if so,
pass back the tree block as the handle. The key for the tree node is the search
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(" cached open\n");
+ DEBUG(D_lookup) debug_printf_indent(" cached open\n");
store_pool = old_pool;
return t;
}
- DEBUG(D_lookup) debug_printf(" cached closed\n");
+ DEBUG(D_lookup) debug_printf_indent(" cached closed\n");
}
/* Otherwise, we need to open the file or database - each search type has its
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
{
search_cache *c = (search_cache *)(open_bot->data.ptr);
- DEBUG(D_lookup) debug_printf("Too many lookup files open\n closing %s\n",
+ 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;
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;
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);
*/
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);
search_error_message = US"";
f.search_find_defer = FALSE;
-DEBUG(D_lookup) debug_printf("internal_search_find: file=\"%s\"\n "
+DEBUG(D_lookup) debug_printf_indent("internal_search_find: file=\"%s\"\n "
"type=%s key=\"%s\"\n", filename,
lookup_list[search_type]->name, 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;
- DEBUG(D_lookup) debug_printf("cached data used for lookup of %s%s%s\n",
+ 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"");
}
DEBUG(D_lookup)
{
- if (t) debug_printf("cached data found but past valid time; ");
- debug_printf("%s lookup required for %s%s%s\n",
+ if (t) debug_printf_indent("cached data found but past valid time; ");
+ debug_printf_indent("%s lookup required for %s%s%s\n",
filename ? US"file" : US"database",
keystring,
filename ? US"\n in " : US"", filename ? filename : US"");
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;
else
{
- DEBUG(D_lookup) debug_printf("lookup forced cache cleanup\n");
+ DEBUG(D_lookup) debug_printf_indent("lookup forced cache cleanup\n");
c->item_cache = NULL;
}
}
DEBUG(D_lookup)
{
if (data)
- debug_printf("lookup yielded: %s\n", data);
+ debug_printf_indent("lookup yielded: %s\n", data);
else if (f.search_find_defer)
- debug_printf("lookup deferred: %s\n", search_error_message);
- else debug_printf("lookup failed\n");
+ debug_printf_indent("lookup deferred: %s\n", search_error_message);
+ else debug_printf_indent("lookup failed\n");
}
/* Return it in new dynamic store in the regular pool */
*/
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;
DEBUG(D_lookup)
{
if (partial < 0) affixlen = 99; /* So that "NULL" prints */
- debug_printf("search_find: file=\"%s\"\n key=\"%s\" "
+ debug_printf_indent("search_find: file=\"%s\"\n key=\"%s\" "
"partial=%d affix=%.*s starflags=%x\n",
(filename == NULL)? US"NULL" : filename,
keystring, partial, affixlen, affix, starflags);
/* 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;
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;
}
DEBUG(D_lookup)
{
- tree_node *t = open_top;
- debug_printf("LRU list:\n");
- while (t != NULL)
+ debug_printf_indent("LRU list:\n");
+ for (tree_node *t = open_top; t; )
{
search_cache *c = (search_cache *)(t->data.ptr);
- debug_printf(" %s\n", t->name);
- if (t == open_bot) debug_printf(" End\n");
+ debug_printf_indent(" %s\n", t->name);
+ if (t == open_bot) debug_printf_indent(" End\n");
t = c->down;
}
}
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,
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("trying partial match %s\n", keystring2);
+ DEBUG(D_lookup) debug_printf_indent("trying partial match %s\n", keystring2);
yield = internal_search_find(handle, filename, keystring2);
if (f.search_find_defer) return NULL;
}
if (affixlen > 0) Ustrncpy(keystring3, affix, affixlen);
}
- DEBUG(D_lookup) debug_printf("trying partial match %s\n", keystring3);
+ 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;
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)
savechar = *(--atat);
*atat = '*';
- DEBUG(D_lookup) debug_printf("trying default match %s\n", atat);
+ DEBUG(D_lookup) debug_printf_indent("trying default match %s\n", atat);
yield = internal_search_find(handle, filename, atat);
*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;
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("trying to match *\n");
+ 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;
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;