Duplicate map label detection for encoding (#209)
This adds duplicate map label detection during encoding as part of sorting.
There was a lot of rework of map sorting.
UsefulOutBuf_Compare() was changed to behave differently and more universally.
* Duplicate detection for encoding
* rework UsefulOutBuf_Compare and test
* Dup detection seems to be working
* Final tidy-up
---------
Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index 7594006..118b232 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -3196,7 +3196,24 @@
if(uErr) {
return 31;
}
- static const uint8_t spNested[] = {
+
+ /* Correctly sorted.
+ * {
+ * 88: 1(888888),
+ * 428: {
+ * "null": null,
+ * "array": [
+ * "hi",
+ * "there"
+ * ],
+ * "empty1": {},
+ * "empty2": {}
+ * },
+ * "boo": true,
+ * "three": 3
+ * }
+ */
+ static const uint8_t spSorted[] = {
0xA4, 0x18, 0x58, 0xC1, 0x1A, 0x00, 0x0D, 0x90,
0x38, 0x19, 0x01, 0xAC, 0xA4, 0x64, 0x6E, 0x75,
0x6C, 0x6C, 0xF6, 0x65, 0x61, 0x72, 0x72, 0x61,
@@ -3207,11 +3224,72 @@
0x65, 0x74, 0x68, 0x72, 0x65, 0x65, 0x03};
if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
- UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spNested),
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSorted),
&CompareDiagnostics)) {
return 32;
}
+
+ /* Same data items, but added in a different order */
+ QCBOREncode_Init(&EC, TestBuf);
+ QCBOREncode_OpenMap(&EC);
+ QCBOREncode_AddInt64ToMap(&EC, "three", 3);
+ QCBOREncode_OpenMapInMapN(&EC, 428);
+ QCBOREncode_OpenMapInMap(&EC, "empty1");
+ QCBOREncode_CloseAndSortMap(&EC);
+ QCBOREncode_OpenArrayInMap(&EC, "array");
+ QCBOREncode_AddSZString(&EC, "hi");
+ QCBOREncode_AddSZString(&EC, "there");
+ QCBOREncode_CloseArray(&EC);
+ QCBOREncode_OpenMapInMap(&EC, "empty2");
+ QCBOREncode_CloseAndSortMap(&EC);
+ QCBOREncode_AddNULLToMap(&EC, "null");
+ QCBOREncode_CloseAndSortMap(&EC);
+ QCBOREncode_AddDateEpochToMapN(&EC, 88, 888888);
+ QCBOREncode_AddBoolToMap(&EC, "boo", true);
+ QCBOREncode_CloseAndSortMap(&EC);
+ uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+ if(uErr) {
+ return 31;
+ }
+
+ if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSorted),
+ &CompareDiagnostics)) {
+ return 32;
+ }
+
+ /* Same data items, but added in a different order */
+ QCBOREncode_Init(&EC, TestBuf);
+ QCBOREncode_OpenMap(&EC);
+ QCBOREncode_AddBoolToMap(&EC, "boo", true);
+ QCBOREncode_OpenMapInMapN(&EC, 428);
+ QCBOREncode_OpenMapInMap(&EC, "empty1");
+ QCBOREncode_CloseAndSortMap(&EC);
+ QCBOREncode_OpenArrayInMap(&EC, "array");
+ QCBOREncode_AddSZString(&EC, "hi");
+ QCBOREncode_AddSZString(&EC, "there");
+ QCBOREncode_CloseArray(&EC);
+ QCBOREncode_OpenMapInMap(&EC, "empty2");
+ QCBOREncode_CloseAndSortMap(&EC);
+ QCBOREncode_AddNULLToMap(&EC, "null");
+ QCBOREncode_CloseAndSortMap(&EC);
+ QCBOREncode_AddDateEpochToMapN(&EC, 88, 888888);
+ QCBOREncode_AddInt64ToMap(&EC, "three", 3);
+ QCBOREncode_CloseAndSortMap(&EC);
+ uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+ if(uErr) {
+ return 31;
+ }
+
+ if(UsefulBuf_CompareWithDiagnostic(EncodedAndSorted,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSorted),
+ &CompareDiagnostics)) {
+ return 32;
+ }
+
+
+
/* --- Degenerate case of everything in order --- */
QCBOREncode_Init(&EC, TestBuf);
QCBOREncode_OpenMap(&EC);
@@ -3429,6 +3507,44 @@
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;
+ }
+
+ QCBOREncode_Init(&EC, TestBuf);
+ QCBOREncode_OpenMap(&EC);
+ QCBOREncode_AddInt64ToMapN(&EC, 3, 3);
+ QCBOREncode_AddInt64ToMapN(&EC, 1, 1);
+ QCBOREncode_AddInt64ToMapN(&EC, 1, 2);
+ QCBOREncode_AddInt64ToMapN(&EC, 2, 2);
+ QCBOREncode_CloseAndSortMap(&EC);
+ uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+ if(uErr != QCBOR_ERR_DUPLICATE_LABEL) {
+ return 115;
+ }
+
+ QCBOREncode_Init(&EC, TestBuf);
+ QCBOREncode_OpenMap(&EC);
+ QCBOREncode_AddInt64ToMap(&EC, "abc", 3);
+ QCBOREncode_AddInt64ToMap(&EC, "def", 1);
+ QCBOREncode_AddInt64ToMap(&EC, "def", 1);
+ QCBOREncode_AddInt64ToMap(&EC, "def", 2);
+ QCBOREncode_CloseAndSortMap(&EC);
+ uErr = QCBOREncode_Finish(&EC, &EncodedAndSorted);
+ if(uErr != QCBOR_ERR_DUPLICATE_LABEL) {
+ return 116;
+ }
+
return 0;
}