length.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package ber
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. )
  7. func readLength(reader io.Reader) (length int, read int, err error) {
  8. // length byte
  9. b, err := readByte(reader)
  10. if err != nil {
  11. if Debug {
  12. fmt.Printf("error reading length byte: %v\n", err)
  13. }
  14. return 0, 0, err
  15. }
  16. read++
  17. switch {
  18. case b == 0xFF:
  19. // Invalid 0xFF (x.600, 8.1.3.5.c)
  20. return 0, read, errors.New("invalid length byte 0xff")
  21. case b == LengthLongFormBitmask:
  22. // Indefinite form, we have to decode packets until we encounter an EOC packet (x.600, 8.1.3.6)
  23. length = LengthIndefinite
  24. case b&LengthLongFormBitmask == 0:
  25. // Short definite form, extract the length from the bottom 7 bits (x.600, 8.1.3.4)
  26. length = int(b) & LengthValueBitmask
  27. case b&LengthLongFormBitmask != 0:
  28. // Long definite form, extract the number of length bytes to follow from the bottom 7 bits (x.600, 8.1.3.5.b)
  29. lengthBytes := int(b) & LengthValueBitmask
  30. // Protect against overflow
  31. // TODO: support big int length?
  32. if lengthBytes > 8 {
  33. return 0, read, errors.New("long-form length overflow")
  34. }
  35. for i := 0; i < lengthBytes; i++ {
  36. b, err = readByte(reader)
  37. if err != nil {
  38. if Debug {
  39. fmt.Printf("error reading long-form length byte %d: %v\n", i, err)
  40. }
  41. return 0, read, err
  42. }
  43. read++
  44. // x.600, 8.1.3.5
  45. length <<= 8
  46. length |= int(b)
  47. }
  48. default:
  49. return 0, read, errors.New("invalid length byte")
  50. }
  51. return length, read, nil
  52. }
  53. func encodeLength(length int) []byte {
  54. length_bytes := encodeUnsignedInteger(uint64(length))
  55. if length > 127 || len(length_bytes) > 1 {
  56. longFormBytes := []byte{(LengthLongFormBitmask | byte(len(length_bytes)))}
  57. longFormBytes = append(longFormBytes, length_bytes...)
  58. length_bytes = longFormBytes
  59. }
  60. return length_bytes
  61. }