Skip to content

Commit 9e970e1

Browse files
authored
[CBOR] Improve an error message for byte string / array type mismatch (#3052)
1 parent 51fa6ad commit 9e970e1

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,17 @@ internal class CborParser(private val input: ByteArrayInput, private val verifyO
208208
skipByte(unboundedHeader)
209209
return -1
210210
}
211-
if ((curByte and 0b111_00000) != boundedHeaderMask)
211+
if ((curByte and 0b111_00000) != boundedHeaderMask) {
212+
if (boundedHeaderMask == HEADER_ARRAY && (curByte and 0b111_00000) == HEADER_BYTE_STRING) {
213+
throw CborDecodingException(
214+
"Expected a start of array, " +
215+
"but found ${printByte(curByte)}, which corresponds to the start of a byte string. " +
216+
"Make sure you correctly set 'alwaysUseByteString' setting " +
217+
"and/or 'kotlinx.serialization.cbor.ByteString' annotation."
218+
)
219+
}
212220
throw CborDecodingException("start of $collectionType", curByte)
221+
}
213222
val size = readNumber().toInt()
214223
readByte()
215224
return size
@@ -221,8 +230,17 @@ internal class CborParser(private val input: ByteArrayInput, private val verifyO
221230

222231
fun nextByteString(tags: ULongArray? = null): ByteArray {
223232
processTags(tags)
224-
if ((curByte and 0b111_00000) != HEADER_BYTE_STRING)
233+
if ((curByte and 0b111_00000) != HEADER_BYTE_STRING) {
234+
if (curByte and 0b111_00000 == HEADER_ARRAY) {
235+
throw CborDecodingException(
236+
"Expected a start of a byte string, " +
237+
"but found ${printByte(curByte)}, which corresponds to the start of an array. " +
238+
"Make sure you correctly set 'alwaysUseByteString' setting " +
239+
"and/or 'kotlinx.serialization.cbor.ByteString' annotation."
240+
)
241+
}
225242
throw CborDecodingException("start of byte string", curByte)
243+
}
226244
val arr = readBytes()
227245
readByte()
228246
return arr

formats/cbor/commonTest/src/kotlinx/serialization/cbor/CborDecoderTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,4 +374,24 @@ class CborDecoderTest {
374374
)
375375
}
376376

377+
@Test
378+
fun testMismatchedByteStringRepresentationError() {
379+
@Serializable class BytesHolder(@ByteString val bytes: ByteArray)
380+
@Serializable class ArrayHolder(val bytes: ByteArray)
381+
382+
assertFailsWithMessage<CborDecodingException>("Expected a start of array, but found 40, " +
383+
"which corresponds to the start of a byte string. " +
384+
"Make sure you correctly set 'alwaysUseByteString' setting " +
385+
"and/or 'kotlinx.serialization.cbor.ByteString' annotation.") {
386+
Cbor.decodeFromHexString<ArrayHolder>(Cbor.encodeToHexString(BytesHolder(ByteArray(0))))
387+
}
388+
389+
assertFailsWithMessage<CborDecodingException>("Expected a start of a byte string, but found 9F, " +
390+
"which corresponds to the start of an array. " +
391+
"Make sure you correctly set 'alwaysUseByteString' setting " +
392+
"and/or 'kotlinx.serialization.cbor.ByteString' annotation.") {
393+
Cbor.decodeFromHexString<BytesHolder>(Cbor.encodeToHexString(ArrayHolder(ByteArray(0))))
394+
}
395+
}
396+
377397
}

0 commit comments

Comments
 (0)