I missed some parts when finishing this. I should've tested it better.
GC would hit assertions or NULL dereferences when removing entries,
and eventually that would lead to cache overflowing (and getting
cleared).
Bugfixes
--------
- dnstap module: don't break request resolution on dnstap errors (!1147)
+- cache garbage collector: fix crashes introduced in 5.3.0 (!1153)
Knot Resolver 5.3.0 (2021-02-25)
} else {
/* find the first double zero in the key */
for (i = 2; kd[i - 1] || kd[i - 2]; ++i) {
- if (i >= key.len)
+ if (i >= key.len) {
+ // TODO: assert(!EINVAL) -> kr_assume()
return NULL;
+ }
}
}
// the next character can be used for classification
return &NSEC1;
case '3':
return &NSEC3;
- case 'S': // we don't GC the rtt_state entries, at least for now
+ case 'S': // the rtt_state entries are considered inconsistent, at least for now
+ return NULL;
default:
+ assert(!EINVAL);
return NULL;
}
}
int kr_gc_cache_iter(knot_db_t * knot_db, const kr_cache_gc_cfg_t *cfg,
kr_gc_iter_callback callback, void *ctx);
+/** Return RR type corresponding to the key or NULL.
+ *
+ * NULL is returned on unexpected values (those also trigger assertion)
+ * and on other kinds of data in cache (e.g. struct rtt_state).
+ */
const uint16_t *kr_gc_key_consistent(knot_db_val_t key);
/** Printf a *binary* string in a human-readable way. */
case KNOT_EOK:
deleted_records++;
const uint16_t *entry_type = kr_gc_key_consistent(**i);
- assert(entry_type != NULL);
- rrtypelist_add(&deleted_rrtypes, *entry_type);
+ if (entry_type != NULL) // some "inconsistent" entries are OK
+ rrtypelist_add(&deleted_rrtypes, *entry_type);
break;
case KNOT_ENOENT:
already_gone++;