The branch, master has been updated
       via  9844ac289be ldb-samba: ldif_read_objectSid avoids VLA
       via  bf4af1a28a3 ldb-samba: ldif_read_objectSid() short-circuits without 
'S'
       via  6c0bdf37187 lib/fuzzing: add fuzz_stable_sort_r_unstable
       via  59cbaa91348 ldb: note a transitivity problem in ldb_comparison_fold
       via  e2051eebd49 ldb:attrib_handlers: reduce non-transitive behaviour in 
ldb_comparison_fold
       via  f81b7c7eb20 ldb:attrib_handlers: use NUMERIC_CMP in 
ldb_comparison_fold
       via  3e899ef5bfa ldb-samba: remove unused 
ldif_comparision_objectSid_isString()
       via  8c702735641 ldb-samba: simplify extended_dn_read_SID()
       via  c6c7cb8d4ba ldb-samba: simplify ldif_canonicalise_objectSid()
       via  be5fd9a3a1b ldb-samba: simplify ldif_comparison_objectSid()
       via  d801ed8b111 pytest: sid_strings: Samba DN object refuses sub-auth 
overflow
       via  edf9b282ba6 pytest: sid_strings: adjust to match Windows 2016
       via  473502d1701 pytest: sid_strings: Windows does allow lowercase 
s-1-... SIDs
       via  fb724c61107 pytest: sid_strings: use more reliable well known SID
       via  ae4f095586e ldb-samba: ldif_write_schemaInfo() uses correct size
       via  13af2cb0217 lib:util: codepoint_cmpi: be transitive and 
case-insensitive
       via  310d59c7cc3 lib:util:tests: more tests for codepoint_cmpi
       via  827b0c39ed0 s4:dsdb:mod: repl_md: message sort uses NUMERIC_CMP()
       via  c5c29f59fa6 s4:rpc_srv:getncchanges: USN sort uses qsort() instead 
of ldb_qsort()
       via  65df8ce05c1 s4:rpc_srv:getncchanges: 4.5 anc emulation uses 
qsort(), not ldb_qsort()
       via  5335f122fb5 s4:dsdb:mod: repl_md: make message_sort transitive
       via  7f995ab887a ldb:tools: ldbsearch doesn't need ldb_qsort()
       via  b37186cf917 s4:dsdb:util_trusts: simplify the NULL case in dns_cmp
       via  91b802941c1 s4:dsdb:util_trusts: describe dns_cmp return values
       via  8f080c0295d ldb:tests: add a test for dotted i uppercase
       via  af7654331fb ldb: avoid NULL deref in ldb_db_compare
      from  d58a72c572f .gitlab-ci: Remove tags no longer provided by gitlab.com

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 9844ac289be3430fd3f72c5e57fa00e012c5d417
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Sat May 4 13:40:35 2024 +1200

    ldb-samba: ldif_read_objectSid avoids VLA
    
    I don't think this variable length array is any trouble, but people
    complain about them (e.g. https://nullprogram.com/blog/2019/10/27/)
    because they make things more complex at run-time, and this is a
    somewhat performance sensitive path.
    
    DOM_SID_STR_BUFLEN + 1 is 191 -- if that stack allocation is going to
    cause trouble, then so was the VLA <= that.
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abart...@samba.org>
    Autobuild-Date(master): Wed May  8 00:26:42 UTC 2024 on atb-devel-224

commit bf4af1a28a3580223fcc3a861c7fdd1b43f234d1
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Sat May 4 13:32:39 2024 +1200

    ldb-samba: ldif_read_objectSid() short-circuits without 'S'
    
    This avoids a memcpy, and level 3 debug verbosity from
    dom_sid_parse_endp().
    
    In other places we have something like `|| in->data[1] != '-'`, but
    that is not useful here -- the value is either a string SID, or a
    binary SID that starts with '\1', or some awful value that we *do*
    want to get messages about.
    
    This replaces the work of ldif_comparision_objectSid_isString().
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 6c0bdf371878eb1a3a1c3b1663379a89bd0ec2c0
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Wed May 1 17:16:38 2024 +1200

    lib/fuzzing: add fuzz_stable_sort_r_unstable
    
    This should find out how well stable_sort copes with an unstable
    non-transitive comparison function.
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 59cbaa91348857c51854ee5e6bc8f78cdcde4e56
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Tue Apr 30 12:41:25 2024 +1200

    ldb: note a transitivity problem in ldb_comparison_fold
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit e2051eebd492a419f840280336eb242d0b4a26ac
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 26 15:58:44 2024 +1200

    ldb:attrib_handlers: reduce non-transitive behaviour in ldb_comparison_fold
    
    If two strings are invalid UTF-8, the string is first compared with
    memcmp(), which compares as unsigned char.
    
    If the strings are of different lengths and one is a substring of the
    other, the memcmp() returns 0 and a second comparison is made which
    assumes the next character in the shorter string is '\0' -- but this
    comparison was done using SIGNED chars (on most systems). That leads
    to non-transitive comparisons.
    
    Consider the strings {"a\xff", "a", "ab\xff"} under that system.
    
       "a\xff"  < "a",      because (char)0xff == -1.
    
       "ab\xff" > "a",     because  'b' == 98.
    
       "ab\xff" < "a\xff", because memcmp("ab\xff", "a\xff", 2) avoiding the
                           signed char tiebreaker.
    
    (Before c49c48afe09a1a78989628bbffd49dd3efc154dd, the final character
    might br arbitrarily cast into another character -- in latin-1, for
    example, the 0xff here would have been seen as 'ÿ', which would be
    uppercased to 'Ÿ', which is U+0178, which would be truncated to
    '\x78', a positive char.
    
    On the other hand e.g. 0xfe, 'þ', would have mapped to 0xde, 'Þ',
    remaining negative).
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit f81b7c7eb206a447d799a25cc2da26304dc7567a
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Thu Apr 11 13:21:25 2024 +1200

    ldb:attrib_handlers: use NUMERIC_CMP in ldb_comparison_fold
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 3e899ef5bfa67a12e8eb18cbebc06367f37a8376
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Thu Apr 18 01:49:11 2024 +1200

    ldb-samba: remove unused ldif_comparision_objectSid_isString()
    
    This is unused because it does things badly, by just guessing and
    not allowing valid sids that start with "s-". All the places that used
    to use it were calling ldif_read_objectSid() or similar which correctly
    check for string SIDs by actually trying to parse them. That begins
    with looking for the "S-"/"s-", so this shortcut is not saving any real
    work.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 8c702735641aaad58c317843c547249c6bd1c716
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Thu Apr 18 01:44:03 2024 +1200

    ldb-samba: simplify extended_dn_read_SID()
    
    This will allow the reading of SIDs that start with "s-", which
    Windows allows, and we allow elsewhere.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit c6c7cb8d4ba0e115034f4f0f7ff4a9943e54d914
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Thu Apr 18 01:42:27 2024 +1200

    ldb-samba: simplify ldif_canonicalise_objectSid()
    
    ldif_comparision_objectSid_isString() is doing not useful or accurate,
    and ldif_read_objectSid() checks properly.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit be5fd9a3a1b91dbd41e2bd0b025e3d3ffb598463
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Thu Apr 18 00:38:17 2024 +1200

    ldb-samba: simplify ldif_comparison_objectSid()
    
    The ldif_comparision_objectSid_isString() call is both wrong
    (disallowing "s-") and redundant, because ldif_read_objectSid() calls
    dom_sid_parse(), which does the check properly.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit d801ed8b11125527b0b8193c8d0e430b5fb2c3a7
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri May 3 11:29:31 2024 +1200

    pytest: sid_strings: Samba DN object refuses sub-auth overflow
    
    We were mistakenly asserting something that did not happen with
    Windows, because Samba already won't parse the DN string.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit edf9b282ba6e3fc089ab2d8a4db122b300b95fe4
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri May 3 11:24:02 2024 +1200

    pytest: sid_strings: adjust to match Windows 2016
    
    9 hex-digit subauths like '0xABCDef123' will not fit in 32 bits, so
    should be rejected on parsing.
    
    In other situations, such as defaultSecurityDescriptor, overflowing
    SID subauths on Windows will saturate to 0xffffffff, resulting in a
    valid but probably meaningless SID. It is possible that in previous
    testing we saw that here, but it is more likely I got confused. In any
    case, now I see them being rejected, and that is good.
    
    The saturating defaultSecurityDescriptor case is tested in
    SidStringBehavioursThatWindowsAllows.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 473502d170190b6bfe8da29708d347b16e0a2f7f
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri May 3 11:19:16 2024 +1200

    pytest: sid_strings: Windows does allow lowercase s-1-... SIDs
    
    And so should we.
    
    Right now, these tests won't pass against Windows because they rely on
    ldb pre-parsing of the SIDs, so they fail before Windows gets to see
    them. Running them against Windows looks something like this, BTW:
    
        SAMBA_SID_STRINGS_SKIP_LOCAL=1  \
        SMB_CONF_PATH=st/ad_dc/etc/smb.conf \
        PYTHONPATH=bin/default/python \
        DC_SERVER=192.168.122.126 \
        DC_USERNAME=Administrator DC_PASSWORD='xxx' \
        python3 python/samba/tests/sid_strings.py
    
    When things are right, the only failing tests should be from the
    SidStringBehavioursThatSambaPrefers suite.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit fb724c61107b76d32b500802f960aa8e049ccbd8
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Thu May 2 14:24:18 2024 +1200

    pytest: sid_strings: use more reliable well known SID
    
    It seems as if the well-known SID S-1-5-32-579
    (DOMAIN_ALIAS_RID_ACCESS_CONTROL_ASSISTANCE_OPS) is
    not always present -- specifically, it was not there on the
    Windows machine used to develop these tests, but it is there on
    the one I am now using.
    
    S-1-5-32-545 (DOMAIN_ALIAS_RID_USERS) is surely going to exist,
    so we use that instead.
    
    That changes some of the assertions, making some NO_SUCH_OBJECTs
    into successes.
    
    For these tests we are only interested in the parsing of the SIDs, not
    their meaning, so it's OK to change it.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit ae4f095586e50d765f404cd85e9aacf21e84892d
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Sat Apr 13 22:39:49 2024 +1200

    ldb-samba: ldif_write_schemaInfo() uses correct size
    
    repsFromToBlob is much bigger, so this only meant we briefly allocated
    more than we needed.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10763
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 13af2cb02171c0f10133813746e2f938ae2e304d
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Sat Apr 13 17:53:24 2024 +1200

    lib:util: codepoint_cmpi: be transitive and case-insensitive
    
    the less/greater conparisons were not case-sensitive, which made the whole
    function non-transitive.
    
    I think codepoint_cmpi() is currently only used for equality tests, so
    nothing will change.
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 310d59c7cc38f82e2906c4a5c80db140ad2a1548
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Sat Apr 13 17:07:20 2024 +1200

    lib:util:tests: more tests for codepoint_cmpi
    
    is codepoint_cmpi as case-insensitive as it claims when it comes to
    inequalities? (no, it is not!).
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 827b0c39ed0497407bfcfc5683735a165b1b0f0a
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 12 20:28:04 2024 +1200

    s4:dsdb:mod: repl_md: message sort uses NUMERIC_CMP()
    
    No change at all in the result, just saving lines and branches.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit c5c29f59fa6baa1564a7fde55e2b0639a6a8a39c
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 12 18:33:47 2024 +1200

    s4:rpc_srv:getncchanges: USN sort uses qsort() instead of ldb_qsort()
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 65df8ce05c1d1bb9dd93592269ef966446cc5746
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 12 18:32:42 2024 +1200

    s4:rpc_srv:getncchanges: 4.5 anc emulation uses qsort(), not ldb_qsort()
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 5335f122fb551231a02a58f88f6a0aa23b5e02cb
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 12 18:11:47 2024 +1200

    s4:dsdb:mod: repl_md: make message_sort transitive
    
    Before we had (with a TODO of regret):
    
           if (!a1 || !a2) {
                   return strcasecmp(e1->name, e2->name);
           }
    
    so, given {name:"A", id 2}, {name:"B", NO id}, {name:"C", id 1},
    
     A < B by name
     B < C by name
     A > C by id
    
    Now the sort order is always A > C > B.
    
    This sort could have caused mysterious crashes in repl_meta_data if
    the schema is out of sync.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 7f995ab887a487df2213cbb7e9f79a09346e86ba
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 12 18:11:12 2024 +1200

    ldb:tools: ldbsearch doesn't need ldb_qsort()
    
    When the opaque context blob is not used, we might as well
    use a real qsort().
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit b37186cf917ba9416b9d255e2d00d24cb8d12347
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Wed May 1 16:26:14 2024 +1200

    s4:dsdb:util_trusts: simplify the NULL case in dns_cmp
    
    In this comparison function a NULL string is treated as the ancestor
    of all names, but you need to look hard to see that.
    
    By pulling the logic for NULLs to the front, hopefully we have to look
    less hard.
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 91b802941c17f81398b08a66b5bedfa1127db070
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 12 21:28:31 2024 +1200

    s4:dsdb:util_trusts: describe dns_cmp return values
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 8f080c0295d07b526740882469e1577a44c79060
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Tue Apr 16 23:31:45 2024 +1200

    ldb:tests: add a test for dotted i uppercase
    
    This didn't fail in the tr_TR locale before recent changes for
    https://bugzilla.samba.org/show_bug.cgi?id=15637, because this is a
    different casefold codepath. But it could fail if that other path goes
    wrong, so we might as well have the test.
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit af7654331fb6a2d9cc41cf5bdffa74c81ff4ffee
Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
Date:   Fri Apr 26 15:24:47 2024 +1200

    ldb: avoid NULL deref in ldb_db_compare
    
    This also sorts NULLs after invalid DNs, which matches the comment
    above.
    
    CID 1596622.
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15625
    
    Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 ...able_sort_r.c => fuzz_stable_sort_r_unstable.c} | 53 +++++++++++----
 lib/fuzzing/wscript_build                          |  5 ++
 lib/ldb-samba/ldif_handlers.c                      | 77 +++++++++-------------
 lib/ldb/common/attrib_handlers.c                   | 47 +++++++++++--
 lib/ldb/common/ldb_dn.c                            | 16 ++++-
 lib/ldb/tests/python/api.py                        |  4 ++
 lib/ldb/tools/ldbsearch.c                          |  5 +-
 lib/util/charset/codepoints.c                      | 18 +----
 lib/util/charset/tests/charset.c                   | 11 +++-
 python/samba/tests/sid_strings.py                  | 26 ++++----
 selftest/knownfail.d/sid-strings                   |  6 +-
 source4/dsdb/common/util_trusts.c                  | 32 +++++++--
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c    | 17 +++--
 source4/rpc_server/drsuapi/getncchanges.c          | 20 +++---
 14 files changed, 207 insertions(+), 130 deletions(-)
 copy lib/fuzzing/{fuzz_stable_sort_r.c => fuzz_stable_sort_r_unstable.c} (61%)


Changeset truncated at 500 lines:

diff --git a/lib/fuzzing/fuzz_stable_sort_r.c 
b/lib/fuzzing/fuzz_stable_sort_r_unstable.c
similarity index 61%
copy from lib/fuzzing/fuzz_stable_sort_r.c
copy to lib/fuzzing/fuzz_stable_sort_r_unstable.c
index 68be73b3f48..cd4d7915ad3 100644
--- a/lib/fuzzing/fuzz_stable_sort_r.c
+++ b/lib/fuzzing/fuzz_stable_sort_r_unstable.c
@@ -1,6 +1,6 @@
 /*
    Fuzzing for stable_sort
-   Copyright © Catalyst IT
+   Copyright © Catalyst IT 2024
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -27,12 +27,45 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
 }
 
 /*
- * For a "context" we use a byte that the values are XORed with before
- * comparison, for a non-obvious but stable sort order.
+ * This function tries to never be a proper comparison function,
+ * whatever the value of ctx.
+ *
+ * If ctx is an odd number, it will change on every comparison,
+ * otherwise it will consistently use the same bad comparison
+ * technique.
  */
-static int cmp_int8(int8_t *a, int8_t *b, int8_t *c)
+static int cmp_int8(int8_t *_a, int8_t *_b, int8_t *ctx)
 {
-       return (*a ^ *c) - (*b ^ *c);
+       int8_t a = *_a;
+       int8_t b = *_b;
+       int8_t c = *ctx;
+
+       if (c & 1) {
+               /* aim for sustained chaos. */
+               c += a;
+               c ^= b;
+               c ^= (c >> 5) + (c << 3);
+               *ctx = (c + 99) | 1;
+       }
+       switch((c >> 1) & 7) {
+       case 0:
+               return -1;
+       case 1:
+               return 1;
+       case 2:
+               return a + b;
+       case 3:
+               return c - b;
+       case 4:
+               return (a ^ b) > c;
+       case 5:
+               return -(a > c);
+       case 6:
+               return 2 * a - b;
+       case 7:
+               break;
+       }
+       return a - c;
 }
 
 
@@ -45,7 +78,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
        int8_t aux[MAX_SIZE];
        int8_t context;
 
-       if (len < 1 || len > MAX_SIZE) {
+       if (len < 3 || len > MAX_SIZE) {
                return 0;
        }
        context = (int8_t)buf[0];
@@ -57,13 +90,5 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
        stable_sort_r(buf2, aux, len, 1,
                      (samba_compare_with_context_fn_t)cmp_int8,
                      &context);
-
-       for (i = 1; i < len; i++) {
-               int c = cmp_int8(&buf2[i - 1], &buf2[i], &context);
-               if (c > 0) {
-                       abort();
-               }
-       }
-
        return 0;
 }
diff --git a/lib/fuzzing/wscript_build b/lib/fuzzing/wscript_build
index 5a9801321aa..897a114ca7e 100644
--- a/lib/fuzzing/wscript_build
+++ b/lib/fuzzing/wscript_build
@@ -153,6 +153,11 @@ bld.SAMBA_BINARY('fuzz_stable_sort_r',
                  deps='fuzzing stable_sort afl-fuzz-main',
                  fuzzer=True)
 
+bld.SAMBA_BINARY('fuzz_stable_sort_r_unstable',
+                 source='fuzz_stable_sort_r_unstable.c',
+                 deps='fuzzing stable_sort afl-fuzz-main',
+                 fuzzer=True)
+
 bld.SAMBA_BINARY('fuzz_security_token_vs_descriptor',
                  source='fuzz_security_token_vs_descriptor.c',
                  deps='fuzzing samba-security afl-fuzz-main',
diff --git a/lib/ldb-samba/ldif_handlers.c b/lib/ldb-samba/ldif_handlers.c
index f77f86fdcc0..35531222611 100644
--- a/lib/ldb-samba/ldif_handlers.c
+++ b/lib/ldb-samba/ldif_handlers.c
@@ -91,8 +91,14 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void 
*mem_ctx,
        struct dom_sid sid;
        if (in->length > DOM_SID_STR_BUFLEN) {
                return -1;
+       }
+       if (in->length < 5) { /* "S-1-x" */
+               return -1;
+       }
+       if (in->data[0] != 'S' && in->data[0] != 's') {
+               return -1;
        } else {
-               char p[in->length+1];
+               char p[DOM_SID_STR_BUFLEN + 1];
                memcpy(p, in->data, in->length);
                p[in->length] = '\0';
 
@@ -138,17 +144,6 @@ int ldif_write_objectSid(struct ldb_context *ldb, void 
*mem_ctx,
        return 0;
 }
 
-bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
-{
-       if (v->length < 3) {
-               return false;
-       }
-
-       if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
-
-       return true;
-}
-
 /*
   compare two objectSids
 
@@ -157,40 +152,31 @@ bool ldif_comparision_objectSid_isString(const struct 
ldb_val *v)
 static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
                                    const struct ldb_val *v1, const struct 
ldb_val *v2)
 {
-       bool v1_is_string = ldif_comparision_objectSid_isString(v1);
-       bool v2_is_string = ldif_comparision_objectSid_isString(v2);
-       struct ldb_val parsed_1 = {};
-       struct ldb_val parsed_2 = {};
+       struct ldb_val parsed_1 = {.data = NULL};
+       struct ldb_val parsed_2 = {.data = NULL};
        int ret;
        /*
         * If the ldb_vals look like SID strings (i.e. start with "S-"
-        * or "s-"), we try to parse them as such. If that fails, we
-        * assume they are binary SIDs, even though that's not really
-        * possible -- the first two bytes of a struct dom_sid are the
-        * version (1), and the number of sub-auths (<= 15), neither
-        * of which are close to 'S' or '-'.
+        * or "s-"), we treat them as strings.
+        *
+        * It is not really possible for a blob to be both a SID string and a
+        * SID struct -- the first two bytes of a struct dom_sid (including in
+        * NDR form) are the version (1), and the number of sub-auths (<= 15),
+        * neither of which are close to 'S' or '-'.
         */
-       if (v1_is_string) {
-               int r = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
-               if (r == 0) {
-                       v1 = &parsed_1;
-               }
+       ret = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
+       if (ret == 0) {
+               v1 = &parsed_1;
        }
-       if (v2_is_string) {
-               int r = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
-               if (r == 0) {
-                       v2 = &parsed_2;
-               }
+       ret = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
+       if (ret == 0) {
+               v2 = &parsed_2;
        }
 
        ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
 
-       if (v1_is_string) {
-               TALLOC_FREE(parsed_1.data);
-       }
-       if (v2_is_string) {
-               TALLOC_FREE(parsed_2.data);
-       }
+       TALLOC_FREE(parsed_1.data);
+       TALLOC_FREE(parsed_2.data);
        return ret;
 }
 
@@ -200,13 +186,11 @@ static int ldif_comparison_objectSid(struct ldb_context 
*ldb, void *mem_ctx,
 static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
                                      const struct ldb_val *in, struct ldb_val 
*out)
 {
-       if (ldif_comparision_objectSid_isString(in)) {
-               if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
-                       /* Perhaps not a string after all */
-                       return ldb_handler_copy(ldb, mem_ctx, in, out);
-               }
+       /* First try as a string SID */
+       if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
                return 0;
        }
+       /* not a string after all */
        return ldb_handler_copy(ldb, mem_ctx, in, out);
 }
 
@@ -215,10 +199,9 @@ static int extended_dn_read_SID(struct ldb_context *ldb, 
void *mem_ctx,
 {
        struct dom_sid sid;
        enum ndr_err_code ndr_err;
-       if (ldif_comparision_objectSid_isString(in)) {
-               if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
-                       return 0;
-               }
+
+       if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
+               return 0;
        }
 
        /* Perhaps not a string after all */
@@ -562,7 +545,7 @@ static int ldif_write_schemaInfo(struct ldb_context *ldb, 
void *mem_ctx,
                                 const struct ldb_val *in, struct ldb_val *out)
 {
        return ldif_write_NDR(ldb, mem_ctx, in, out,
-                             sizeof(struct repsFromToBlob),
+                             sizeof(struct schemaInfoBlob),
                              (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
                              (ndr_print_fn_t)ndr_print_schemaInfoBlob,
                              true);
diff --git a/lib/ldb/common/attrib_handlers.c b/lib/ldb/common/attrib_handlers.c
index 6ae12c88eec..e6d412bd3cf 100644
--- a/lib/ldb/common/attrib_handlers.c
+++ b/lib/ldb/common/attrib_handlers.c
@@ -389,22 +389,57 @@ utf8str:
         * No need to recheck from the start, just from the first utf8 charu
         * found. Note that the callback of ldb_casefold() needs to be ascii
         * compatible.
+        *
+        * Probably ldb_casefold() is wrap_casefold() which wraps
+        * strupper_talloc_n().
         */
        b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
        b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
 
        if (!b1 || !b2) {
-               /* One of the strings was not UTF8, so we have no
-                * options but to do a binary compare */
+               /*
+                * One of the strings was not UTF8, so we have no
+                * options but to do a binary compare.
+                *
+                * FIXME: this can be non-transitive.
+                *
+                * consider {
+                *           CA 8A  "ʊ"
+                *           C6 B1  "Ʊ"
+                *           C8 FE  invalid utf-8
+                *          }
+                *
+                * The byte "0xfe" is always invalid in utf-8, so the
+                * comparisons against that string end up coming this way,
+                * while the "Ʊ" vs "ʊ" comparison goes via the ldb_casefold
+                * branch. Then:
+                *
+                *  "ʊ" == "Ʊ"     by casefold.
+                *  "ʊ" > {c8 fe}  by byte comparison.
+                *  "Ʊ" < {c8 fe}  by byte comparison.
+                *
+                * In many cases there are no invalid encodings between the
+                * upper and lower case letters, but the string as a whole
+                * might also compare differently due to the space-eating in
+                * the other branch.
+                */
                talloc_free(b1);
                talloc_free(b2);
                ret = memcmp(s1, s2, MIN(n1, n2));
                if (ret == 0) {
-                       if (n1 == n2) return 0;
+                       if (n1 == n2) {
+                               return 0;
+                       }
                        if (n1 > n2) {
-                               return (int)ldb_ascii_toupper(s1[n2]);
+                               if (s1[n2] == '\0') {
+                                       return 0;
+                               }
+                               return 1;
                        } else {
-                               return -(int)ldb_ascii_toupper(s2[n1]);
+                               if (s2[n1] == '\0') {
+                                       return 0;
+                               }
+                               return -1;
                        }
                }
                return ret;
@@ -426,7 +461,7 @@ utf8str:
                while (*u1 == ' ') u1++;
                while (*u2 == ' ') u2++;
        }
-       ret = (int)(*u1 - *u2);
+       ret = NUMERIC_CMP(*u1, *u2);
 
        talloc_free(b1);
        talloc_free(b2);
diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c
index d2517089da5..cb4266dca91 100644
--- a/lib/ldb/common/ldb_dn.c
+++ b/lib/ldb/common/ldb_dn.c
@@ -1145,13 +1145,23 @@ int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn 
*dn1)
         * | normal DNs, sorted | casefold failed DNs | invalid DNs | NULLs |
         */
 
-       if (dn0 == dn1 || (dn0->invalid && dn1->invalid)) {
+       if (dn0 == dn1) {
+               /* this includes the both-NULL case */
                return 0;
        }
-       if (dn0 == NULL || dn0->invalid) {
+       if (dn0 == NULL) {
                return 1;
        }
-       if (dn1 == NULL || dn1->invalid) {
+       if (dn1 == NULL) {
+               return -1;
+       }
+       if (dn0->invalid && dn1->invalid) {
+               return 0;
+       }
+       if (dn0->invalid) {
+               return 1;
+       }
+       if (dn1->invalid) {
                return -1;
        }
 
diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py
index 0fc31e3fe09..bdd69f07734 100755
--- a/lib/ldb/tests/python/api.py
+++ b/lib/ldb/tests/python/api.py
@@ -2852,6 +2852,10 @@ class DnTests(TestCase):
         x = ldb.Dn(self.ldb, "dc=foo14,bar=bloe")
         self.assertEqual(x.get_casefold(), "DC=FOO14,BAR=bloe")
 
+    def test_get_casefold_dotted_i(self):
+        x = ldb.Dn(self.ldb, "dc=foo14,bir=blie")
+        self.assertEqual(x.get_casefold(), "DC=FOO14,BIR=blie")
+
     def test_validate(self):
         x = ldb.Dn(self.ldb, "dc=foo15,bar=bloe")
         self.assertTrue(x.validate())
diff --git a/lib/ldb/tools/ldbsearch.c b/lib/ldb/tools/ldbsearch.c
index 374f2405e47..a0c74b175fa 100644
--- a/lib/ldb/tools/ldbsearch.c
+++ b/lib/ldb/tools/ldbsearch.c
@@ -45,8 +45,7 @@ static void usage(struct ldb_context *ldb)
 }
 
 static int do_compare_msg(struct ldb_message **el1,
-                         struct ldb_message **el2,
-                         void *opaque)
+                         struct ldb_message **el2)
 {
        return ldb_dn_compare((*el1)->dn, (*el2)->dn);
 }
@@ -269,7 +268,7 @@ again:
                unsigned int i;
 
                if (sctx->num_stored) {
-                       LDB_TYPESAFE_QSORT(sctx->store, sctx->num_stored, ldb, 
do_compare_msg);
+                       TYPESAFE_QSORT(sctx->store, sctx->num_stored, 
do_compare_msg);
                }
                for (i = 0; i < sctx->num_stored; i++) {
                        display_message(sctx->store[i], sctx);
diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c
index 80226278faf..a62771801d8 100644
--- a/lib/util/charset/codepoints.c
+++ b/lib/util/charset/codepoints.c
@@ -16480,22 +16480,8 @@ _PUBLIC_ bool isupper_m(codepoint_t val)
 */
 _PUBLIC_ int codepoint_cmpi(codepoint_t c1, codepoint_t c2)
 {
-       /*
-        * FIXME: this is unsuitable for use in a sort, as the
-        * comparison is intransitive.
-        *
-        * The problem is toupper_m() is only called on equality case,
-        * which has strange effects.
-        *
-        *    Consider {'a', 'A', 'B'}.
-        *     'a' == 'A'
-        *     'a' >  'B'  (lowercase letters come after upper)
-        *     'A' <  'B'
-        */
-       if (c1 == c2 ||
-           toupper_m(c1) == toupper_m(c2)) {
-               return 0;
-       }
+       c1 = toupper_m(c1);
+       c2 = toupper_m(c2);
        return NUMERIC_CMP(c1, c2);
 }
 
diff --git a/lib/util/charset/tests/charset.c b/lib/util/charset/tests/charset.c
index bca5449c579..46f89cb9ef4 100644
--- a/lib/util/charset/tests/charset.c
+++ b/lib/util/charset/tests/charset.c
@@ -47,7 +47,16 @@ static bool test_codepoint_cmpi(struct torture_context *tctx)
        torture_assert_int_equal(tctx, codepoint_cmpi('a', 'a'), 0, "same 
char");
        torture_assert_int_equal(tctx, codepoint_cmpi('A', 'a'), 0, "upcase 
version");
        torture_assert_int_equal(tctx, codepoint_cmpi('b', 'a'), 1, "right 
diff");
-       torture_assert_int_equal(tctx, codepoint_cmpi('a', 'b'), -1, "right 
diff");
+       torture_assert_int_equal(tctx, codepoint_cmpi('b', 'A'), 1, "left 
greater, mixed case");
+       torture_assert_int_equal(tctx, codepoint_cmpi('C', 'a'), 1, "left 
greater, mixed case");
+       torture_assert_int_equal(tctx, codepoint_cmpi('a', 'b'), -1, "right 
greater");
+       torture_assert_int_equal(tctx, codepoint_cmpi('A', 'B'), -1, "right 
greater, upper case");
+       torture_assert_int_equal(tctx, codepoint_cmpi(0xc5, 0xc5), 0,
+                                "Latin Capital Letter A with Ring Above");
+       torture_assert_int_equal(tctx, codepoint_cmpi(0xc5, 0xe5), 0,
+                                "Latin both Letter A with Ring Above, lower 
right");
+       torture_assert_int_equal(tctx, codepoint_cmpi(0xe5, 0xde), -1,
+                                "å < Þ");
        return true;
 }
 
diff --git a/python/samba/tests/sid_strings.py 
b/python/samba/tests/sid_strings.py
index 108351cc102..fbeb0a94077 100644
--- a/python/samba/tests/sid_strings.py
+++ b/python/samba/tests/sid_strings.py
@@ -410,9 +410,9 @@ class SidStringsAsDnInSearchBase(SidStringBase):
     """
     skip_local = True
     cases = {' S-1-1-1-1-1-1-1': ldb.ERR_INVALID_DN_SYNTAX,
-             'S-0-5-32-579': ldb.ERR_INVALID_DN_SYNTAX,
+             'S-0-5-32-545': ldb.ERR_INVALID_DN_SYNTAX,
              'S-000000000001-5-20-243': ldb.ERR_INVALID_DN_SYNTAX,
-             'S-000000001-5-32-579': ldb.ERR_INVALID_DN_SYNTAX,
+             'S-000000001-5-32-545': ldb.ERR_INVALID_DN_SYNTAX,
              'S-01-05-020-0243': ldb.ERR_NO_SUCH_OBJECT,
              'S-01-5-32-11579': ldb.ERR_NO_SUCH_OBJECT,
              'S-0x1-0-0-579': ldb.ERR_INVALID_DN_SYNTAX,
@@ -423,11 +423,11 @@ class SidStringsAsDnInSearchBase(SidStringBase):
              'S-1-0': ldb.ERR_NO_SUCH_OBJECT,
              'S-1-0-0-579': ldb.ERR_NO_SUCH_OBJECT,
              'S-1-0x05-32-11579': ldb.ERR_NO_SUCH_OBJECT,
-             'S-1-0x5-0x20-0x243': ldb.ERR_NO_SUCH_OBJECT,
+             'S-1-0x5-0x20-0x221': None,
              'S-1-0x50000000-32-579': ldb.ERR_NO_SUCH_OBJECT,
-             'S-1-0x500000000-0x500000000-579': ldb.ERR_NO_SUCH_OBJECT,
+             'S-1-0x500000000-0x500000000-579': ldb.ERR_INVALID_DN_SYNTAX,
              'S-1-0x500000000-32-579': ldb.ERR_NO_SUCH_OBJECT,
-             'S-1-0xABcDef123-0xABCDef123-579': ldb.ERR_NO_SUCH_OBJECT,
+             'S-1-0xABcDef123-0xABCDef123-579': ldb.ERR_INVALID_DN_SYNTAX,
              'S-1-1-1-1-1-1-1': ldb.ERR_NO_SUCH_OBJECT,
              'S-1-21474836480-32-579': ldb.ERR_NO_SUCH_OBJECT,
              'S-1-22': ldb.ERR_NO_SUCH_OBJECT,
@@ -439,7 +439,7 @@ class SidStringsAsDnInSearchBase(SidStringBase):
              'S-1-3-99': ldb.ERR_NO_SUCH_OBJECT,
              'S-1-5-0-579': ldb.ERR_NO_SUCH_OBJECT,
              'S-1-5-040-579': ldb.ERR_NO_SUCH_OBJECT,
-             'S-1-5-0x20-579': ldb.ERR_NO_SUCH_OBJECT,
+             'S-1-5-0x20-545': None,
              'S-1-5-11111111111111111111111111111111111-579': 
ldb.ERR_INVALID_DN_SYNTAX,
              'S-1-5-18446744073709551615-579': ldb.ERR_INVALID_DN_SYNTAX,
              'S-1-5-18446744073709551616-579': ldb.ERR_INVALID_DN_SYNTAX,
@@ -453,7 +453,8 @@ class SidStringsAsDnInSearchBase(SidStringBase):
              'S-1-99999999999999999999999999999999999999-32-11111111111': 
ldb.ERR_INVALID_DN_SYNTAX,
              'S-10-5-32-579': ldb.ERR_INVALID_DN_SYNTAX,
              'S-2-5-32-579': ldb.ERR_INVALID_DN_SYNTAX,
-             's-1-5-32-579': ldb.ERR_INVALID_DN_SYNTAX,
+             's-1-5-32-5791': ldb.ERR_NO_SUCH_OBJECT,
+             's-1-5-32-545': None,
              'AA': ldb.ERR_INVALID_DN_SYNTAX,
         }
 
@@ -488,11 +489,11 @@ class SidStringsAsDnSearchWithDnObject(SidStringBase):
              'S-1-0': (None, ldb.ERR_NO_SUCH_OBJECT),
              'S-1-0-0-579': (None, ldb.ERR_NO_SUCH_OBJECT),
              'S-1-0x05-32-579': (None, None),
-             'S-1-0x5-0x20-0x243': (None, ldb.ERR_NO_SUCH_OBJECT),
+             'S-1-0x5-0x20-0x221': (None, None),
              'S-1-0x50000000-32-579': (None, ldb.ERR_NO_SUCH_OBJECT),
-             'S-1-0x500000000-0x500000000-579': (None, ldb.ERR_NO_SUCH_OBJECT),
+             'S-1-0x500000000-0x500000000-579': ('parse error', None),
              'S-1-0x500000000-32-579': (None, ldb.ERR_NO_SUCH_OBJECT),
-             'S-1-0xABcDef123-0xABCDef123-579': (None, ldb.ERR_NO_SUCH_OBJECT),
+             'S-1-0xABcDef123-0xABCDef123-579': ('parse error', None),
              'S-1-1-1-1-1-1-1': (None, ldb.ERR_NO_SUCH_OBJECT),
              'S-1-21474836480-32-579': (None, ldb.ERR_NO_SUCH_OBJECT),
              'S-1-22': (None, ldb.ERR_NO_SUCH_OBJECT),


-- 
Samba Shared Repository


Reply via email to