diff --git a/diagnose.go b/diagnose.go index 40179060..8af4d7aa 100644 --- a/diagnose.go +++ b/diagnose.go @@ -183,7 +183,7 @@ func (di *diagnose) diag() (string, error) { // CBOR Sequence firstItem := true for { - switch err := di.valid(); err { + switch err := di.wellformed(); err { case nil: if !firstItem { if err = di.writeString(", "); err != nil { @@ -204,9 +204,9 @@ func (di *diagnose) diag() (string, error) { } } -func (di *diagnose) valid() error { +func (di *diagnose) wellformed() error { off := di.d.off - err := di.d.valid(di.dm.cborSequence) + err := di.d.wellformed(di.dm.cborSequence) di.d.off = off return err } @@ -372,11 +372,19 @@ func (di *diagnose) item() error { //nolint:gocyclo _, _, tagNum := di.d.getHead() switch tagNum { case 2: + if di.d.nextCBORType() != cborTypeByteString { + return errors.New("cbor: tag number 2 must be followed by byte string, got " + t.String()) + } + b := di.d.parseByteString() bi := new(big.Int).SetBytes(b) return di.writeString(bi.String()) case 3: + if di.d.nextCBORType() != cborTypeByteString { + return errors.New("cbor: tag number 3 must be followed by byte string, got " + t.String()) + } + b := di.d.parseByteString() bi := new(big.Int).SetBytes(b) bi.Add(bi, big.NewInt(1)) diff --git a/diagnose_test.go b/diagnose_test.go index c87b2a49..e6430e92 100644 --- a/diagnose_test.go +++ b/diagnose_test.go @@ -780,3 +780,76 @@ func TestDiagnoseCBORSequences(t *testing.T) { }) } } + +func TestDiagnoseTag(t *testing.T) { + testCases := []struct { + title string + cbor []byte + diag string + opts *DiagOptions + returnError bool + }{ + { + "CBOR tag number 2 with not well-formed encoded CBOR data item", + hexDecode("c201"), + ``, + &DiagOptions{}, + true, + }, + { + "CBOR tag number 3 with not well-formed encoded CBOR data item", + hexDecode("c301"), + ``, + &DiagOptions{}, + true, + }, + { + "CBOR tag number 2 with well-formed encoded CBOR data item", + hexDecode("c240"), + `0`, + &DiagOptions{}, + false, + }, + { + "CBOR tag number 3 with well-formed encoded CBOR data item", + hexDecode("c340"), + `-1`, // -1 - n + &DiagOptions{}, + false, + }, + { + "CBOR tag number 2 with well-formed encoded CBOR data item", + hexDecode("c249010000000000000000"), + `18446744073709551616`, + &DiagOptions{}, + false, + }, + { + "CBOR tag number 3 with well-formed encoded CBOR data item", + hexDecode("c349010000000000000000"), + `-18446744073709551617`, // -1 - n + &DiagOptions{}, + false, + }, + } + + for _, tc := range testCases { + t.Run(tc.title, func(t *testing.T) { + dm, err := tc.opts.DiagMode() + if err != nil { + t.Errorf("DiagMode() for 0x%x returned error %q", tc.cbor, err) + } + + str, err := dm.Diagnose(tc.cbor) + if tc.returnError && err == nil { + t.Errorf("Diagnose(0x%x) returned error %q", tc.cbor, err) + } else if !tc.returnError && err != nil { + t.Errorf("Diagnose(0x%x) returned error %q", tc.cbor, err) + } + + if str != tc.diag { + t.Errorf("Diagnose(0x%x) returned `%s`, want %s", tc.cbor, str, tc.diag) + } + }) + } +}