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