github.com/zmap/zcrypto@v0.0.0-20240512203510-0fef58d9a9db/cryptobyte/cryptobyte_test.go (about)

     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  
     5  package cryptobyte
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"testing"
    12  )
    13  
    14  func builderBytesEq(b *Builder, want ...byte) error {
    15  	got := b.BytesOrPanic()
    16  	if !bytes.Equal(got, want) {
    17  		return fmt.Errorf("Bytes() = %v, want %v", got, want)
    18  	}
    19  	return nil
    20  }
    21  
    22  func TestContinuationError(t *testing.T) {
    23  	const errorStr = "TestContinuationError"
    24  	var b Builder
    25  	b.AddUint8LengthPrefixed(func(b *Builder) {
    26  		b.AddUint8(1)
    27  		panic(BuildError{Err: errors.New(errorStr)})
    28  	})
    29  
    30  	ret, err := b.Bytes()
    31  	if ret != nil {
    32  		t.Error("expected nil result")
    33  	}
    34  	if err == nil {
    35  		t.Fatal("unexpected nil error")
    36  	}
    37  	if s := err.Error(); s != errorStr {
    38  		t.Errorf("expected error %q, got %v", errorStr, s)
    39  	}
    40  }
    41  
    42  func TestContinuationNonError(t *testing.T) {
    43  	defer func() {
    44  		recover()
    45  	}()
    46  
    47  	var b Builder
    48  	b.AddUint8LengthPrefixed(func(b *Builder) {
    49  		b.AddUint8(1)
    50  		panic(1)
    51  	})
    52  
    53  	t.Error("Builder did not panic")
    54  }
    55  
    56  func TestGeneratedPanic(t *testing.T) {
    57  	defer func() {
    58  		recover()
    59  	}()
    60  
    61  	var b Builder
    62  	b.AddUint8LengthPrefixed(func(b *Builder) {
    63  		var p *byte
    64  		*p = 0
    65  	})
    66  
    67  	t.Error("Builder did not panic")
    68  }
    69  
    70  func TestBytes(t *testing.T) {
    71  	var b Builder
    72  	v := []byte("foobarbaz")
    73  	b.AddBytes(v[0:3])
    74  	b.AddBytes(v[3:4])
    75  	b.AddBytes(v[4:9])
    76  	if err := builderBytesEq(&b, v...); err != nil {
    77  		t.Error(err)
    78  	}
    79  	s := String(b.BytesOrPanic())
    80  	for _, w := range []string{"foo", "bar", "baz"} {
    81  		var got []byte
    82  		if !s.ReadBytes(&got, 3) {
    83  			t.Errorf("ReadBytes() = false, want true (w = %v)", w)
    84  		}
    85  		want := []byte(w)
    86  		if !bytes.Equal(got, want) {
    87  			t.Errorf("ReadBytes(): got = %v, want %v", got, want)
    88  		}
    89  	}
    90  	if len(s) != 0 {
    91  		t.Errorf("len(s) = %d, want 0", len(s))
    92  	}
    93  }
    94  
    95  func TestUint8(t *testing.T) {
    96  	var b Builder
    97  	b.AddUint8(42)
    98  	if err := builderBytesEq(&b, 42); err != nil {
    99  		t.Error(err)
   100  	}
   101  
   102  	var s String = b.BytesOrPanic()
   103  	var v uint8
   104  	if !s.ReadUint8(&v) {
   105  		t.Error("ReadUint8() = false, want true")
   106  	}
   107  	if v != 42 {
   108  		t.Errorf("v = %d, want 42", v)
   109  	}
   110  	if len(s) != 0 {
   111  		t.Errorf("len(s) = %d, want 0", len(s))
   112  	}
   113  }
   114  
   115  func TestUint16(t *testing.T) {
   116  	var b Builder
   117  	b.AddUint16(65534)
   118  	if err := builderBytesEq(&b, 255, 254); err != nil {
   119  		t.Error(err)
   120  	}
   121  	var s String = b.BytesOrPanic()
   122  	var v uint16
   123  	if !s.ReadUint16(&v) {
   124  		t.Error("ReadUint16() == false, want true")
   125  	}
   126  	if v != 65534 {
   127  		t.Errorf("v = %d, want 65534", v)
   128  	}
   129  	if len(s) != 0 {
   130  		t.Errorf("len(s) = %d, want 0", len(s))
   131  	}
   132  }
   133  
   134  func TestUint24(t *testing.T) {
   135  	var b Builder
   136  	b.AddUint24(0xfffefd)
   137  	if err := builderBytesEq(&b, 255, 254, 253); err != nil {
   138  		t.Error(err)
   139  	}
   140  
   141  	var s String = b.BytesOrPanic()
   142  	var v uint32
   143  	if !s.ReadUint24(&v) {
   144  		t.Error("ReadUint8() = false, want true")
   145  	}
   146  	if v != 0xfffefd {
   147  		t.Errorf("v = %d, want fffefd", v)
   148  	}
   149  	if len(s) != 0 {
   150  		t.Errorf("len(s) = %d, want 0", len(s))
   151  	}
   152  }
   153  
   154  func TestUint24Truncation(t *testing.T) {
   155  	var b Builder
   156  	b.AddUint24(0x10111213)
   157  	if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil {
   158  		t.Error(err)
   159  	}
   160  }
   161  
   162  func TestUint32(t *testing.T) {
   163  	var b Builder
   164  	b.AddUint32(0xfffefdfc)
   165  	if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil {
   166  		t.Error(err)
   167  	}
   168  
   169  	var s String = b.BytesOrPanic()
   170  	var v uint32
   171  	if !s.ReadUint32(&v) {
   172  		t.Error("ReadUint8() = false, want true")
   173  	}
   174  	if v != 0xfffefdfc {
   175  		t.Errorf("v = %x, want fffefdfc", v)
   176  	}
   177  	if len(s) != 0 {
   178  		t.Errorf("len(s) = %d, want 0", len(s))
   179  	}
   180  }
   181  
   182  func TestUMultiple(t *testing.T) {
   183  	var b Builder
   184  	b.AddUint8(23)
   185  	b.AddUint32(0xfffefdfc)
   186  	b.AddUint16(42)
   187  	if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil {
   188  		t.Error(err)
   189  	}
   190  
   191  	var s String = b.BytesOrPanic()
   192  	var (
   193  		x uint8
   194  		y uint32
   195  		z uint16
   196  	)
   197  	if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) {
   198  		t.Error("ReadUint8() = false, want true")
   199  	}
   200  	if x != 23 || y != 0xfffefdfc || z != 42 {
   201  		t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z)
   202  	}
   203  	if len(s) != 0 {
   204  		t.Errorf("len(s) = %d, want 0", len(s))
   205  	}
   206  }
   207  
   208  func TestUint8LengthPrefixedSimple(t *testing.T) {
   209  	var b Builder
   210  	b.AddUint8LengthPrefixed(func(c *Builder) {
   211  		c.AddUint8(23)
   212  		c.AddUint8(42)
   213  	})
   214  	if err := builderBytesEq(&b, 2, 23, 42); err != nil {
   215  		t.Error(err)
   216  	}
   217  
   218  	var base, child String = b.BytesOrPanic(), nil
   219  	var x, y uint8
   220  	if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) ||
   221  		!child.ReadUint8(&y) {
   222  		t.Error("parsing failed")
   223  	}
   224  	if x != 23 || y != 42 {
   225  		t.Errorf("want x, y == 23, 42; got %d, %d", x, y)
   226  	}
   227  	if len(base) != 0 {
   228  		t.Errorf("len(base) = %d, want 0", len(base))
   229  	}
   230  	if len(child) != 0 {
   231  		t.Errorf("len(child) = %d, want 0", len(child))
   232  	}
   233  }
   234  
   235  func TestUint8LengthPrefixedMulti(t *testing.T) {
   236  	var b Builder
   237  	b.AddUint8LengthPrefixed(func(c *Builder) {
   238  		c.AddUint8(23)
   239  		c.AddUint8(42)
   240  	})
   241  	b.AddUint8(5)
   242  	b.AddUint8LengthPrefixed(func(c *Builder) {
   243  		c.AddUint8(123)
   244  		c.AddUint8(234)
   245  	})
   246  	if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil {
   247  		t.Error(err)
   248  	}
   249  
   250  	var s, child String = b.BytesOrPanic(), nil
   251  	var u, v, w, x, y uint8
   252  	if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) ||
   253  		!s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) {
   254  		t.Error("parsing failed")
   255  	}
   256  	if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 {
   257  		t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234",
   258  			u, v, w, x, y)
   259  	}
   260  	if len(s) != 0 {
   261  		t.Errorf("len(s) = %d, want 0", len(s))
   262  	}
   263  	if len(child) != 0 {
   264  		t.Errorf("len(child) = %d, want 0", len(child))
   265  	}
   266  }
   267  
   268  func TestUint8LengthPrefixedNested(t *testing.T) {
   269  	var b Builder
   270  	b.AddUint8LengthPrefixed(func(c *Builder) {
   271  		c.AddUint8(5)
   272  		c.AddUint8LengthPrefixed(func(d *Builder) {
   273  			d.AddUint8(23)
   274  			d.AddUint8(42)
   275  		})
   276  		c.AddUint8(123)
   277  	})
   278  	if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil {
   279  		t.Error(err)
   280  	}
   281  
   282  	var base, child1, child2 String = b.BytesOrPanic(), nil, nil
   283  	var u, v, w, x uint8
   284  	if !base.ReadUint8LengthPrefixed(&child1) {
   285  		t.Error("parsing base failed")
   286  	}
   287  	if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) {
   288  		t.Error("parsing child1 failed")
   289  	}
   290  	if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) {
   291  		t.Error("parsing child2 failed")
   292  	}
   293  	if u != 5 || v != 23 || w != 42 || x != 123 {
   294  		t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123",
   295  			u, v, w, x)
   296  	}
   297  	if len(base) != 0 {
   298  		t.Errorf("len(base) = %d, want 0", len(base))
   299  	}
   300  	if len(child1) != 0 {
   301  		t.Errorf("len(child1) = %d, want 0", len(child1))
   302  	}
   303  	if len(base) != 0 {
   304  		t.Errorf("len(child2) = %d, want 0", len(child2))
   305  	}
   306  }
   307  
   308  func TestPreallocatedBuffer(t *testing.T) {
   309  	var buf [5]byte
   310  	b := NewBuilder(buf[0:0])
   311  	b.AddUint8(1)
   312  	b.AddUint8LengthPrefixed(func(c *Builder) {
   313  		c.AddUint8(3)
   314  		c.AddUint8(4)
   315  	})
   316  	b.AddUint16(1286) // Outgrow buf by one byte.
   317  	want := []byte{1, 2, 3, 4, 0}
   318  	if !bytes.Equal(buf[:], want) {
   319  		t.Errorf("buf = %v want %v", buf, want)
   320  	}
   321  	if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil {
   322  		t.Error(err)
   323  	}
   324  }
   325  
   326  func TestWriteWithPendingChild(t *testing.T) {
   327  	var b Builder
   328  	b.AddUint8LengthPrefixed(func(c *Builder) {
   329  		c.AddUint8LengthPrefixed(func(d *Builder) {
   330  			func() {
   331  				defer func() {
   332  					if recover() == nil {
   333  						t.Errorf("recover() = nil, want error; c.AddUint8() did not panic")
   334  					}
   335  				}()
   336  				c.AddUint8(2) // panics
   337  			}()
   338  
   339  			defer func() {
   340  				if recover() == nil {
   341  					t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
   342  				}
   343  			}()
   344  			b.AddUint8(2) // panics
   345  		})
   346  
   347  		defer func() {
   348  			if recover() == nil {
   349  				t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
   350  			}
   351  		}()
   352  		b.AddUint8(2) // panics
   353  	})
   354  }
   355  
   356  func TestSetError(t *testing.T) {
   357  	const errorStr = "TestSetError"
   358  	var b Builder
   359  	b.SetError(errors.New(errorStr))
   360  
   361  	ret, err := b.Bytes()
   362  	if ret != nil {
   363  		t.Error("expected nil result")
   364  	}
   365  	if err == nil {
   366  		t.Fatal("unexpected nil error")
   367  	}
   368  	if s := err.Error(); s != errorStr {
   369  		t.Errorf("expected error %q, got %v", errorStr, s)
   370  	}
   371  }
   372  
   373  func TestUnwrite(t *testing.T) {
   374  	var b Builder
   375  	b.AddBytes([]byte{1, 2, 3, 4, 5})
   376  	b.Unwrite(2)
   377  	if err := builderBytesEq(&b, 1, 2, 3); err != nil {
   378  		t.Error(err)
   379  	}
   380  
   381  	func() {
   382  		defer func() {
   383  			if recover() == nil {
   384  				t.Errorf("recover() = nil, want error; b.Unwrite() did not panic")
   385  			}
   386  		}()
   387  		b.Unwrite(4) // panics
   388  	}()
   389  
   390  	b = Builder{}
   391  	b.AddBytes([]byte{1, 2, 3, 4, 5})
   392  	b.AddUint8LengthPrefixed(func(b *Builder) {
   393  		b.AddBytes([]byte{1, 2, 3, 4, 5})
   394  
   395  		defer func() {
   396  			if recover() == nil {
   397  				t.Errorf("recover() = nil, want error; b.Unwrite() did not panic")
   398  			}
   399  		}()
   400  		b.Unwrite(6) // panics
   401  	})
   402  
   403  	b = Builder{}
   404  	b.AddBytes([]byte{1, 2, 3, 4, 5})
   405  	b.AddUint8LengthPrefixed(func(c *Builder) {
   406  		defer func() {
   407  			if recover() == nil {
   408  				t.Errorf("recover() = nil, want error; b.Unwrite() did not panic")
   409  			}
   410  		}()
   411  		b.Unwrite(2) // panics (attempted unwrite while child is pending)
   412  	})
   413  }
   414  
   415  func TestFixedBuilderLengthPrefixed(t *testing.T) {
   416  	bufCap := 10
   417  	inner := bytes.Repeat([]byte{0xff}, bufCap-2)
   418  	buf := make([]byte, 0, bufCap)
   419  	b := NewFixedBuilder(buf)
   420  	b.AddUint16LengthPrefixed(func(b *Builder) {
   421  		b.AddBytes(inner)
   422  	})
   423  	if got := b.BytesOrPanic(); len(got) != bufCap {
   424  		t.Errorf("Expected output length to be %d, got %d", bufCap, len(got))
   425  	}
   426  }
   427  
   428  func TestFixedBuilderPanicReallocate(t *testing.T) {
   429  	defer func() {
   430  		recover()
   431  	}()
   432  
   433  	b := NewFixedBuilder(make([]byte, 0, 10))
   434  	b1 := NewFixedBuilder(make([]byte, 0, 10))
   435  	b.AddUint16LengthPrefixed(func(b *Builder) {
   436  		*b = *b1
   437  	})
   438  
   439  	t.Error("Builder did not panic")
   440  }
   441  
   442  // ASN.1
   443  
   444  func TestASN1Int64(t *testing.T) {
   445  	tests := []struct {
   446  		in   int64
   447  		want []byte
   448  	}{
   449  		{-0x800000, []byte{2, 3, 128, 0, 0}},
   450  		{-256, []byte{2, 2, 255, 0}},
   451  		{-129, []byte{2, 2, 255, 127}},
   452  		{-128, []byte{2, 1, 128}},
   453  		{-1, []byte{2, 1, 255}},
   454  		{0, []byte{2, 1, 0}},
   455  		{1, []byte{2, 1, 1}},
   456  		{2, []byte{2, 1, 2}},
   457  		{127, []byte{2, 1, 127}},
   458  		{128, []byte{2, 2, 0, 128}},
   459  		{256, []byte{2, 2, 1, 0}},
   460  		{0x800000, []byte{2, 4, 0, 128, 0, 0}},
   461  	}
   462  	for i, tt := range tests {
   463  		var b Builder
   464  		b.AddASN1Int64(tt.in)
   465  		if err := builderBytesEq(&b, tt.want...); err != nil {
   466  			t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
   467  		}
   468  
   469  		var n int64
   470  		s := String(b.BytesOrPanic())
   471  		ok := s.ReadASN1Integer(&n)
   472  		if !ok || n != tt.in {
   473  			t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
   474  				ok, n, tt.in, i)
   475  		}
   476  		if len(s) != 0 {
   477  			t.Errorf("len(s) = %d, want 0", len(s))
   478  		}
   479  	}
   480  }
   481  
   482  func TestASN1Uint64(t *testing.T) {
   483  	tests := []struct {
   484  		in   uint64
   485  		want []byte
   486  	}{
   487  		{0, []byte{2, 1, 0}},
   488  		{1, []byte{2, 1, 1}},
   489  		{2, []byte{2, 1, 2}},
   490  		{127, []byte{2, 1, 127}},
   491  		{128, []byte{2, 2, 0, 128}},
   492  		{256, []byte{2, 2, 1, 0}},
   493  		{0x800000, []byte{2, 4, 0, 128, 0, 0}},
   494  		{0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}},
   495  		{0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}},
   496  		{0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}},
   497  	}
   498  	for i, tt := range tests {
   499  		var b Builder
   500  		b.AddASN1Uint64(tt.in)
   501  		if err := builderBytesEq(&b, tt.want...); err != nil {
   502  			t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
   503  		}
   504  
   505  		var n uint64
   506  		s := String(b.BytesOrPanic())
   507  		ok := s.ReadASN1Integer(&n)
   508  		if !ok || n != tt.in {
   509  			t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
   510  				ok, n, tt.in, i)
   511  		}
   512  		if len(s) != 0 {
   513  			t.Errorf("len(s) = %d, want 0", len(s))
   514  		}
   515  	}
   516  }