parse_rules() has been calling toast_rules() in case of a parse error in
order to deallocate the 'struct rule' objects it has constructed up to
that point.
toast_rules() would take a pointer to a full 'struct rules' object, and
besides freeing all 'struct rule' referenced by it, would also free the
holding 'struct rules' itself.
With the introduction of the "executable paths" feature, and the
embedding of 'struct rules' into 'struct conf', meaning that the
lifecycle for 'struct rules' was no longer independent, toast_rules()
was changed not to free the passed 'struct rules' (as it was a field of
a 'struct conf' object). Unfortunately, this change was not completed
with a reinitialization of the rules list head, so the 'struct conf'
object would continue to reference just-freed rules, which then would be
freed a second time on destruction of that container.
So, make toast_rules() re-initialize the rules list in 'struct rules',
which it logically has been having to do since not freeing the enclosing
'struct rules'. This alone is enough to fix the bug, but let's use the
occasion to change the contract of parse_rules() and bring its herald
comment up-to-date: On error, parse_rules() now simply leaves already
constructed 'struct rule' objects in 'conf'. The latter is eventually
destroyed and the rule objects reclaimed at that point.
Reported by: impost0r(ret2plt) <impostor@ret2p.lt>
Fixes: 9818224174c4 ("MAC/do: Executable paths feature (GSoC 2025's final state)")
Sponsored by: The FreeBSD Foundation