decode_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. package wire
  2. import (
  3. "bytes"
  4. "io"
  5. "testing"
  6. "github.com/stretchr/testify/assert"
  7. )
  8. func TestUnmarshal(t *testing.T) {
  9. tests := []struct {
  10. name string
  11. prototype any
  12. given []byte
  13. want any
  14. wantErr error
  15. }{
  16. {
  17. name: "uint8",
  18. prototype: &struct {
  19. Val uint8
  20. }{},
  21. want: &struct {
  22. Val uint8
  23. }{
  24. Val: 100,
  25. },
  26. given: []byte{0x64},
  27. },
  28. {
  29. name: "uint8 with read error",
  30. prototype: &struct {
  31. Val uint8
  32. }{},
  33. wantErr: io.EOF,
  34. given: []byte{},
  35. },
  36. {
  37. name: "uint16",
  38. prototype: &struct {
  39. Val uint16
  40. }{},
  41. want: &struct {
  42. Val uint16
  43. }{
  44. Val: 100,
  45. },
  46. given: []byte{0x0, 0x64},
  47. },
  48. {
  49. name: "uint16 with read error",
  50. prototype: &struct {
  51. Val uint16
  52. }{},
  53. wantErr: io.EOF,
  54. given: []byte{},
  55. },
  56. {
  57. name: "uint32",
  58. prototype: &struct {
  59. Val uint32
  60. }{},
  61. want: &struct {
  62. Val uint32
  63. }{
  64. Val: 100,
  65. },
  66. given: []byte{0x0, 0x0, 0x0, 0x64},
  67. },
  68. {
  69. name: "uint32 with read error",
  70. prototype: &struct {
  71. Val uint32
  72. }{},
  73. wantErr: io.EOF,
  74. given: []byte{},
  75. },
  76. {
  77. name: "uint64",
  78. prototype: &struct {
  79. Val uint64
  80. }{},
  81. want: &struct {
  82. Val uint64
  83. }{
  84. Val: 100,
  85. },
  86. given: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64},
  87. },
  88. {
  89. name: "uint64 with read error",
  90. prototype: &struct {
  91. Val uint64
  92. }{},
  93. wantErr: io.EOF,
  94. given: []byte{},
  95. },
  96. {
  97. name: "string8",
  98. prototype: &struct {
  99. Val string `oscar:"len_prefix=uint8"`
  100. }{},
  101. want: &struct {
  102. Val string `oscar:"len_prefix=uint8"`
  103. }{
  104. Val: "test-value",
  105. },
  106. given: append(
  107. []byte{0xa}, /* len prefix */
  108. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  109. },
  110. {
  111. name: "string8 read error",
  112. prototype: &struct {
  113. Val string `oscar:"len_prefix=uint8"`
  114. }{},
  115. given: []byte{},
  116. wantErr: io.EOF,
  117. },
  118. {
  119. name: "string16",
  120. prototype: &struct {
  121. Val string `oscar:"len_prefix=uint16"`
  122. }{},
  123. want: &struct {
  124. Val string `oscar:"len_prefix=uint16"`
  125. }{
  126. Val: "test-value",
  127. },
  128. given: append(
  129. []byte{0x0, 0xa}, /* len prefix */
  130. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  131. },
  132. {
  133. name: "null-terminated string16",
  134. prototype: &struct {
  135. Val string `oscar:"len_prefix=uint16,nullterm"`
  136. }{},
  137. want: &struct {
  138. Val string `oscar:"len_prefix=uint16,nullterm"`
  139. }{
  140. Val: "test-value",
  141. },
  142. given: append(
  143. []byte{0x0, 0xb}, /* len prefix */
  144. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x00}...), /* str val */
  145. },
  146. {
  147. name: "null-terminated string16 with len 0",
  148. prototype: &struct {
  149. Val string `oscar:"len_prefix=uint16,nullterm"`
  150. }{},
  151. want: &struct {
  152. Val string `oscar:"len_prefix=uint16,nullterm"`
  153. }{
  154. Val: "",
  155. },
  156. given: []byte{0x0, 0x00}, /* len prefix */
  157. },
  158. {
  159. name: "null-terminated string16 without null terminator",
  160. prototype: &struct {
  161. Val string `oscar:"len_prefix=uint16,nullterm"`
  162. }{},
  163. want: &struct {
  164. Val string `oscar:"len_prefix=uint16,nullterm"`
  165. }{
  166. Val: "test-value",
  167. },
  168. given: append(
  169. []byte{0x0, 0xa}, /* len prefix */
  170. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  171. },
  172. {
  173. name: "null-terminated string16 with null in middle",
  174. prototype: &struct {
  175. Val string `oscar:"len_prefix=uint16,nullterm"`
  176. }{},
  177. want: &struct {
  178. Val string `oscar:"len_prefix=uint16,nullterm"`
  179. }{
  180. Val: "test",
  181. },
  182. given: append(
  183. []byte{0x0, 0xf}, /* len prefix = 15 bytes */
  184. []byte{0x74, 0x65, 0x73, 0x74, 0x00, 0x6d, 0x6f, 0x72, 0x65, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x21}...), /* "test\0more-data!" */
  185. },
  186. {
  187. name: "string16 read error",
  188. prototype: &struct {
  189. Val string `oscar:"len_prefix=uint16"`
  190. }{},
  191. given: []byte{},
  192. wantErr: io.EOF,
  193. },
  194. {
  195. name: "unsupported string prefix type",
  196. prototype: &struct {
  197. Val string `oscar:"len_prefix=uint128"`
  198. }{},
  199. wantErr: ErrUnmarshalFailure,
  200. given: append(
  201. []byte{0x0, 0xa}, /* len prefix */
  202. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  203. },
  204. {
  205. name: "string with missing len_prefix",
  206. prototype: &struct {
  207. Val string
  208. }{},
  209. wantErr: ErrUnmarshalFailure,
  210. given: append(
  211. []byte{0x0, 0xa}, /* len prefix */
  212. []byte{0x74, 0x65, 0x73, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65}...), /* str val */
  213. },
  214. {
  215. name: "partial string8",
  216. prototype: &struct {
  217. Val string `oscar:"len_prefix=uint8"`
  218. }{},
  219. wantErr: io.EOF,
  220. given: append(
  221. []byte{0xa}, /* len prefix */
  222. []byte{}...), /* truncated payload */
  223. },
  224. {
  225. name: "byte slice with uint8 len_prefix",
  226. prototype: &struct {
  227. Val []byte `oscar:"len_prefix=uint8"`
  228. }{},
  229. want: &struct {
  230. Val []byte `oscar:"len_prefix=uint8"`
  231. }{
  232. Val: []byte(`hello`),
  233. },
  234. given: append(
  235. []byte{0x05}, /* len prefix */
  236. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  237. },
  238. {
  239. name: "slice of invalid type with uint8 len_prefix",
  240. prototype: &struct {
  241. Val []int `oscar:"len_prefix=uint8"`
  242. }{},
  243. wantErr: ErrUnmarshalFailure,
  244. given: []byte{0x04, 0x65, 0x6c, 0x6c, 0x6f},
  245. },
  246. {
  247. name: "byte slice with uint8 len_prefix with read error",
  248. prototype: &struct {
  249. Val []byte `oscar:"len_prefix=uint8"`
  250. }{},
  251. wantErr: io.EOF,
  252. given: append(
  253. []byte{0x05}, /* len prefix */
  254. []byte{}...), /* slice val */
  255. },
  256. {
  257. name: "byte slice with uint8 len_prefix read error",
  258. prototype: &struct {
  259. Val []byte `oscar:"len_prefix=uint8"`
  260. }{},
  261. wantErr: io.EOF,
  262. given: []byte{},
  263. },
  264. {
  265. name: "byte slice with uint16 len_prefix",
  266. prototype: &struct {
  267. Val []byte `oscar:"len_prefix=uint16"`
  268. }{},
  269. want: &struct {
  270. Val []byte `oscar:"len_prefix=uint16"`
  271. }{
  272. Val: []byte(`hello`),
  273. },
  274. given: append(
  275. []byte{0x00, 0x05}, /* len prefix */
  276. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  277. },
  278. {
  279. name: "byte slice with uint16 len_prefix read error",
  280. prototype: &struct {
  281. Val []byte `oscar:"len_prefix=uint16"`
  282. }{},
  283. wantErr: io.EOF,
  284. given: []byte{},
  285. },
  286. {
  287. name: "byte slice with invalid len_prefix",
  288. prototype: &struct {
  289. Val []byte `oscar:"len_prefix=uint128"`
  290. }{},
  291. wantErr: ErrUnmarshalFailure,
  292. given: append(
  293. []byte{0x00, 0x05}, /* len prefix */
  294. []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f}...), /* slice val */
  295. },
  296. {
  297. name: "struct slice without prefix",
  298. prototype: &struct {
  299. Val []TLV
  300. }{},
  301. want: &struct {
  302. Val []TLV
  303. }{
  304. Val: []TLV{
  305. NewTLVBE(10, uint16(1234)),
  306. NewTLVBE(20, uint16(1234)),
  307. },
  308. },
  309. given: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2},
  310. },
  311. {
  312. name: "slice of unsupported type without prefix",
  313. prototype: &struct {
  314. Val []int
  315. }{},
  316. wantErr: ErrUnmarshalFailure,
  317. given: []byte{0x0, 0xa, 0x0, 0x2},
  318. },
  319. {
  320. name: "struct slice with uint8 count_prefix",
  321. prototype: &struct {
  322. Val []TLV `oscar:"count_prefix=uint8"`
  323. }{},
  324. want: &struct {
  325. Val []TLV `oscar:"count_prefix=uint8"`
  326. }{
  327. Val: []TLV{
  328. NewTLVBE(10, uint16(1234)),
  329. NewTLVBE(20, uint16(1234)),
  330. },
  331. },
  332. given: append(
  333. []byte{0x02}, /* count prefix */
  334. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  335. },
  336. {
  337. name: "struct slice with uint8 count_prefix and unsupported type",
  338. prototype: &struct {
  339. Val []struct {
  340. Val int16
  341. } `oscar:"count_prefix=uint8"`
  342. }{},
  343. wantErr: ErrUnmarshalFailure,
  344. given: append(
  345. []byte{0x02}, /* count prefix */
  346. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  347. },
  348. {
  349. name: "struct slice with uint8 count_prefix read error",
  350. prototype: &struct {
  351. Val []TLV `oscar:"count_prefix=uint8"`
  352. }{},
  353. wantErr: io.EOF,
  354. given: []byte{},
  355. },
  356. {
  357. name: "struct slice with uint16 count_prefix",
  358. prototype: &struct {
  359. Val []TLV `oscar:"count_prefix=uint16"`
  360. }{},
  361. want: &struct {
  362. Val []TLV `oscar:"count_prefix=uint16"`
  363. }{
  364. Val: []TLV{
  365. NewTLVBE(10, uint16(1234)),
  366. NewTLVBE(20, uint16(1234)),
  367. },
  368. },
  369. given: append(
  370. []byte{0x0, 0x02}, /* count prefix */
  371. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  372. },
  373. {
  374. name: "struct slice with uint16 count_prefix and unsupported type",
  375. prototype: &struct {
  376. Val []struct {
  377. Val int16
  378. } `oscar:"count_prefix=uint16"`
  379. }{},
  380. wantErr: ErrUnmarshalFailure,
  381. given: append(
  382. []byte{0x0, 0x02}, /* count prefix */
  383. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  384. },
  385. {
  386. name: "struct slice with uint16 count_prefix read error",
  387. prototype: &struct {
  388. Val []TLV `oscar:"count_prefix=uint16"`
  389. }{},
  390. wantErr: io.EOF,
  391. given: []byte{},
  392. },
  393. {
  394. name: "struct slice with invalid count_prefix",
  395. prototype: &struct {
  396. Val []TLV `oscar:"count_prefix=uint128"`
  397. }{},
  398. wantErr: ErrUnmarshalFailure,
  399. given: append(
  400. []byte{0x0, 0x02}, /* count prefix */
  401. []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}...), /* slice val */
  402. },
  403. {
  404. name: "struct with uint8 len_prefix",
  405. prototype: &struct {
  406. Val0 uint8
  407. Val1 struct {
  408. Val2 uint16
  409. Val3 uint8
  410. } `oscar:"len_prefix=uint8"`
  411. Val4 uint16
  412. }{},
  413. want: &struct {
  414. Val0 uint8
  415. Val1 struct {
  416. Val2 uint16
  417. Val3 uint8
  418. } `oscar:"len_prefix=uint8"`
  419. Val4 uint16
  420. }{
  421. Val0: 34,
  422. Val1: struct {
  423. Val2 uint16
  424. Val3 uint8
  425. }{
  426. Val2: 16,
  427. Val3: 10,
  428. },
  429. Val4: 32,
  430. },
  431. given: []byte{
  432. 0x22, // Val0
  433. 0x03, // Val1 struct len
  434. 0x00, 0x10, // Val2
  435. 0x0A, // Val3
  436. 0x00, 0x20, // Val2
  437. },
  438. },
  439. {
  440. name: "struct with uint16 len_prefix",
  441. prototype: &struct {
  442. Val0 uint8
  443. Val1 struct {
  444. Val2 uint16
  445. Val3 uint8
  446. } `oscar:"len_prefix=uint16"`
  447. Val4 uint16
  448. }{},
  449. want: &struct {
  450. Val0 uint8
  451. Val1 struct {
  452. Val2 uint16
  453. Val3 uint8
  454. } `oscar:"len_prefix=uint16"`
  455. Val4 uint16
  456. }{
  457. Val0: 34,
  458. Val1: struct {
  459. Val2 uint16
  460. Val3 uint8
  461. }{
  462. Val2: 16,
  463. Val3: 10,
  464. },
  465. Val4: 32,
  466. },
  467. given: []byte{
  468. 0x22, // Val0
  469. 0x00, 0x03, // Val1 struct len
  470. 0x00, 0x10, // Val2
  471. 0x0A, // Val3
  472. 0x00, 0x20, // Val2
  473. },
  474. },
  475. {
  476. name: "struct with uint16 len_prefix with read error",
  477. prototype: &struct {
  478. Val1 struct {
  479. Val2 uint16
  480. } `oscar:"len_prefix=uint16"`
  481. }{},
  482. given: []byte{
  483. 0x00, 0x10, // 16 byte len, but the body is truncated
  484. },
  485. wantErr: io.EOF,
  486. },
  487. {
  488. name: "struct with unknown len_prefix",
  489. prototype: &struct {
  490. Val1 struct {
  491. Val2 uint16
  492. } `oscar:"len_prefix=uint128"`
  493. }{},
  494. wantErr: ErrUnmarshalFailure,
  495. },
  496. {
  497. name: "optional struct has value",
  498. prototype: &struct {
  499. Val0 uint16
  500. Optional *struct {
  501. Val1 uint16
  502. } `oscar:"optional"`
  503. }{},
  504. want: &struct {
  505. Val0 uint16
  506. Optional *struct {
  507. Val1 uint16
  508. } `oscar:"optional"`
  509. }{
  510. Val0: 34,
  511. Optional: &struct {
  512. Val1 uint16
  513. }{
  514. Val1: 100,
  515. },
  516. },
  517. given: []byte{
  518. 0x00, 0x22, // Val0
  519. 0x00, 0x64, // Val1
  520. },
  521. },
  522. {
  523. name: "optional struct with value missing `optional` struct tag",
  524. prototype: &struct {
  525. Val0 uint16
  526. Optional *struct {
  527. Val1 uint16
  528. }
  529. }{},
  530. given: []byte{
  531. 0x00, 0x22, // Val0
  532. 0x00, 0x64, // Val1
  533. },
  534. wantErr: ErrUnmarshalFailure,
  535. },
  536. {
  537. name: "optional struct doesn't have value",
  538. prototype: &struct {
  539. Val0 uint16
  540. Optional *struct {
  541. Val1 uint16
  542. } `oscar:"optional"`
  543. }{},
  544. want: &struct {
  545. Val0 uint16
  546. Optional *struct {
  547. Val1 uint16
  548. } `oscar:"optional"`
  549. }{
  550. Val0: 34,
  551. Optional: nil,
  552. },
  553. given: []byte{
  554. 0x00, 0x22, // Val0
  555. },
  556. },
  557. {
  558. name: "optional struct followed by value throws error",
  559. prototype: &struct {
  560. Optional *struct {
  561. Val0 uint16
  562. } `oscar:"optional"`
  563. Val1 uint16
  564. }{},
  565. wantErr: ErrUnmarshalFailure,
  566. given: []byte{
  567. 0x00, 0x22, // Val0
  568. 0x00, 0x22, // Val1
  569. },
  570. },
  571. {
  572. name: "optional non-struct field throws error",
  573. prototype: &struct {
  574. Optional *uint16 `oscar:"optional"`
  575. }{},
  576. wantErr: ErrUnmarshalFailure,
  577. given: []byte{
  578. 0x00, 0x22, // Val0
  579. },
  580. },
  581. {
  582. name: "non-struct pointer value throws error",
  583. prototype: func() any {
  584. val := 10
  585. ptr1 := &val
  586. return &ptr1
  587. }(),
  588. wantErr: ErrUnmarshalFailure,
  589. given: []byte{
  590. 0x00, 0x22, // Val0
  591. },
  592. },
  593. {
  594. name: "optional struct with uint16 len_prefix and value",
  595. prototype: &struct {
  596. Val0 uint8
  597. Val1 *struct {
  598. Val2 uint16
  599. Val3 uint8
  600. } `oscar:"len_prefix=uint16,optional"`
  601. }{},
  602. want: &struct {
  603. Val0 uint8
  604. Val1 *struct {
  605. Val2 uint16
  606. Val3 uint8
  607. } `oscar:"len_prefix=uint16,optional"`
  608. }{
  609. Val0: 34,
  610. Val1: &struct {
  611. Val2 uint16
  612. Val3 uint8
  613. }{
  614. Val2: 16,
  615. Val3: 10,
  616. },
  617. },
  618. given: []byte{
  619. 0x22, // Val0
  620. 0x00, 0x03, // Val1 struct len
  621. 0x00, 0x10, // Val2
  622. 0x0A, // Val3
  623. 0x00, 0x20, // Val2
  624. },
  625. },
  626. {
  627. name: "optional struct with uint16 len_prefix and no value",
  628. prototype: &struct {
  629. Val0 uint8
  630. Val1 *struct {
  631. Val2 uint16
  632. Val3 uint8
  633. } `oscar:"len_prefix=uint16,optional"`
  634. }{},
  635. want: &struct {
  636. Val0 uint8
  637. Val1 *struct {
  638. Val2 uint16
  639. Val3 uint8
  640. } `oscar:"len_prefix=uint16,optional"`
  641. }{
  642. Val0: 34,
  643. Val1: nil,
  644. },
  645. given: []byte{
  646. 0x22, // Val0
  647. },
  648. },
  649. {
  650. name: "optional field that isn't a pointer to a struct is unsupported",
  651. prototype: &struct {
  652. Val1 *string `oscar:"optional"`
  653. }{},
  654. given: []byte{
  655. 0x00,
  656. },
  657. wantErr: errNonOptionalPointer,
  658. },
  659. {
  660. name: "byte array",
  661. prototype: &struct {
  662. Val [5]byte
  663. }{},
  664. want: &struct {
  665. Val [5]byte
  666. }{
  667. Val: [5]byte{'h', 'e', 'l', 'l', 'o'},
  668. },
  669. given: []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f},
  670. },
  671. {
  672. name: "array of invalid type",
  673. prototype: &struct {
  674. Val [5]int
  675. }{},
  676. wantErr: ErrUnmarshalFailure,
  677. given: []byte{1, 2, 3, 4, 5},
  678. },
  679. {
  680. name: "struct array",
  681. prototype: &struct {
  682. Val [2]TLV
  683. }{},
  684. want: &struct {
  685. Val [2]TLV
  686. }{
  687. Val: [2]TLV{
  688. NewTLVBE(10, uint16(1234)),
  689. NewTLVBE(20, uint16(1234)),
  690. },
  691. },
  692. given: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2},
  693. },
  694. }
  695. for _, tt := range tests {
  696. t.Run(tt.name, func(t *testing.T) {
  697. r := bytes.NewBuffer(tt.given)
  698. err := UnmarshalBE(tt.prototype, r)
  699. assert.ErrorIs(t, err, tt.wantErr)
  700. if tt.wantErr == nil {
  701. assert.Equal(t, tt.want, tt.prototype)
  702. }
  703. })
  704. }
  705. }
  706. // TestUnmarshalLE_ICQ2003bSaveInfoEmailTLVLengthQuirk checks ICQ 2003b "save info" / META
  707. // CLI_SET_FULLINFO: INF_TLV_EMAIL (ICQTLVTagsEmail, 0x015E) declares length 3 but writes 4 bytes
  708. // on the wire; unmarshal with oscar:"quirk=icq2003b_set_fullinfo"
  709. func TestUnmarshalLE_ICQ2003bSaveInfoEmailTLVLengthQuirk(t *testing.T) {
  710. b := []byte{
  711. 0x5E, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, // ICQTLVTagsEmail: LE len 3, 4 bytes on wire
  712. 0x58, 0x02, 0x02, 0x00, 0x00, 0x00, // ICQTLVTagsNotesText (0x0258), LE len 2
  713. }
  714. var got ICQ_0x07D0_0x0C3A_DBQueryMetaReqSetFullInfo
  715. err := UnmarshalLE(&got, bytes.NewReader(b))
  716. assert.NoError(t, err)
  717. assert.Len(t, got.TLVList, 2)
  718. assert.Equal(t, ICQTLVTagsEmail, got.TLVList[0].Tag)
  719. assert.Equal(t, []byte{0x01, 0x00, 0x00, 0x00}, got.TLVList[0].Value)
  720. assert.Equal(t, ICQTLVTagsNotesText, got.TLVList[1].Tag)
  721. assert.Equal(t, []byte{0x00, 0x00}, got.TLVList[1].Value)
  722. }
  723. // TestUnmarshalLE_QIP2005SearchByUIN2TLVLengthQuirk checks QIP 2005 META SearchByUIN2: TLV ICQTLVTagsUIN
  724. // declares length 6 but only 4 bytes (UIN) follow; unmarshal with oscar:"quirk=qip_2005_search_by_uin2"
  725. func TestUnmarshalLE_QIP2005SearchByUIN2TLVLengthQuirk(t *testing.T) {
  726. b := []byte{
  727. 0x36, 0x01, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, // ICQTLVTagsUIN: LE len 6 (wrong), 4-byte UIN on wire
  728. }
  729. var got ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2
  730. err := UnmarshalLE(&got, bytes.NewReader(b))
  731. assert.NoError(t, err)
  732. assert.Len(t, got.TLVList, 1)
  733. assert.Equal(t, ICQTLVTagsUIN, got.TLVList[0].Tag)
  734. assert.Equal(t, []byte{0x01, 0x00, 0x00, 0x00}, got.TLVList[0].Value)
  735. }
  736. // TestUnmarshalBE_JimmSetInfoTLVLengthQuirk checks that UnmarshalBE gracefully
  737. // handles SNAC_0x02_0x04_LocateSetInfo with TLV 0x05 containing length param
  738. // that exceeds value length.
  739. func TestUnmarshalBE_JimmSetInfoTLVLengthQuirk(t *testing.T) {
  740. b := []byte{
  741. 0x0, 0x5,
  742. 0x0, 0x4, // TLV len 4 exceeds value length 3
  743. 0x1, 0x2, 0x3,
  744. }
  745. var got SNAC_0x02_0x04_LocateSetInfo
  746. err := UnmarshalBE(&got, bytes.NewReader(b))
  747. assert.NoError(t, err)
  748. assert.Len(t, got.TLVList, 1)
  749. assert.Equal(t, uint16(5), got.TLVList[0].Tag)
  750. assert.Equal(t, []byte{0x1, 0x2, 0x3}, got.TLVList[0].Value)
  751. }