...

Source file src/github.com/go-asn1-ber/asn1-ber/length.go

Documentation: github.com/go-asn1-ber/asn1-ber

     1  package ber
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  )
     8  
     9  func 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, unexpectedEOF(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, unexpectedEOF(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  
    73  func 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  

View as plain text