From 48b090cb5cae11cb4c3dfb2bac69a9c7fb1af12c Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Wed, 26 Sep 2018 12:53:59 +0100 Subject: [PATCH] Fix b6f926fbefcd2471699599e44f32b8d25b87b471 to not SEGV on startup (rarely). Many thanks to Kristian Evensen for finding and diagnosing this. We can't copy the whole of a crec structure in make_non_terminals, since crec structures allocated to represent /etc/hosts entries are allocated with just enough space for the actual name they contain, not the full SMALLDNAME bytes declared in struct crec. Using structure copy therefore copies beyond the end of the allocated source and, just occaisionally, into unmapped memory, resulting in a SEGV. Since the crecs we're making here always have F_NAMEP set, we're not interested in copying the name field from the source anyway, we use the namep part of the union and set it to point some way into the name of the source crec to get the super-domain that we're representing. The fix is therefore to copy the relevant fields of the crec, rather than copying the whole and overwriting. --- src/cache.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cache.c b/src/cache.c index 5a38c21..68cdc85 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1436,9 +1436,8 @@ static void make_non_terminals(struct crec *source) if (crecp) { - *crecp = *source; - crecp->flags &= ~(F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_REVERSE); - crecp->flags |= F_NAMEP; + crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_REVERSE); + crecp->ttd = source->ttd; crecp->name.namep = name; cache_hash(crecp);