valid.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // Copyright (c) Faye Amacker. All rights reserved.
  2. // Licensed under the MIT License. See LICENSE in the project root for license information.
  3. package cbor
  4. import (
  5. "encoding/binary"
  6. "errors"
  7. "io"
  8. "math"
  9. "strconv"
  10. "github.com/x448/float16"
  11. )
  12. // SyntaxError is a description of a CBOR syntax error.
  13. type SyntaxError struct {
  14. msg string
  15. }
  16. func (e *SyntaxError) Error() string { return e.msg }
  17. // SemanticError is a description of a CBOR semantic error.
  18. type SemanticError struct {
  19. msg string
  20. }
  21. func (e *SemanticError) Error() string { return e.msg }
  22. // MaxNestedLevelError indicates exceeded max nested level of any combination of CBOR arrays/maps/tags.
  23. type MaxNestedLevelError struct {
  24. maxNestedLevels int
  25. }
  26. func (e *MaxNestedLevelError) Error() string {
  27. return "cbor: exceeded max nested level " + strconv.Itoa(e.maxNestedLevels)
  28. }
  29. // MaxArrayElementsError indicates exceeded max number of elements for CBOR arrays.
  30. type MaxArrayElementsError struct {
  31. maxArrayElements int
  32. }
  33. func (e *MaxArrayElementsError) Error() string {
  34. return "cbor: exceeded max number of elements " + strconv.Itoa(e.maxArrayElements) + " for CBOR array"
  35. }
  36. // MaxMapPairsError indicates exceeded max number of key-value pairs for CBOR maps.
  37. type MaxMapPairsError struct {
  38. maxMapPairs int
  39. }
  40. func (e *MaxMapPairsError) Error() string {
  41. return "cbor: exceeded max number of key-value pairs " + strconv.Itoa(e.maxMapPairs) + " for CBOR map"
  42. }
  43. // IndefiniteLengthError indicates found disallowed indefinite length items.
  44. type IndefiniteLengthError struct {
  45. t cborType
  46. }
  47. func (e *IndefiniteLengthError) Error() string {
  48. return "cbor: indefinite-length " + e.t.String() + " isn't allowed"
  49. }
  50. // TagsMdError indicates found disallowed CBOR tags.
  51. type TagsMdError struct {
  52. }
  53. func (e *TagsMdError) Error() string {
  54. return "cbor: CBOR tag isn't allowed"
  55. }
  56. // ExtraneousDataError indicates found extraneous data following well-formed CBOR data item.
  57. type ExtraneousDataError struct {
  58. numOfBytes int // number of bytes of extraneous data
  59. index int // location of extraneous data
  60. }
  61. func (e *ExtraneousDataError) Error() string {
  62. return "cbor: " + strconv.Itoa(e.numOfBytes) + " bytes of extraneous data starting at index " + strconv.Itoa(e.index)
  63. }
  64. // wellformed checks whether the CBOR data item is well-formed.
  65. // allowExtraData indicates if extraneous data is allowed after the CBOR data item.
  66. // - use allowExtraData = true when using Decoder.Decode()
  67. // - use allowExtraData = false when using Unmarshal()
  68. func (d *decoder) wellformed(allowExtraData bool, checkBuiltinTags bool) error {
  69. if len(d.data) == d.off {
  70. return io.EOF
  71. }
  72. _, err := d.wellformedInternal(0, checkBuiltinTags)
  73. if err == nil {
  74. if !allowExtraData && d.off != len(d.data) {
  75. err = &ExtraneousDataError{len(d.data) - d.off, d.off}
  76. }
  77. }
  78. return err
  79. }
  80. // wellformedInternal checks data's well-formedness and returns max depth and error.
  81. func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, error) { //nolint:gocyclo
  82. t, _, val, indefiniteLength, err := d.wellformedHeadWithIndefiniteLengthFlag()
  83. if err != nil {
  84. return 0, err
  85. }
  86. switch t {
  87. case cborTypeByteString, cborTypeTextString:
  88. if indefiniteLength {
  89. if d.dm.indefLength == IndefLengthForbidden {
  90. return 0, &IndefiniteLengthError{t}
  91. }
  92. return d.wellformedIndefiniteString(t, depth, checkBuiltinTags)
  93. }
  94. valInt := int(val)
  95. if valInt < 0 {
  96. // Detect integer overflow
  97. return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, causing integer overflow")
  98. }
  99. if len(d.data)-d.off < valInt { // valInt+off may overflow integer
  100. return 0, io.ErrUnexpectedEOF
  101. }
  102. d.off += valInt
  103. case cborTypeArray, cborTypeMap:
  104. depth++
  105. if depth > d.dm.maxNestedLevels {
  106. return 0, &MaxNestedLevelError{d.dm.maxNestedLevels}
  107. }
  108. if indefiniteLength {
  109. if d.dm.indefLength == IndefLengthForbidden {
  110. return 0, &IndefiniteLengthError{t}
  111. }
  112. return d.wellformedIndefiniteArrayOrMap(t, depth, checkBuiltinTags)
  113. }
  114. valInt := int(val)
  115. if valInt < 0 {
  116. // Detect integer overflow
  117. return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, it would cause integer overflow")
  118. }
  119. if t == cborTypeArray {
  120. if valInt > d.dm.maxArrayElements {
  121. return 0, &MaxArrayElementsError{d.dm.maxArrayElements}
  122. }
  123. } else {
  124. if valInt > d.dm.maxMapPairs {
  125. return 0, &MaxMapPairsError{d.dm.maxMapPairs}
  126. }
  127. }
  128. count := 1
  129. if t == cborTypeMap {
  130. count = 2
  131. }
  132. maxDepth := depth
  133. for j := 0; j < count; j++ {
  134. for i := 0; i < valInt; i++ {
  135. var dpt int
  136. if dpt, err = d.wellformedInternal(depth, checkBuiltinTags); err != nil {
  137. return 0, err
  138. }
  139. if dpt > maxDepth {
  140. maxDepth = dpt // Save max depth
  141. }
  142. }
  143. }
  144. depth = maxDepth
  145. case cborTypeTag:
  146. if d.dm.tagsMd == TagsForbidden {
  147. return 0, &TagsMdError{}
  148. }
  149. tagNum := val
  150. // Scan nested tag numbers to avoid recursion.
  151. for {
  152. if len(d.data) == d.off { // Tag number must be followed by tag content.
  153. return 0, io.ErrUnexpectedEOF
  154. }
  155. if checkBuiltinTags {
  156. err = validBuiltinTag(tagNum, d.data[d.off])
  157. if err != nil {
  158. return 0, err
  159. }
  160. }
  161. if d.dm.bignumTag == BignumTagForbidden && (tagNum == 2 || tagNum == 3) {
  162. return 0, &UnacceptableDataItemError{
  163. CBORType: cborTypeTag.String(),
  164. Message: "bignum",
  165. }
  166. }
  167. if getType(d.data[d.off]) != cborTypeTag {
  168. break
  169. }
  170. if _, _, tagNum, err = d.wellformedHead(); err != nil {
  171. return 0, err
  172. }
  173. depth++
  174. if depth > d.dm.maxNestedLevels {
  175. return 0, &MaxNestedLevelError{d.dm.maxNestedLevels}
  176. }
  177. }
  178. // Check tag content.
  179. return d.wellformedInternal(depth, checkBuiltinTags)
  180. }
  181. return depth, nil
  182. }
  183. // wellformedIndefiniteString checks indefinite length byte/text string's well-formedness and returns max depth and error.
  184. func (d *decoder) wellformedIndefiniteString(t cborType, depth int, checkBuiltinTags bool) (int, error) {
  185. var err error
  186. for {
  187. if len(d.data) == d.off {
  188. return 0, io.ErrUnexpectedEOF
  189. }
  190. if isBreakFlag(d.data[d.off]) {
  191. d.off++
  192. break
  193. }
  194. // Peek ahead to get next type and indefinite length status.
  195. nt, ai := parseInitialByte(d.data[d.off])
  196. if t != nt {
  197. return 0, &SyntaxError{"cbor: wrong element type " + nt.String() + " for indefinite-length " + t.String()}
  198. }
  199. if additionalInformation(ai).isIndefiniteLength() {
  200. return 0, &SyntaxError{"cbor: indefinite-length " + t.String() + " chunk is not definite-length"}
  201. }
  202. if depth, err = d.wellformedInternal(depth, checkBuiltinTags); err != nil {
  203. return 0, err
  204. }
  205. }
  206. return depth, nil
  207. }
  208. // wellformedIndefiniteArrayOrMap checks indefinite length array/map's well-formedness and returns max depth and error.
  209. func (d *decoder) wellformedIndefiniteArrayOrMap(t cborType, depth int, checkBuiltinTags bool) (int, error) {
  210. var err error
  211. maxDepth := depth
  212. i := 0
  213. for {
  214. if len(d.data) == d.off {
  215. return 0, io.ErrUnexpectedEOF
  216. }
  217. if isBreakFlag(d.data[d.off]) {
  218. d.off++
  219. break
  220. }
  221. var dpt int
  222. if dpt, err = d.wellformedInternal(depth, checkBuiltinTags); err != nil {
  223. return 0, err
  224. }
  225. if dpt > maxDepth {
  226. maxDepth = dpt
  227. }
  228. i++
  229. if t == cborTypeArray {
  230. if i > d.dm.maxArrayElements {
  231. return 0, &MaxArrayElementsError{d.dm.maxArrayElements}
  232. }
  233. } else {
  234. if i%2 == 0 && i/2 > d.dm.maxMapPairs {
  235. return 0, &MaxMapPairsError{d.dm.maxMapPairs}
  236. }
  237. }
  238. }
  239. if t == cborTypeMap && i%2 == 1 {
  240. return 0, &SyntaxError{"cbor: unexpected \"break\" code"}
  241. }
  242. return maxDepth, nil
  243. }
  244. func (d *decoder) wellformedHeadWithIndefiniteLengthFlag() (
  245. t cborType,
  246. ai byte,
  247. val uint64,
  248. indefiniteLength bool,
  249. err error,
  250. ) {
  251. t, ai, val, err = d.wellformedHead()
  252. if err != nil {
  253. return
  254. }
  255. indefiniteLength = additionalInformation(ai).isIndefiniteLength()
  256. return
  257. }
  258. func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error) {
  259. dataLen := len(d.data) - d.off
  260. if dataLen == 0 {
  261. return 0, 0, 0, io.ErrUnexpectedEOF
  262. }
  263. t, ai = parseInitialByte(d.data[d.off])
  264. val = uint64(ai)
  265. d.off++
  266. dataLen--
  267. if ai <= maxAdditionalInformationWithoutArgument {
  268. return t, ai, val, nil
  269. }
  270. if ai == additionalInformationWith1ByteArgument {
  271. const argumentSize = 1
  272. if dataLen < argumentSize {
  273. return 0, 0, 0, io.ErrUnexpectedEOF
  274. }
  275. val = uint64(d.data[d.off])
  276. d.off++
  277. if t == cborTypePrimitives && val < 32 {
  278. return 0, 0, 0, &SyntaxError{"cbor: invalid simple value " + strconv.Itoa(int(val)) + " for type " + t.String()}
  279. }
  280. return t, ai, val, nil
  281. }
  282. if ai == additionalInformationWith2ByteArgument {
  283. const argumentSize = 2
  284. if dataLen < argumentSize {
  285. return 0, 0, 0, io.ErrUnexpectedEOF
  286. }
  287. val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+argumentSize]))
  288. d.off += argumentSize
  289. if t == cborTypePrimitives {
  290. if err := d.acceptableFloat(float64(float16.Frombits(uint16(val)).Float32())); err != nil {
  291. return 0, 0, 0, err
  292. }
  293. }
  294. return t, ai, val, nil
  295. }
  296. if ai == additionalInformationWith4ByteArgument {
  297. const argumentSize = 4
  298. if dataLen < argumentSize {
  299. return 0, 0, 0, io.ErrUnexpectedEOF
  300. }
  301. val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+argumentSize]))
  302. d.off += argumentSize
  303. if t == cborTypePrimitives {
  304. if err := d.acceptableFloat(float64(math.Float32frombits(uint32(val)))); err != nil {
  305. return 0, 0, 0, err
  306. }
  307. }
  308. return t, ai, val, nil
  309. }
  310. if ai == additionalInformationWith8ByteArgument {
  311. const argumentSize = 8
  312. if dataLen < argumentSize {
  313. return 0, 0, 0, io.ErrUnexpectedEOF
  314. }
  315. val = binary.BigEndian.Uint64(d.data[d.off : d.off+argumentSize])
  316. d.off += argumentSize
  317. if t == cborTypePrimitives {
  318. if err := d.acceptableFloat(math.Float64frombits(val)); err != nil {
  319. return 0, 0, 0, err
  320. }
  321. }
  322. return t, ai, val, nil
  323. }
  324. if additionalInformation(ai).isIndefiniteLength() {
  325. switch t {
  326. case cborTypePositiveInt, cborTypeNegativeInt, cborTypeTag:
  327. return 0, 0, 0, &SyntaxError{"cbor: invalid additional information " + strconv.Itoa(int(ai)) + " for type " + t.String()}
  328. case cborTypePrimitives: // 0xff (break code) should not be outside wellformedIndefinite().
  329. return 0, 0, 0, &SyntaxError{"cbor: unexpected \"break\" code"}
  330. }
  331. return t, ai, val, nil
  332. }
  333. // ai == 28, 29, 30
  334. return 0, 0, 0, &SyntaxError{"cbor: invalid additional information " + strconv.Itoa(int(ai)) + " for type " + t.String()}
  335. }
  336. func (d *decoder) acceptableFloat(f float64) error {
  337. switch {
  338. case d.dm.nanDec == NaNDecodeForbidden && math.IsNaN(f):
  339. return &UnacceptableDataItemError{
  340. CBORType: cborTypePrimitives.String(),
  341. Message: "floating-point NaN",
  342. }
  343. case d.dm.infDec == InfDecodeForbidden && math.IsInf(f, 0):
  344. return &UnacceptableDataItemError{
  345. CBORType: cborTypePrimitives.String(),
  346. Message: "floating-point infinity",
  347. }
  348. }
  349. return nil
  350. }