Duplicate detection for encoding
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index eb0a691..cb22ff3 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -1,6 +1,6 @@
 /* =========================================================================
  * Copyright (c) 2016-2018, The Linux Foundation.
- * Copyright (c) 2018-2022, Laurence Lundblade.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
  * Copyright (c) 2021, Arm Limited. All rights reserved.
  * All rights reserved.
  *
@@ -43,6 +43,7 @@
 
  when         who             what, where, why
  --------     ----            --------------------------------------------------
+ 28/02/2022   llundblade      Rearrange UsefulOutBuf_Compare().
  19/11/2023   llundblade      Add UsefulOutBuf_GetOutput().
  19/11/2023   llundblade      Add UsefulOutBuf_Swap().
  19/11/2023   llundblade      Add UsefulOutBuf_Compare().
@@ -1406,6 +1407,8 @@
  * @return  0 for equality, positive if uStart1 is lexographically larger,
  *          negative if uStart2 is lexographically larger.
  *
+ * TODO: update documentation
+ * 
  * This looks into bytes that have been output at the offsets @c start1
  * and @c start2. It compares bytes at those two starting points until
  * they are not equal or the end of the output data is reached from
@@ -1427,8 +1430,10 @@
  * output buffer. It is employed by QCBOR to sort CBOR-encoded maps that
  * are in the output buffer.
  */
-int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf, size_t uStart1, size_t uStart2);
 
+int UsefulOutBuf_Compare(UsefulOutBuf *me,
+                         size_t uStart1, size_t uLen1,
+                         size_t uStart2, size_t uLen2);
 
 /**
  * @brief Swap two regions of output bytes.
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index 847395c..3c39ebd 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2023, Laurence Lundblade.
+ Copyright (c) 2018-2024, Laurence Lundblade.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -41,6 +41,7 @@
 
  when        who          what, where, why
  --------    ----         ---------------------------------------------------
+ 28/02/2022  llundblade   Rearrange UsefulOutBuf_Compare().
  19/11/2023  llundblade   Add UsefulOutBuf_GetOutput().
  19/11/2023  llundblade   Add UsefulOutBuf_Swap().
  19/11/2023  llundblade   Add UsefulOutBuf_Compare().
@@ -433,21 +434,27 @@
  *
  * Code Reviewers: THIS FUNCTION DOES POINTER MATH
  */
-int UsefulOutBuf_Compare(UsefulOutBuf *me, size_t uStart1, size_t uStart2)
+int UsefulOutBuf_Compare(UsefulOutBuf *me,
+                         size_t uStart1, size_t uLen1,
+                         size_t uStart2, size_t uLen2)
 {
    const uint8_t *pBase;
    const uint8_t *pEnd;
    const uint8_t *p1;
    const uint8_t *p2;
+   const uint8_t *p1End;
+   const uint8_t *p2End;
    int            uComparison;
 
    pBase = me->UB.ptr;
    pEnd = (const uint8_t *)pBase + me->data_len;
    p1   = pBase + uStart1;
    p2   = pBase + uStart2;
+   p1End = p1 + uLen1;
+   p2End = p2 + uLen2;
 
    uComparison = 0;
-   while(p1 < pEnd && p2 < pEnd) {
+   while(p1 < pEnd && p2 < pEnd && p1 < p1End && p2 < p2End) {
       uComparison = *p2 - *p1;
       if(uComparison != 0) {
          break;;
@@ -460,6 +467,7 @@
 }
 
 
+
 /**
  * @brief Reverse order of bytes in a buffer.
  *
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 146253d..76f2923 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -1274,13 +1274,18 @@
             break;
          }
 
-         nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf), uStart1, uStart2);
+         nComparison = UsefulOutBuf_Compare(&(pMe->OutBuf),
+                                            uStart1, (uStart2 - uStart1),
+                                            uStart2, uLen2);
          if(nComparison < 0) {
             UsefulOutBuf_Swap(&(pMe->OutBuf), uStart1, uStart2, uStart2 + uLen2);
             uStart1 = uStart1 + uLen2;
             bSwapped = true;
-         } else {
+         } else if (nComparison > 0) {
             uStart1 = uStart2;
+         } else /* nComparison == 0 */ {
+            pMe->uError = QCBOR_ERR_DUPLICATE_LABEL;
+            return;
          }
          uStart2 = uStart2 + uLen2;
       }
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index e6be249..34a9a00 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.c
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2023, Laurence Lundblade.
+ Copyright (c) 2018-2024, Laurence Lundblade.
  Copyright (c) 2021, Arm Limited.
  All rights reserved.
 
@@ -885,61 +885,63 @@
    /* Test UsefulOutBuf_Compare() */
    UsefulOutBuf_AppendString(&UOB, "abcabdefab");
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 0, 8);
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 2, 8, 2);
    if(nCompare != 0) {
       return "ab should compare equal";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 0, 3);
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 3, 3, 3);
    if(nCompare != 'd' - 'c') {
       return "abc should not equal abd";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 3, 8);
+   nCompare = UsefulOutBuf_Compare(&UOB, 3, 2, 8, 2);
    if(nCompare != 0) {
        return "ab should compare equal";
     }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 2, 5);
+   nCompare = UsefulOutBuf_Compare(&UOB, 2, 4, 5, 4);
    if(nCompare != 'd' - 'c') {
       return "ca should not equal de";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 5, 2);
+   nCompare = UsefulOutBuf_Compare(&UOB, 5, 1, 2, 1);
    if(nCompare != 'c' - 'd') {
       return "de should not equal ca";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 7, 8);
+   nCompare = UsefulOutBuf_Compare(&UOB, 7, 2, 8, 2);
    if(nCompare !=  'a' - 'f') {
       return "fa should not equal ab";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 0, 0);
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 10, 0, 10);
    if(nCompare != 0) {
       return "comparison to self failed";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 9, 9);
+   nCompare = UsefulOutBuf_Compare(&UOB, 9, 1, 9, 1);
    if(nCompare != 0) {
       return "b should compare equal to b";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 10, 10);
+   nCompare = UsefulOutBuf_Compare(&UOB, 10, 1, 10, 1);
    if(nCompare != 0) {
       return "Comparison off the end is equal";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 0, 100);
+   nCompare = UsefulOutBuf_Compare(&UOB, 0, 1, 100, 1);
    if(nCompare != 0) {
       return "Comparison off the end is equal";
    }
 
-   nCompare = UsefulOutBuf_Compare(&UOB, 100, 0);
+   nCompare = UsefulOutBuf_Compare(&UOB, 100, 1, 0, 1);
    if(nCompare != 0) {
       return "Comparison off the end is equal";
    }
 
+   // TODO: a bit more checking off the end
+
    /* Test UsefulOutBuf_Swap() */
 
    UsefulOutBuf_Reset(&UOB);
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index 0abbb72..8c609bc 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -3379,5 +3379,19 @@
       return 102;
    }
 
+
+   /* --- Duplicate label test  --- */
+   QCBOREncode_Init(&EC, TestBuf);
+   QCBOREncode_OpenMap(&EC);
+   QCBOREncode_AddInt64ToMapN(&EC, 3, 3);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+   QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+   QCBOREncode_CloseAndSortMap(&EC);
+   uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+   if(uErr != QCBOR_ERR_DUPLICATE_LABEL) {
+      return 114;
+   }
+
    return 0;
 }