rvagg / cborg

fast CBOR with a focus on strictness
Other
47 stars 13 forks source link

Decoder failure #92

Closed telamon closed 1 year ago

telamon commented 1 year ago

Hello. I attempted to decode the following hex sequence:

a50102032620012158209b58eab4a0bd78474117f6f23a6c457cc5351d7b6bbeab62271d5ce2c8fdbda4225820db189f7af9cf4eb6149d6204ebe0821b0ed95193f10dc84044fac1e3f26c4a50a16b6372656450726f7465637402

using:

decode(buffer, { useMaps : true })

but cborg throws Error: CBOR decode error: too many terminals, data makes no sense

Expected

To decode the following data:

{1: 2, 3: -7, -1: 1, -2: h'9B58EAB4A0BD78474117F6F23A6C457CC5351D7B6BBEAB62271D5CE2C8FDBDA4', -3: h'DB189F7AF9CF4EB6149D6204EBE0821B0ED95193F10DC84044FAC1E3F26C4A50'}

Diagnostics from https://cbor.me

A5                                      # map(5)
   01                                   # unsigned(1)
   02                                   # unsigned(2)
   03                                   # unsigned(3)
   26                                   # negative(6)
   20                                   # negative(0)
   01                                   # unsigned(1)
   21                                   # negative(1)
   58 20                                # bytes(32)
      9B58EAB4A0BD78474117F6F23A6C457CC5351D7B6BBEAB62271D5CE2C8FDBDA4 # "\x9BX괠\xBDxGA\u0017\xF6\xF2:lE|\xC55\u001D{k\xBE\xABb'\u001D\\\xE2\xC8\xFD\xBD\xA4"
   22                                   # negative(2)
   58 20                                # bytes(32)
      DB189F7AF9CF4EB6149D6204EBE0821B0ED95193F10DC84044FAC1E3F26C4A50 # "\xDB\u0018\x9Fz\xF9\xCFN\xB6\u0014\x9Db\u0004\xEB\xE0\x82\e\u000E\xD9Q\x93\xF1\r\xC8@D\xFA\xC1\xE3\xF2lJP"

##### 14 unused bytes after the end of the data item:

A1 6B 63 72 65 64 50 72 6F 74 65 63 74 02

Can I get a second pair of eyes on this? Thanks!

rvagg commented 1 year ago

yeah:

$ cborg hex2diag a50102032620012158209b58eab4a0bd78474117f6f23a6c457cc5351d7b6bbeab62271d5ce2c8fdbda4225820db189f7af9cf4eb6149d6204ebe0821b0ed95193f10dc84044fac1e3f26c4a50a16b6372656450726f7465637402
a5                                                # map(5)
  01                                              #   uint(1)
  02                                              #   uint(2)
  03                                              #   uint(3)
  26                                              #   negint(-7)
  20                                              #   negint(-1)
  01                                              #   uint(1)
  21                                              #   negint(-2)
  58 20                                           #   bytes(32)
    9b58eab4a0bd78474117f6f23a6c457cc5351d7b6bbe  #     "\x9bXê´\xa0½xGA\x17öò:lE|Å5\x1d{k¾"
    ab62271d5ce2c8fdbda4                          #     "«b'\x1d\âÈý½¤"
  22                                              #   negint(-3)
  58 20                                           #   bytes(32)
    db189f7af9cf4eb6149d6204ebe0821b0ed95193f10d  #     "Û\x18\x9fzùÏN¶\x14\x9db\x04ëà\x82\x1b\x0eÙQ\x93ñ\x0d"
    c84044fac1e3f26c4a50                          #     "È@DúÁãòlJP"
a1                                                # map(1)
  6b                                              #   string(11)
    6372656450726f74656374                        #     "credProtect"
  02                                              #   uint(2)

So the problem here is that you have two maps, but they are not contained within a parent object, it doesn't know what to do with 2 dangling maps.

This would work:

cborg.decode(Buffer.from('a50102032620012158209b58eab4a0bd78474117f6f23a6c457cc5351d7b6bbeab62271d5ce2c8fdbda4225820db189f7af9cf4eb6149d6204ebe0821b0ed95193f10dc84044fac1e3f26c4a50', 'hex'), { useMaps: true })
// ->
Map(5) {
  1 => 2,
  3 => -7,
  -1 => 1,
  -2 => Uint8Array(32) [
    155, 88, 234, 180, 160, 189, 120,  71,
     65, 23, 246, 242,  58, 108,  69, 124,
    197, 53,  29, 123, 107, 190, 171,  98,
     39, 29,  92, 226, 200, 253, 189, 164
  ],
  -3 => Uint8Array(32) [
    219,  24, 159, 122, 249, 207,  78, 182,
     20, 157,  98,   4, 235, 224, 130,  27,
     14, 217,  81, 147, 241,  13, 200,  64,
     68, 250, 193, 227, 242, 108,  74,  80
  ]
}

and this would work:

cborg.decode(Buffer.from('a16b6372656450726f7465637402', 'hex'), { useMaps: true })
// ->
Map(1) { 'credProtect' => 2 }

and finally if you really wanted it to work you could join them together, maybe with an array:

cborg.decode(Buffer.from('82a50102032620012158209b58eab4a0bd78474117f6f23a6c457cc5351d7b6bbeab62271d5ce2c8fdbda4225820db189f7af9cf4eb6149d6204ebe0821b0ed95193f10dc84044fac1e3f26c4a50a16b6372656450726f7465637402', 'hex'), { useMaps: true })
// ->
[
  Map(5) {
    1 => 2,
    3 => -7,
    -1 => 1,
    -2 => Uint8Array(32) [
      155, 88, 234, 180, 160, 189, 120,  71,
       65, 23, 246, 242,  58, 108,  69, 124,
      197, 53,  29, 123, 107, 190, 171,  98,
       39, 29,  92, 226, 200, 253, 189, 164
    ],
    -3 => Uint8Array(32) [
      219,  24, 159, 122, 249, 207,  78, 182,
       20, 157,  98,   4, 235, 224, 130,  27,
       14, 217,  81, 147, 241,  13, 200,  64,
       68, 250, 193, 227, 242, 108,  74,  80
    ]
  },
  Map(1) { 'credProtect' => 2 }
]

Currently we have no support for read-until termination of an object; although it has been requested and shouldn't be too hard to do. I wrote up some notes in https://github.com/rvagg/cborg/issues/75

telamon commented 1 year ago

I see. Those are two separate maps yes. In my case that sequence was output by hardware. Without read-until termination of object - there is no way to determine the size of the first map / offset of second map.

const m1 = decode(buffer)
const m2 = decode(buffer.slice(decode.decodedBytes))
rvagg commented 1 year ago

see https://github.com/rvagg/cborg/pull/93, I'll likely publish that as a 4.0.0 tomorrow if there's no feedback in the meantime