]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
ldb:attrib_handlers: make ldb_comparison_Boolean more consistent
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Tue, 9 Apr 2024 22:54:41 +0000 (10:54 +1200)
committerJule Anger <janger@samba.org>
Mon, 10 Jun 2024 13:25:17 +0000 (13:25 +0000)
This isn't supposed to be used for sorting, but it is hard to say it
won't be, so we might as well make it sort properly.

Following long-standing behaviour, we try to sort "FALSE" > "TRUE", by
length, then switch to using strncasecmp().

strncasecmp would sort the other way, so we swap the operands. This is
to make e.g. "TRUE\0" sort the same as "TRUE".

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit a75c98ad688415aec8afc617a759ba90cfd9f23b)

lib/ldb/common/attrib_handlers.c

index baccf193f88b2ab73be206ce06de6aa4235d31a0..c01477331f00cc9e54dcc98493d70f68346b9753 100644 (file)
@@ -281,15 +281,36 @@ static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx,
 }
 
 /*
-  compare two Booleans
-*/
+ * compare two Booleans.
+ *
+ * According to RFC4517 4.2.2, "the booleanMatch rule is an equality matching
+ * rule", meaning it isn't used for ordering.
+ *
+ * However, it seems conceivable that Samba could be coerced into sorting on a
+ * field with Boolean syntax, so we might as well have consistent behaviour in
+ * that case.
+ *
+ * The most probably values are {"FALSE", 5} and {"TRUE", 4}. To save time we
+ * compare first by length, which makes FALSE > TRUE. This is somewhat
+ * contrary to convention, but is how Samba has worked forever.
+ *
+ * If somehow we are comparing incompletely normalised values where the length
+ * is the same (for example {"false", 5} and {"TRUE\0", 5}), the length is the
+ * same, and we fall back to a strncasecmp. In this case, since "FALSE" is
+ * alphabetically lower, we swap the order, so that "TRUE\0" again comes
+ * before "FALSE".
+ *
+ * ldb_canonicalise_Boolean (just above) gives us a clue as to what we might
+ * expect to cope with by way of invalid values.
+ */
 static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx,
                           const struct ldb_val *v1, const struct ldb_val *v2)
 {
        if (v1->length != v2->length) {
-               return NUMERIC_CMP(v1->length, v2->length);
+               return NUMERIC_CMP(v2->length, v1->length);
        }
-       return strncasecmp((char *)v1->data, (char *)v2->data, v1->length);
+       /* reversed, see long comment above */
+       return strncasecmp((char *)v2->data, (char *)v1->data, v1->length);
 }