flt_precheck_instances() finalized every instance of a proxy,
calling the parser of its filter class to produce the filter
configuration. But in legacy mode, the instances mirrored from the
implicit declarations are only metadata: the filters and the
implicit/explicit reconciliation are fully handled by the legacy
filter_configs list, checked and completed by flt_check().
Running the class parsers on these instances would be wrong: they may
modify the proxy options (e.g. the decompression parsers update the
direction flags of the proxy) or allocate filter configurations that
are never used by the legacy evaluation path. And the filter-enable and
filter-sequence directives are rejected in legacy mode, so nothing else
consumes the instances during the post-parsing stage.
Now flt_precheck_instances() returns early for a proxy using the
legacy "filter" directive. Its instances keep no filter configuration:
they are only flattened as metadata, for inspection through the CLI, and
released with the proxy. The legacy filters, including the implicit
decompression and compression filters, remain checked and initialized
as before.
struct filter_class_ref *ref;
int err_code = ERR_NONE;
+ /* Mirrored implicit instances in legacy mode are only metadata. Their
+ * parsers must not modify the proxy options or allocate unused configs.
+ */
+ if (flt_use_legacy_filter(proxy))
+ return ERR_NONE;
+
/* Finalize every instance once, following the global class order. */
list_for_each_entry(ref, &proxy->conf.filter_refs, list)
err_code |= flt_precheck_class_instances(proxy, ref);