{
PAIR_VERIFY(to_add);
+#ifdef WITH_VERIFY_PTR
+ fr_assert(!fr_pair_order_list_in_a_list(to_add));
+ list->verified = false;
+#endif
+
if (fr_pair_order_list_in_a_list(to_add)) {
fr_strerror_printf(IN_A_LIST_MSG, to_add);
return -1;
{
PAIR_VERIFY(to_add);
+#ifdef WITH_VERIFY_PTR
+ fr_assert(!fr_pair_order_list_in_a_list(to_add));
+ list->verified = false;
+#endif
+
if (fr_pair_order_list_in_a_list(to_add)) {
fr_strerror_printf(IN_A_LIST_MSG, to_add);
return -1;
{
PAIR_VERIFY(to_add);
+#ifdef WITH_VERIFY_PTR
+ fr_assert(!fr_pair_order_list_in_a_list(to_add));
+ list->verified = false;
+#endif
+
if (fr_pair_order_list_in_a_list(to_add)) {
fr_strerror_printf(IN_A_LIST_MSG, to_add);
return -1;
{
PAIR_VERIFY(to_add);
+#ifdef WITH_VERIFY_PTR
+ fr_assert(!fr_pair_order_list_in_a_list(to_add));
+ fr_assert(!pos || fr_pair_order_list_in_a_list(pos));
+ list->verified = false;
+#endif
+
if (fr_pair_order_list_in_a_list(to_add)) {
fr_strerror_printf(IN_A_LIST_MSG, to_add);
return -1;
PAIR_VERIFY_WITH_LIST(list, to_replace);
PAIR_VERIFY(vp);
+#ifdef WITH_VERIFY_PTR
+ fr_assert(!fr_pair_order_list_in_a_list(vp));
+ fr_assert(fr_pair_order_list_in_a_list(to_replace));
+ list->verified = false;
+#endif
+
fr_pair_insert_after(list, to_replace, vp);
fr_pair_remove(list, to_replace);
talloc_free(to_replace);
case FR_TYPE_STRUCTURAL:
{
+ if (vp->vp_group.verified) break;
+
fr_pair_list_foreach(&vp->vp_group, child) {
TALLOC_CTX *parent = talloc_parent(child);
// fr_assert(fr_dict_attr_can_contain(vp->da, child->da));
fr_pair_verify(file, line, &vp->vp_group, child);
}
+
+ UNCONST(fr_pair_t *, vp)->vp_group.verified = true;
}
break;
if (fr_pair_list_empty(list)) return; /* Fast path */
+ /*
+ * Only verify the list if it has been modified.
+ */
+ if (list->verified) return;
+
for (slow = fr_pair_list_head(list), fast = fr_pair_list_head(list);
slow && fast;
slow = fr_pair_list_next(list, slow), fast = fr_pair_list_next(list, fast)) {
parent = talloc_parent(slow);
if (expected && (parent != expected)) goto bad_parent;
}
+
+ UNCONST(fr_pair_list_t *, list)->verified = true;
}
#endif
FR_TLIST_HEAD(fr_pair_order_list) order; //!< Maintains the relative order of pairs in a list.
bool _CONST is_child; //!< is a child of a VP
+
+#ifdef WITH_VERIFY_PTR
+ unsigned int verified : 1; //!< hack to avoid O(N^3) issues
+#endif
} fr_pair_list_t;
/** Stores an attribute, a value and various bits of other data
*/
_INLINE fr_pair_t *fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
{
+#ifdef WITH_VERIFY_PTR
+ fr_assert(fr_pair_order_list_in_a_list(vp));
+ list->verified = false;
+#endif
+
return fr_pair_order_list_remove(&list->order, vp);
}
--- /dev/null
+# -*- text -*-
+# Copyright (C) 2023 Network RADIUS SARL (legal@networkradius.com)
+# This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0
+#
+# Version $Id$
+#
+# Tests for deeply nested pairs.
+#
+# The PAIR_VERIFY macros were recursive, perhaps exponential. So the tests here would take gradually more
+# and more time, to more than 30+s. That's bad.
+#
+
+proto dhcpv6
+proto-dictionary dhcpv6
+fuzzer-out dhcpv6
+
+decode-pair 00 5e 00 04 6a 2b 00 00
+match S46-MAP-Cont-E = { Options = { raw.27179 = 0x } }
+
+decode-pair ff 0f 00 01 fa
+match raw.65295 = 0xfa
+
+decode-pair 00 00 00 02 00 04
+match raw.0 = 0x0004
+
+decode-pair 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } }, raw.16410 = 0x
+
+decode-pair 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } }, raw.16410 = 0x
+
+decode-pair 00 5e 00 14 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } } } }, raw.16410 = 0x
+
+decode-pair 00 5e 00 18 00 5e 00 14 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } } } } } }, raw.16410 = 0x
+
+decode-pair 00 5e 00 1c 00 5e 00 18 00 5e 00 14 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } } } } } } } }, raw.16410 = 0x
+
+decode-pair 00 5e 00 20 00 5e 00 1c 00 5e 00 18 00 5e 00 14 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } } } } } } } } } }, raw.16410 = 0x
+
+decode-pair 00 5e 00 24 00 5e 00 20 00 5e 00 1c 00 5e 00 18 00 5e 00 14 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } } } } } } } } } } } }, raw.16410 = 0x
+
+decode-pair 00 5e 00 28 00 5e 00 24 00 5e 00 20 00 5e 00 1c 00 5e 00 18 00 5e 00 14 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } } } } } } } } } } } } } }, raw.16410 = 0x
+
+# 00 5e 00 30
+# 00 5e 00 2c
+# 00 5e 00 24
+# 00 5e 00 20
+# 00 5e 00 1c
+# 00 5e 00 18
+# 00 5f 00 14
+# 00 5e 00 10
+# 00 5f 00 0c
+# 00 5e 00 08
+# 00 5e 00 04
+# 6a 2b 00 00 40 1a 00 00
+
+decode-pair 00 5e 00 30 00 5e 00 2c 00 5e 00 24 00 5e 00 20 00 5e 00 1c 00 5e 00 18 00 5f 00 14 00 5e 00 10 00 5f 00 0c 00 5e 00 08 00 5e 00 04 6a 2b 00 00 40 1a 00 00
+match S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-T = { Options = { S46-MAP-Cont-E = { Options = { S46-MAP-Cont-E = { Options = { raw.27179 = 0x } } } } } } } } } } } } } } } } } }, raw.16410 = 0x } } } }
+
+count
+match 27