github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/ber/decoder.go (about)

     1  package ber
     2  
     3  import (
     4  	"bufio"
     5  	"io"
     6  )
     7  
     8  type Decoder struct {
     9  	base io.Reader
    10  	r    *bufio.Reader
    11  
    12  	stack    *stack
    13  	nextByte int
    14  }
    15  
    16  type stack struct {
    17  	open    []*Token
    18  	closeat []int
    19  }
    20  
    21  func (s *stack) pop() (*Token, error) {
    22  	if len(s.open) == 0 {
    23  		return nil, SyntaxError{"no types unfinished"}
    24  	}
    25  
    26  	last := len(s.closeat) - 1
    27  	t := s.open[last]
    28  	s.open, s.closeat = s.open[:last], s.closeat[:last]
    29  	return t, nil
    30  }
    31  
    32  func (s *stack) push(t *Token, end int) {
    33  	s.open = append(s.open, t)
    34  	s.closeat = append(s.closeat, end)
    35  }
    36  
    37  // closes type with indefinite length
    38  func (s *stack) popIndefiniteEnd() (*Token, error) {
    39  	if len(s.open) == 0 {
    40  		return nil, SyntaxError{"no types unfinished"}
    41  	}
    42  	last := len(s.closeat) - 1
    43  	if s.closeat[last] != 0 {
    44  		return nil, SyntaxError{"unclosed type is definite"}
    45  	}
    46  	return s.pop()
    47  }
    48  
    49  func (s *stack) pushEnd(t *Token, cur int, h header) {
    50  	if h.indefinite {
    51  		s.push(t, 0)
    52  	} else {
    53  		s.push(t, cur+h.length)
    54  	}
    55  }
    56  
    57  func (s *stack) tryPop(at int) (bool, *Token, error) {
    58  	// no open types
    59  	if len(s.open) == 0 {
    60  		return false, nil, nil
    61  	}
    62  	last := len(s.closeat) - 1
    63  	next := s.closeat[last]
    64  	switch {
    65  	case next == 0: // indefinite
    66  		return false, nil, nil
    67  	case next == at:
    68  		t, err := s.pop()
    69  		return true, t, err
    70  	case next > at:
    71  		return false, nil, SyntaxError{"read past end of previous type"}
    72  	}
    73  	return false, nil, nil
    74  }
    75  
    76  func NewDecoder(r io.Reader) *Decoder {
    77  	return &Decoder{
    78  		base:     r,
    79  		r:        bufio.NewReader(r),
    80  		stack:    &stack{},
    81  		nextByte: 0,
    82  	}
    83  }
    84  
    85  func (d *Decoder) readByte() (byte, error) {
    86  	d.nextByte += 1
    87  	return d.r.ReadByte()
    88  }
    89  
    90  func (d *Decoder) readFull(data []byte) error {
    91  	n, err := io.ReadFull(d.r, data)
    92  	d.nextByte += n
    93  	return err
    94  }
    95  
    96  // Returns the next token in the input stream. At the end of the input stream, Token returns nil, io.EOF.
    97  func (d *Decoder) Token() (t *Token, err error) {
    98  	var ok bool
    99  	if ok, t, err = d.stack.tryPop(d.nextByte); ok {
   100  		return
   101  	}
   102  
   103  	var h header
   104  	if h, err = d.nextHeader(); err != nil {
   105  		return
   106  	}
   107  
   108  	// closing an indefinite length
   109  	if h.class == 0 && h.tag == TagEOC && h.length == 0 {
   110  		return d.stack.popIndefiniteEnd()
   111  	}
   112  
   113  	if h.constructed {
   114  		t = &Token{Constructed, h.class, h.tag, nil}
   115  		d.stack.pushEnd(&Token{EndConstructed, h.class, h.tag, nil}, d.nextByte, h)
   116  		return
   117  	}
   118  
   119  	if h.indefinite {
   120  		err = StructuralError{"indefinite primitive"}
   121  		return
   122  	}
   123  
   124  	buf := make([]byte, h.length)
   125  	if err = d.readFull(buf); err != nil {
   126  		return
   127  	}
   128  
   129  	t = &Token{Value, h.class, h.tag, buf}
   130  	return
   131  }
   132  
   133  func (d *Decoder) skipUntilEnd() (skipped bool, err error) {
   134  	var t *Token
   135  	for err != nil {
   136  		t, err = d.Token()
   137  		switch t.Kind {
   138  		case Constructed:
   139  			skipped = true
   140  			// recurse
   141  			_, err = d.skipUntilEnd()
   142  		case Value:
   143  			skipped = true
   144  			// grab the next one
   145  			t, err = d.Token()
   146  		case EndConstructed:
   147  			// finished
   148  			return
   149  		}
   150  	}
   151  	return
   152  }
   153  
   154  // readBase128Int parses a base-128 encoded int from the given offset in the
   155  // given byte slice. It returns the value and the new offset.
   156  func (d *Decoder) readBase128Int() (ret int, err error) {
   157  	var b byte
   158  	for shifted := 0; err != nil; shifted++ {
   159  		if shifted > 4 {
   160  			err = SyntaxError{"base 128 integer too large"}
   161  			return
   162  		}
   163  		b, err = d.readByte()
   164  		ret <<= 7
   165  		ret |= int(b & 0x7f)
   166  		if b&0x80 == 0 {
   167  			return
   168  		}
   169  	}
   170  	err = SyntaxError{"truncated base 128 integer"}
   171  	return
   172  }
   173  
   174  type header struct {
   175  	class       int
   176  	tag         int
   177  	length      int
   178  	constructed bool
   179  	indefinite  bool
   180  }
   181  
   182  func (d *Decoder) nextHeader() (ret header, err error) {
   183  	var b byte
   184  	b, err = d.readByte()
   185  
   186  	ret.class = int(b >> 6)
   187  	ret.constructed = b&0x20 == 0x20
   188  	ret.tag = int(b & 0x1f)
   189  
   190  	// If the bottom five bits are set, then the tag number is actually base 128
   191  	// encoded afterwards
   192  	if ret.tag == 0x1f {
   193  		ret.tag, err = d.readBase128Int()
   194  		if err != nil {
   195  			return
   196  		}
   197  	}
   198  
   199  	if b, err = d.readByte(); err != nil {
   200  		return
   201  	}
   202  
   203  	if b&0x80 == 0 {
   204  		// The length is encoded in the bottom 7 bits
   205  		ret.length = int(b & 0x7f)
   206  	} else {
   207  		numBytes := int(b & 0x7f)
   208  		if numBytes == 0 {
   209  			ret.indefinite = true
   210  			return
   211  		}
   212  
   213  		for i := 0; i < numBytes; i++ {
   214  			if b, err = d.readByte(); err != nil {
   215  				return
   216  			}
   217  
   218  			if ret.length >= 1<<23 {
   219  				// We can't shift ret.length up without
   220  				// overflowing.
   221  				err = SyntaxError{"length too large"}
   222  				return
   223  			}
   224  			ret.length <<= 8
   225  			ret.length |= int(b)
   226  			if ret.length == 0 {
   227  				// is this required by BER?
   228  				// DER requires that lengths be minimal.
   229  				err = SyntaxError{"superfluous leading zeros in length"}
   230  				return
   231  			}
   232  		}
   233  	}
   234  
   235  	return
   236  }