Skip to content

Commit 7204a36

Browse files
authored
[Cbor] correctly skip structures with ignoreUnknownKeys setting (#2873)
1 parent aee6336 commit 7204a36

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

formats/cbor/commonMain/src/kotlinx/serialization/cbor/internal/Decoder.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,11 @@ internal class CborParser(private val input: ByteArrayInput, private val verifyO
426426
} else {
427427
val header = curByte and 0b111_00000
428428
val length = elementLength()
429-
if (header == HEADER_ARRAY || header == HEADER_MAP) {
429+
if (header == HEADER_TAG) {
430+
readNumber()
431+
} else if (header == HEADER_ARRAY || header == HEADER_MAP) {
430432
if (length > 0) lengthStack.add(length)
431-
processTags(tags)
433+
else prune(lengthStack) // empty map or array automatically completes
432434
} else {
433435
input.skip(length)
434436
prune(lengthStack)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package kotlinx.serialization.cbor
2+
3+
import kotlinx.serialization.*
4+
import kotlin.test.*
5+
6+
class CborSkipTagAndEmptyTest {
7+
8+
/**
9+
* A3 # map(3)
10+
* 67 # text(7)
11+
* 76657273696F6E # ""version""
12+
* 63 # text(3)
13+
* 312E30 # ""1.0""
14+
* 69 # text(9)
15+
* 646F63756D656E7473 # ""documents""
16+
* 81 # array(1)
17+
* A1 # map(1)
18+
* 6C # text(12)
19+
* 6465766963655369676E6564 # ""deviceSigned""
20+
* A2 # map(2)
21+
* 6A # text(10)
22+
* 6E616D65537061636573 # ""nameSpaces""
23+
* D8 18 # tag(24) <------------------- Testing this skips properly
24+
* 41 # bytes(1)
25+
* A0 # ""\xA0""
26+
* 6A # text(10)
27+
* 64657669636541757468 # ""deviceAuth""
28+
* A1 # map(1)
29+
* 69 # text(9)
30+
* 6465766963654D6163 # ""deviceMac""
31+
* 84 # array(4)
32+
* 43 # bytes(3)
33+
* A10105
34+
* A0 # map(0) <------------------- Testing this skips properly
35+
* F6 # primitive(22)
36+
* 58 20 # bytes(32)
37+
* E99521A85AD7891B806A07F8B5388A332D92C189A7BF293EE1F543405AE6824D
38+
* 66 # text(6)
39+
* 737461747573 # ""status""
40+
* 00 # unsigned(0)
41+
*/
42+
private val referenceHexString = "A36776657273696F6E63312E3069646F63756D656E747381A16C6465766963655369676E6564A26A6E616D65537061636573D81841A06A64657669636541757468A1696465766963654D61638443A10105A0F65820E99521A85AD7891B806A07F8B5388A332D92C189A7BF293EE1F543405AE6824D6673746174757300"
43+
44+
@Test
45+
fun deserializesCorrectly() {
46+
// Specifically, skipping keys with descendants that contain tags and empty maps
47+
val cbor = Cbor{
48+
ignoreUnknownKeys = true
49+
}
50+
// Prior exception:
51+
// Field 'status' is required for type with serial name 'kotlinx.serialization.cbor.CborSkipTagAndEmptyTest.DataClass', but it was missing
52+
val target = cbor.decodeFromHexString(DataClass.serializer(), referenceHexString)
53+
assertEquals(0, target.status)
54+
}
55+
56+
@Serializable
57+
data class DataClass(
58+
val status: Int,
59+
)
60+
}

0 commit comments

Comments
 (0)