java-topology/defects/dbus-0001/patch/dbus-0001-policy-optimize-o-n2.patch

111 lines
4 KiB
Diff

# UNDF: UNDF-2026-000001225
# UNDF: UNDF-PENDING
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -780,38 +780,58 @@ remove_rules_by_type_up_to (BusClientPolicy *policy,
void
bus_client_policy_optimize (BusClientPolicy *policy)
{
- DBusList *link;
+ /* Replace O(R^2) backward-scan optimization with a single O(R) reverse pass.
+ *
+ * Original approach: for each blanket rule, call remove_rules_by_type_up_to()
+ * which walks from head to the current position — O(R) inner loop, O(R^2) total.
+ *
+ * Fixed approach: iterate from tail to head. The first (rightmost) blanket rule
+ * of each type supersedes all earlier rules of the same type. Track the last
+ * seen blanket per type and remove all preceding same-type rules in one pass.
+ */
+ DBusList *link;
+ dbus_bool_t seen_send_blanket = FALSE;
+ dbus_bool_t seen_receive_blanket = FALSE;
+ dbus_bool_t seen_own_blanket = FALSE;
_dbus_verbose ("Optimizing policy with %d rules\n",
_dbus_list_get_length (&policy->rules));
-
- link = _dbus_list_get_first_link (&policy->rules);
+
+ /* Walk from tail to head. Remove any rule that is shadowed by a later
+ * blanket rule of the same type. */
+ link = _dbus_list_get_last_link (&policy->rules);
while (link != NULL)
{
BusPolicyRule *rule;
- DBusList *next;
- dbus_bool_t remove_preceding;
+ DBusList *prev;
+ dbus_bool_t is_blanket;
+ dbus_bool_t already_shadowed;
- next = _dbus_list_get_next_link (&policy->rules, link);
+ prev = _dbus_list_get_prev_link (&policy->rules, link);
rule = link->data;
-
- remove_preceding = FALSE;
- _dbus_assert (rule != NULL);
-
+ is_blanket = FALSE;
+ already_shadowed = FALSE;
+
switch (rule->type)
{
case BUS_POLICY_RULE_SEND:
- remove_preceding =
- rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID &&
+ is_blanket = (rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID &&
rule->d.send.path == NULL &&
rule->d.send.interface == NULL &&
rule->d.send.member == NULL &&
rule->d.send.error == NULL &&
- rule->d.send.destination == NULL;
+ rule->d.send.destination == NULL);
+ already_shadowed = seen_send_blanket && !is_blanket;
+ if (is_blanket) seen_send_blanket = TRUE;
break;
case BUS_POLICY_RULE_RECEIVE:
- remove_preceding =
- rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID &&
+ is_blanket = (rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID &&
rule->d.receive.path == NULL &&
rule->d.receive.interface == NULL &&
rule->d.receive.member == NULL &&
rule->d.receive.error == NULL &&
- rule->d.receive.origin == NULL;
+ rule->d.receive.origin == NULL);
+ already_shadowed = seen_receive_blanket && !is_blanket;
+ if (is_blanket) seen_receive_blanket = TRUE;
break;
case BUS_POLICY_RULE_OWN:
- remove_preceding =
- rule->d.own.service_name == NULL;
+ is_blanket = (rule->d.own.service_name == NULL);
+ already_shadowed = seen_own_blanket && !is_blanket;
+ if (is_blanket) seen_own_blanket = TRUE;
break;
- /* The other rule types don't appear in this list */
case BUS_POLICY_RULE_USER:
case BUS_POLICY_RULE_GROUP:
default:
_dbus_assert_not_reached ("invalid rule");
break;
}
- if (remove_preceding)
- remove_rules_by_type_up_to (policy, rule->type,
- link);
-
- link = next;
+ if (already_shadowed)
+ {
+ /* This specific rule can never fire — remove it in O(1). */
+ _dbus_list_remove_link (&policy->rules, link);
+ bus_policy_rule_unref (rule);
+ }
+
+ link = prev;
}
_dbus_verbose ("After optimization, policy has %d rules\n",