diff --git a/orderlyid.go b/orderlyid.go index 52ef107..83307b1 100644 --- a/orderlyid.go +++ b/orderlyid.go @@ -204,16 +204,15 @@ type Parsed struct { func Parse(s string) (*Parsed, error) { s = strings.TrimSpace(s) base := s + csGiven := "" + hasChecksum := false if i := strings.LastIndexByte(s, '-'); i >= 0 { base = s[:i] - csGiven := s[i+1:] + csGiven = s[i+1:] + hasChecksum = true if len(csGiven) != 4 { return nil, fmt.Errorf("%w: must be 4 chars", ErrInvalidChecksum) } - expected := checksum4Base(base) - if !strings.EqualFold(csGiven, expected) { - return nil, fmt.Errorf("%w: checksum mismatch", ErrInvalidChecksum) - } } i := strings.IndexByte(base, '_') if i <= 0 { @@ -232,6 +231,12 @@ func Parse(s string) (*Parsed, error) { return nil, fmt.Errorf("%w: invalid character at pos %d", ErrInvalidBase32, j) } } + if hasChecksum { + expected := checksum4Base(base) + if !strings.EqualFold(csGiven, expected) { + return nil, fmt.Errorf("%w: checksum mismatch", ErrInvalidChecksum) + } + } buf, err := b32decode(payload) if err != nil { return nil, err diff --git a/orderlyid_test.go b/orderlyid_test.go index f8ff3b9..fecdd30 100644 --- a/orderlyid_test.go +++ b/orderlyid_test.go @@ -88,6 +88,37 @@ func TestParseErrorsSupportErrorsIs(t *testing.T) { } } +func TestParseInvalidChecksumBaseDoesNotPanic(t *testing.T) { + tests := []struct { + name string + id string + want error + }{ + {name: "missing payload separator", id: "order-abcd", want: ErrInvalidFormat}, + {name: "invalid prefix", id: "Order_00000000000000000000000000000000-abcd", want: ErrInvalidPrefix}, + {name: "short payload", id: "order_123-abcd", want: ErrInvalidPayloadLength}, + {name: "invalid base32", id: "order_0000000000000000000000000000000!-abcd", want: ErrInvalidBase32}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Fatalf("Parse panicked: %v", r) + } + }() + + _, err := Parse(tt.id) + if err == nil { + t.Fatalf("expected error") + } + if !errors.Is(err, tt.want) { + t.Fatalf("expected %v, got %v", tt.want, err) + } + }) + } +} + func TestNewFromPartsErrorsSupportErrorsIs(t *testing.T) { if _, err := NewFromParts(Components{Prefix: "Bad!"}, false); err == nil { t.Fatalf("expected invalid prefix error")