patterns: "del map/acl" removes only one of duplicate keys, "clear map/acl @<ver>" may do nothing (3.4 regression) · Issue #3523 · haproxy/haproxy · GitHub
Skip to content

patterns: "del map/acl" removes only one of duplicate keys, "clear map/acl @<ver>" may do nothing (3.4 regression) #3523

Open

Description

@ygkat

Detailed Description of the Problem

  1. del map <map> <key> (and del acl) removes only one entry when the key is duplicated; the others stay and still match.
  2. clear map @<ver> <map> (and clear acl @<ver>) does nothing while a lower version still has entries, the normal case after prepare map.

Both report success. Affected: master (bd884a2), 3.4.x (3.4.6 tested). Not affected: 3.3.16, 3.2.25.

Expected Behavior

All entries of the key (1) or of version <ver> (2) are deleted, as in 3.3 and 3.2.

Steps to Reproduce the Behavior

With the configuration below and dup.map holding k1 v1, k1 v2, k2 v3 (one per line), on master:

$ echo "del map dup.map k1; show map dup.map" | socat - /tmp/ha.sock
0x1f34350 k1 v2
0x1f343d0 k2 v3
$ echo "prepare map dup.map; add map @1 dup.map n1 w1" | socat - /tmp/ha.sock
New version created: 1
$ echo "clear map @1 dup.map; show map @1 dup.map" | socat - /tmp/ha.sock
0x7f1ef009d1c0 n1 w1

Same steps on 3.3.16 and 3.2.25: all k1 entries removed, @1 cleared.

Do you have any idea what may have caused this?

545cf59 ("MEDIUM: patterns: reorganize pattern reference elements"):

  1. pat_ref_gen_delete() now deletes only the element found by cebs_item_lookup(); it used to walk the duplicates with cebs_item_next_dup(). This affects all callers: CLI del map/acl, del-map/del-acl actions, Lua, acme.
  2. pat_ref_purge_range() walks the generations in ascending order and, when from <= to, stops at the first one outside the range even if it is below from. clear map @1 passes from = to = 1, so generation 0 stops the loop:
    if (gen->gen_id - from > to - from) {
        if (from <= to) {
            break;
        }
        continue;
    }

Do you have an idea how to solve the issue?

  1. In pat_ref_gen_delete(), walk the duplicates as pat_ref_set_from_elt() does, then publish the event once:
    while (elt) {
        elt2 = cebs_item_next_dup(&gen->elt_root, node, pattern, elt);
        pat_ref_delete_by_ptr(ref, elt);
        elt = elt2;
    }
  2. In pat_ref_purge_range(), break only above the range and continue below it: if (from <= to && gen->gen_id > to) break;.

With both on master, the steps above give the 3.3.16 output and the http-rules, converter, cli and lua reg-tests pass.

What is your configuration?

global
    stats socket /tmp/ha.sock mode 600 level admin
frontend fe
    mode http
    bind 127.0.0.1:18080
    timeout client 5s
    http-request set-var(txn.v) req.hdr(host),map(dup.map)

Output of haproxy -vv

HAProxy version 3.5-dev8 2026/10/01 - https://haproxy.org/
  OPTIONS = USE_OPENSSL= USE_PCRE2=1

Last Outputs and Backtraces

No crash; the commands report success.

Additional Information

Vanilla builds only.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions