builder.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // Copyright 2017 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package cryptobyte
  5. import (
  6. "errors"
  7. "fmt"
  8. )
  9. // A Builder builds byte strings from fixed-length and length-prefixed values.
  10. // Builders either allocate space as needed, or are ‘fixed’, which means that
  11. // they write into a given buffer and produce an error if it's exhausted.
  12. //
  13. // The zero value is a usable Builder that allocates space as needed.
  14. //
  15. // Simple values are marshaled and appended to a Builder using methods on the
  16. // Builder. Length-prefixed values are marshaled by providing a
  17. // BuilderContinuation, which is a function that writes the inner contents of
  18. // the value to a given Builder. See the documentation for BuilderContinuation
  19. // for details.
  20. type Builder struct {
  21. err error
  22. result []byte
  23. fixedSize bool
  24. child *Builder
  25. offset int
  26. pendingLenLen int
  27. pendingIsASN1 bool
  28. inContinuation *bool
  29. }
  30. // NewBuilder creates a Builder that appends its output to the given buffer.
  31. // Like append(), the slice will be reallocated if its capacity is exceeded.
  32. // Use Bytes to get the final buffer.
  33. func NewBuilder(buffer []byte) *Builder {
  34. return &Builder{
  35. result: buffer,
  36. }
  37. }
  38. // NewFixedBuilder creates a Builder that appends its output into the given
  39. // buffer. This builder does not reallocate the output buffer. Writes that
  40. // would exceed the buffer's capacity are treated as an error.
  41. func NewFixedBuilder(buffer []byte) *Builder {
  42. return &Builder{
  43. result: buffer,
  44. fixedSize: true,
  45. }
  46. }
  47. // SetError sets the value to be returned as the error from Bytes. Writes
  48. // performed after calling SetError are ignored.
  49. func (b *Builder) SetError(err error) {
  50. b.err = err
  51. }
  52. // Bytes returns the bytes written by the builder or an error if one has
  53. // occurred during building.
  54. func (b *Builder) Bytes() ([]byte, error) {
  55. if b.err != nil {
  56. return nil, b.err
  57. }
  58. return b.result[b.offset:], nil
  59. }
  60. // BytesOrPanic returns the bytes written by the builder or panics if an error
  61. // has occurred during building.
  62. func (b *Builder) BytesOrPanic() []byte {
  63. if b.err != nil {
  64. panic(b.err)
  65. }
  66. return b.result[b.offset:]
  67. }
  68. // AddUint8 appends an 8-bit value to the byte string.
  69. func (b *Builder) AddUint8(v uint8) {
  70. b.add(byte(v))
  71. }
  72. // AddUint16 appends a big-endian, 16-bit value to the byte string.
  73. func (b *Builder) AddUint16(v uint16) {
  74. b.add(byte(v>>8), byte(v))
  75. }
  76. // AddUint24 appends a big-endian, 24-bit value to the byte string. The highest
  77. // byte of the 32-bit input value is silently truncated.
  78. func (b *Builder) AddUint24(v uint32) {
  79. b.add(byte(v>>16), byte(v>>8), byte(v))
  80. }
  81. // AddUint32 appends a big-endian, 32-bit value to the byte string.
  82. func (b *Builder) AddUint32(v uint32) {
  83. b.add(byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
  84. }
  85. // AddBytes appends a sequence of bytes to the byte string.
  86. func (b *Builder) AddBytes(v []byte) {
  87. b.add(v...)
  88. }
  89. // BuilderContinuation is a continuation-passing interface for building
  90. // length-prefixed byte sequences. Builder methods for length-prefixed
  91. // sequences (AddUint8LengthPrefixed etc) will invoke the BuilderContinuation
  92. // supplied to them. The child builder passed to the continuation can be used
  93. // to build the content of the length-prefixed sequence. For example:
  94. //
  95. // parent := cryptobyte.NewBuilder()
  96. // parent.AddUint8LengthPrefixed(func (child *Builder) {
  97. // child.AddUint8(42)
  98. // child.AddUint8LengthPrefixed(func (grandchild *Builder) {
  99. // grandchild.AddUint8(5)
  100. // })
  101. // })
  102. //
  103. // It is an error to write more bytes to the child than allowed by the reserved
  104. // length prefix. After the continuation returns, the child must be considered
  105. // invalid, i.e. users must not store any copies or references of the child
  106. // that outlive the continuation.
  107. //
  108. // If the continuation panics with a value of type BuildError then the inner
  109. // error will be returned as the error from Bytes. If the child panics
  110. // otherwise then Bytes will repanic with the same value.
  111. type BuilderContinuation func(child *Builder)
  112. // BuildError wraps an error. If a BuilderContinuation panics with this value,
  113. // the panic will be recovered and the inner error will be returned from
  114. // Builder.Bytes.
  115. type BuildError struct {
  116. Err error
  117. }
  118. // AddUint8LengthPrefixed adds a 8-bit length-prefixed byte sequence.
  119. func (b *Builder) AddUint8LengthPrefixed(f BuilderContinuation) {
  120. b.addLengthPrefixed(1, false, f)
  121. }
  122. // AddUint16LengthPrefixed adds a big-endian, 16-bit length-prefixed byte sequence.
  123. func (b *Builder) AddUint16LengthPrefixed(f BuilderContinuation) {
  124. b.addLengthPrefixed(2, false, f)
  125. }
  126. // AddUint24LengthPrefixed adds a big-endian, 24-bit length-prefixed byte sequence.
  127. func (b *Builder) AddUint24LengthPrefixed(f BuilderContinuation) {
  128. b.addLengthPrefixed(3, false, f)
  129. }
  130. // AddUint32LengthPrefixed adds a big-endian, 32-bit length-prefixed byte sequence.
  131. func (b *Builder) AddUint32LengthPrefixed(f BuilderContinuation) {
  132. b.addLengthPrefixed(4, false, f)
  133. }
  134. func (b *Builder) callContinuation(f BuilderContinuation, arg *Builder) {
  135. if !*b.inContinuation {
  136. *b.inContinuation = true
  137. defer func() {
  138. *b.inContinuation = false
  139. r := recover()
  140. if r == nil {
  141. return
  142. }
  143. if buildError, ok := r.(BuildError); ok {
  144. b.err = buildError.Err
  145. } else {
  146. panic(r)
  147. }
  148. }()
  149. }
  150. f(arg)
  151. }
  152. func (b *Builder) addLengthPrefixed(lenLen int, isASN1 bool, f BuilderContinuation) {
  153. // Subsequent writes can be ignored if the builder has encountered an error.
  154. if b.err != nil {
  155. return
  156. }
  157. offset := len(b.result)
  158. b.add(make([]byte, lenLen)...)
  159. if b.inContinuation == nil {
  160. b.inContinuation = new(bool)
  161. }
  162. b.child = &Builder{
  163. result: b.result,
  164. fixedSize: b.fixedSize,
  165. offset: offset,
  166. pendingLenLen: lenLen,
  167. pendingIsASN1: isASN1,
  168. inContinuation: b.inContinuation,
  169. }
  170. b.callContinuation(f, b.child)
  171. b.flushChild()
  172. if b.child != nil {
  173. panic("cryptobyte: internal error")
  174. }
  175. }
  176. func (b *Builder) flushChild() {
  177. if b.child == nil {
  178. return
  179. }
  180. b.child.flushChild()
  181. child := b.child
  182. b.child = nil
  183. if child.err != nil {
  184. b.err = child.err
  185. return
  186. }
  187. length := len(child.result) - child.pendingLenLen - child.offset
  188. if length < 0 {
  189. panic("cryptobyte: internal error") // result unexpectedly shrunk
  190. }
  191. if child.pendingIsASN1 {
  192. // For ASN.1, we reserved a single byte for the length. If that turned out
  193. // to be incorrect, we have to move the contents along in order to make
  194. // space.
  195. if child.pendingLenLen != 1 {
  196. panic("cryptobyte: internal error")
  197. }
  198. var lenLen, lenByte uint8
  199. if int64(length) > 0xfffffffe {
  200. b.err = errors.New("pending ASN.1 child too long")
  201. return
  202. } else if length > 0xffffff {
  203. lenLen = 5
  204. lenByte = 0x80 | 4
  205. } else if length > 0xffff {
  206. lenLen = 4
  207. lenByte = 0x80 | 3
  208. } else if length > 0xff {
  209. lenLen = 3
  210. lenByte = 0x80 | 2
  211. } else if length > 0x7f {
  212. lenLen = 2
  213. lenByte = 0x80 | 1
  214. } else {
  215. lenLen = 1
  216. lenByte = uint8(length)
  217. length = 0
  218. }
  219. // Insert the initial length byte, make space for successive length bytes,
  220. // and adjust the offset.
  221. child.result[child.offset] = lenByte
  222. extraBytes := int(lenLen - 1)
  223. if extraBytes != 0 {
  224. child.add(make([]byte, extraBytes)...)
  225. childStart := child.offset + child.pendingLenLen
  226. copy(child.result[childStart+extraBytes:], child.result[childStart:])
  227. }
  228. child.offset++
  229. child.pendingLenLen = extraBytes
  230. }
  231. l := length
  232. for i := child.pendingLenLen - 1; i >= 0; i-- {
  233. child.result[child.offset+i] = uint8(l)
  234. l >>= 8
  235. }
  236. if l != 0 {
  237. b.err = fmt.Errorf("cryptobyte: pending child length %d exceeds %d-byte length prefix", length, child.pendingLenLen)
  238. return
  239. }
  240. if b.fixedSize && &b.result[0] != &child.result[0] {
  241. panic("cryptobyte: BuilderContinuation reallocated a fixed-size buffer")
  242. }
  243. b.result = child.result
  244. }
  245. func (b *Builder) add(bytes ...byte) {
  246. if b.err != nil {
  247. return
  248. }
  249. if b.child != nil {
  250. panic("cryptobyte: attempted write while child is pending")
  251. }
  252. if len(b.result)+len(bytes) < len(bytes) {
  253. b.err = errors.New("cryptobyte: length overflow")
  254. }
  255. if b.fixedSize && len(b.result)+len(bytes) > cap(b.result) {
  256. b.err = errors.New("cryptobyte: Builder is exceeding its fixed-size buffer")
  257. return
  258. }
  259. b.result = append(b.result, bytes...)
  260. }
  261. // Unwrite rolls back n bytes written directly to the Builder. An attempt by a
  262. // child builder passed to a continuation to unwrite bytes from its parent will
  263. // panic.
  264. func (b *Builder) Unwrite(n int) {
  265. if b.err != nil {
  266. return
  267. }
  268. if b.child != nil {
  269. panic("cryptobyte: attempted unwrite while child is pending")
  270. }
  271. length := len(b.result) - b.pendingLenLen - b.offset
  272. if length < 0 {
  273. panic("cryptobyte: internal error")
  274. }
  275. if n > length {
  276. panic("cryptobyte: attempted to unwrite more than was written")
  277. }
  278. b.result = b.result[:len(b.result)-n]
  279. }
  280. // A MarshalingValue marshals itself into a Builder.
  281. type MarshalingValue interface {
  282. // Marshal is called by Builder.AddValue. It receives a pointer to a builder
  283. // to marshal itself into. It may return an error that occurred during
  284. // marshaling, such as unset or invalid values.
  285. Marshal(b *Builder) error
  286. }
  287. // AddValue calls Marshal on v, passing a pointer to the builder to append to.
  288. // If Marshal returns an error, it is set on the Builder so that subsequent
  289. // appends don't have an effect.
  290. func (b *Builder) AddValue(v MarshalingValue) {
  291. err := v.Marshal(b)
  292. if err != nil {
  293. b.err = err
  294. }
  295. }