]> Cypherpunks repositories - keks.git/commitdiff
Less panics
authorSergey Matveev <stargrave@stargrave.org>
Sun, 15 Dec 2024 09:49:56 +0000 (12:49 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 15 Dec 2024 13:30:44 +0000 (16:30 +0300)
13 files changed:
gyac/cmd/print/main.go
gyac/cmd/test-vector-anys/main.go
gyac/enc.go
gyac/fromgo.go
gyac/fuzz_test.go
gyac/mapstruct/dec.go
gyac/pki/av.go
gyac/pki/cer.go
gyac/pki/cmd/yacertool/main.go
gyac/pki/cmd/yacsdtool/main.go
gyac/pki/gost/signer.go
gyac/pki/signed-data.go
gyac/togo.go

index f49b61028d0decedc85798084c234ea277c5f56fda982a5feae2bc38822e1efe..c4bfee5db4b498a0c11659879087d962e603a9849306a000678cb60375c13a52 100644 (file)
@@ -22,5 +22,9 @@ func main() {
        if len(tail) > 0 {
                log.Fatalln("trailing data:", tail)
        }
-       fmt.Printf("%v\n", item.ToGo())
+       e, err := item.ToGo()
+       if err != nil {
+               log.Fatal(err)
+       }
+       fmt.Printf("%v\n", e)
 }
index c1713d851972d17cece72c28f6d7eee3f6086d65f83916167e11fbcd31ad5c72..a5fd7f59b78c43f4e805b4ee807744f002f32fadea4c46d56349f23b31fd4e1d 100644 (file)
@@ -4,6 +4,7 @@ import (
        "bytes"
        "encoding/hex"
        "fmt"
+       "log"
        "math/big"
        "time"
 
@@ -107,5 +108,9 @@ func main() {
                },
                "uuid": uuid.MustParse("0e875e3f-d385-49eb-87b4-be42d641c367"),
        }
-       fmt.Println(hex.EncodeToString(gyac.FromGo(data).Encode(nil)))
+       item, err := gyac.FromGo(data)
+       if err != nil {
+               log.Fatal(err)
+       }
+       fmt.Println(hex.EncodeToString(item.Encode(nil)))
 }
index c689ec24874d8708fb312795a45e170c8d017ae98d7414fb085b3e773fe9cb4c..a1f06d4924447d298b5baf02a04f0ed0079d875f0be71a8c6aa0640f5acd682c 100644 (file)
@@ -29,6 +29,8 @@ import (
 // Encode an item appending to the buf.
 func (item Item) Encode(buf []byte) []byte {
        switch item.T {
+       case types.Invalid:
+               panic("invalid item's type met")
        case types.NIL:
                return atom.NILEncode(buf)
        case types.Bool:
index 3a815f1830cbd68be4313b53bd58b35d7c56bf23f9c80667d3bd1f089a838b1c..d7beeed60aa78de84720301439c65b6c2421e51dba73bb6d60553955462dd646 100644 (file)
@@ -62,19 +62,19 @@ func structTagRead(f reflect.StructField) (name string, omit bool) {
 //     TAI64 (if nanoseconds=0), or TAI64N
 //   - uint, uint8, uint16, uint32, uint64
 //   - uuid.UUID
-func FromGo(v any) Item {
+func FromGo(v any) (Item, error) {
        if v == nil {
-               return Item{T: types.NIL}
+               return Item{T: types.NIL}, nil
        }
        rv := reflect.ValueOf(v)
        if b, ok := v.([]byte); ok {
-               return Item{T: types.Bin, V: b}
+               return Item{T: types.Bin, V: b}, nil
        }
        switch v := v.(type) {
        case *Blob:
-               return Item{T: types.Blob, V: *v}
+               return Item{T: types.Blob, V: *v}, nil
        case Blob:
-               return Item{T: types.Blob, V: v}
+               return Item{T: types.Blob, V: v}, nil
        case time.Time:
                t := tai64n.Leapsecs.Add(v)
                var taiRaw []byte
@@ -87,40 +87,57 @@ func FromGo(v any) Item {
                        tai.FromTime(t)
                        taiRaw = tai[:]
                }
-               return Item{T: types.TAI64, V: taiRaw}
+               return Item{T: types.TAI64, V: taiRaw}, nil
        case *atom.Raw:
-               return Item{T: types.Raw, V: *v}
+               return Item{T: types.Raw, V: *v}, nil
        case atom.Raw:
-               return Item{T: types.Raw, V: v}
+               return Item{T: types.Raw, V: v}, nil
        case *big.Int:
-               return Item{T: types.BigInt, V: v}
+               return Item{T: types.BigInt, V: v}, nil
        }
        switch reflect.TypeOf(v).Kind() {
        case reflect.Pointer:
                if rv.IsNil() {
-                       return Item{T: types.NIL}
+                       return Item{T: types.NIL}, nil
                }
                return FromGo(rv.Elem().Interface())
        case reflect.Slice:
                var ret []Item
+               var err error
                if anys, ok := v.([]any); ok {
                        for _, v := range anys {
-                               ret = append(ret, FromGo(v))
+                               var item Item
+                               item, err = FromGo(v)
+                               if err != nil {
+                                       return item, err
+                               }
+                               ret = append(ret, item)
                        }
                } else {
                        rv = reflect.ValueOf(v)
                        for i := 0; i < rv.Len(); i++ {
-                               ret = append(ret, FromGo(rv.Index(i).Interface()))
+                               var item Item
+                               item, err = FromGo(rv.Index(i).Interface())
+                               if err != nil {
+                                       return item, err
+                               }
+                               ret = append(ret, item)
                        }
                }
-               return Item{T: types.List, V: ret}
+               return Item{T: types.List, V: ret}, nil
        case reflect.Map:
                ret := make(map[string]Item, rv.Len())
                iter := rv.MapRange()
+               var err error
                for iter.Next() {
-                       ret[iter.Key().String()] = FromGo(iter.Value().Interface())
+                       var item Item
+                       item, err = FromGo(iter.Value().Interface())
+                       if err != nil {
+                               return item, err
+                       }
+                       ret[iter.Key().String()] = item
                }
-               return Item{T: types.Map, V: ret}
+               return Item{T: types.Map, V: ret}, nil
        }
        {
                t := rv.Type()
@@ -130,7 +147,10 @@ func FromGo(v any) Item {
                                fv := rv.FieldByIndex(f.Index)
                                name, omit := structTagRead(f)
                                var empty bool
-                               item := FromGo(fv.Interface())
+                               item, err := FromGo(fv.Interface())
+                               if err != nil {
+                                       return item, err
+                               }
                                switch item.T {
                                case types.NIL:
                                        empty = true
@@ -147,52 +167,52 @@ func FromGo(v any) Item {
                                        ret[name] = item
                                }
                        }
-                       return Item{T: types.Map, V: ret}
+                       return Item{T: types.Map, V: ret}, nil
                }
        }
        switch v := v.(type) {
        case bool:
-               return Item{T: types.Bool, V: v}
+               return Item{T: types.Bool, V: v}, nil
        case uuid.UUID:
-               return Item{T: types.UUID, V: v}
+               return Item{T: types.UUID, V: v}, nil
        case uint:
-               return Item{T: types.UInt, V: uint64(v)}
+               return Item{T: types.UInt, V: uint64(v)}, nil
        case uint8:
-               return Item{T: types.UInt, V: uint64(v)}
+               return Item{T: types.UInt, V: uint64(v)}, nil
        case uint16:
-               return Item{T: types.UInt, V: uint64(v)}
+               return Item{T: types.UInt, V: uint64(v)}, nil
        case uint32:
-               return Item{T: types.UInt, V: uint64(v)}
+               return Item{T: types.UInt, V: uint64(v)}, nil
        case uint64:
-               return Item{T: types.UInt, V: v}
+               return Item{T: types.UInt, V: v}, nil
        case int:
                if v >= 0 {
-                       return Item{T: types.UInt, V: uint64(v)}
+                       return Item{T: types.UInt, V: uint64(v)}, nil
                }
-               return Item{T: types.Int, V: int64(v)}
+               return Item{T: types.Int, V: int64(v)}, nil
        case int8:
                if v >= 0 {
-                       return Item{T: types.UInt, V: uint64(v)}
+                       return Item{T: types.UInt, V: uint64(v)}, nil
                }
-               return Item{T: types.Int, V: int64(v)}
+               return Item{T: types.Int, V: int64(v)}, nil
        case int16:
                if v >= 0 {
-                       return Item{T: types.UInt, V: uint64(v)}
+                       return Item{T: types.UInt, V: uint64(v)}, nil
                }
-               return Item{T: types.Int, V: int64(v)}
+               return Item{T: types.Int, V: int64(v)}, nil
        case int32:
                if v >= 0 {
-                       return Item{T: types.UInt, V: uint64(v)}
+                       return Item{T: types.UInt, V: uint64(v)}, nil
                }
-               return Item{T: types.Int, V: int64(v)}
+               return Item{T: types.Int, V: int64(v)}, nil
        case int64:
                if v >= 0 {
-                       return Item{T: types.UInt, V: uint64(v)}
+                       return Item{T: types.UInt, V: uint64(v)}, nil
                }
-               return Item{T: types.Int, V: v}
+               return Item{T: types.Int, V: v}, nil
        case string:
-               return Item{T: types.Str, V: v}
+               return Item{T: types.Str, V: v}, nil
        default:
-               panic(fmt.Errorf("unhandled type: %+v", v))
+               return Item{}, fmt.Errorf("unhandled type: %+v", v)
        }
 }
index 103e4dac9e5b32a924ca21fc13f8b13b80fe896929667b342d7d76dc88f8b8ea..f009115c7627c14671134ab10b93ece93a8446ee7a66da92fe902e6004f6880e 100644 (file)
@@ -9,13 +9,19 @@ func FuzzItemDecode(f *testing.F) {
        var item Item
        var err error
        var tail []byte
+       var e any
        f.Fuzz(func(t *testing.T, b []byte) {
                item, tail, err = Decode(b)
                if err == nil {
-                       if !bytes.Equal(
-                               append(FromGo(item.ToGo()).Encode(nil), tail...),
-                               b,
-                       ) {
+                       e, err = item.ToGo()
+                       if err != nil {
+                               t.Fail()
+                       }
+                       item, err = FromGo(e)
+                       if err != nil {
+                               t.Fail()
+                       }
+                       if !bytes.Equal(append(item.Encode(nil), tail...), b) {
                                t.Fail()
                        }
                }
index 5d214f9690a189c83e277fbe46cfc81dcf93b2c6ca7184ed7d69f0c3651f3945..53eaca2022c8ab6f571a520a8ed2250a849e79ad1302e99f954b29f44f7dd735 100644 (file)
@@ -34,6 +34,11 @@ func Decode(dst any, raw []byte) (tail []byte, err error) {
                err = errors.New("non-map")
                return
        }
-       err = FromMap(dst, item.ToGo().(map[string]any))
+       var e any
+       e, err = item.ToGo()
+       if err != nil {
+               return
+       }
+       err = FromMap(dst, e.(map[string]any))
        return
 }
index 4e601d8ff79a945a86f1ee65ddb5daa23326e2bde72a656c14fe9e1194f7553e..89954193dad816dbae663ea07e1947355d251ab78fc7630bde6aa80e94a6c06a 100644 (file)
@@ -28,12 +28,17 @@ func (av *AV) Id() (id uuid.UUID) {
        case GOST3410256A, GOST3410512C:
                hasher = pkihash.ByName(pkihash.Streebog256)
        default:
-               return uuid.Nil
+               id = uuid.Nil
+               return
        }
-       utils.MustWrite(hasher, gyac.FromGo(av).Encode(nil))
-       id, err := uuid.NewRandomFromReader(bytes.NewReader(hasher.Sum(nil)))
+       item, err := gyac.FromGo(av)
        if err != nil {
                panic(err)
        }
-       return id
+       utils.MustWrite(hasher, item.Encode(nil))
+       id, err = uuid.NewRandomFromReader(bytes.NewReader(hasher.Sum(nil)))
+       if err != nil {
+               panic(err)
+       }
+       return
 }
index 4235fc4339e1bd870d7263252381908acca90841485c7b1fc4c93ee7713802c8..2093f57e5421905b50c46fb77cccd1771626afadcde3d215bf0aaf96a501f70c 100644 (file)
@@ -176,7 +176,12 @@ func (sd *SignedData) CerCheckSignatureFrom(parent *CerLoad) (err error) {
                return
        }
        tbs := SignedDataTBS{T: sd.Load.T, V: sd.Load.V, TBS: sig.TBS}
-       return parent.CheckSignature(gyac.FromGo(tbs).Encode(nil), sig.Sign.V)
+       var item gyac.Item
+       item, err = gyac.FromGo(tbs)
+       if err != nil {
+               return
+       }
+       return parent.CheckSignature(item.Encode(nil), sig.Sign.V)
 }
 
 // Get CerLoad from SignedData.
index c71cd33067d77b7918876cbae9fd729c5fe183597f969fa3c6acb65db0cdceed..39c5f983a6dc84dbb3125f22014202ecdafbb8a7114b2dd565d6993be52fa2b8 100644 (file)
@@ -121,6 +121,7 @@ func main() {
                log.Fatal("no -prv is set")
        }
 
+       var item gyac.Item
        var prv crypto.Signer
        var prvRaw []byte
        var pub []byte
@@ -141,11 +142,11 @@ func main() {
                if err != nil {
                        log.Fatal(err)
                }
-               err = os.WriteFile(
-                       *prvPath,
-                       gyac.FromGo(pki.AV{A: *algo, V: prvRaw}).Encode(nil),
-                       0o600,
-               )
+               item, err = gyac.FromGo(pki.AV{A: *algo, V: prvRaw})
+               if err != nil {
+                       log.Fatal(err)
+               }
+               err = os.WriteFile(*prvPath, item.Encode(nil), 0o600)
                if err != nil {
                        log.Fatal(err)
                }
@@ -173,7 +174,11 @@ func main() {
                log.Fatal(err)
        }
 
-       err = os.WriteFile(*cerPath, gyac.FromGo(sd).Encode(nil), 0o666)
+       item, err = gyac.FromGo(sd)
+       if err != nil {
+               log.Fatal(err)
+       }
+       err = os.WriteFile(*cerPath, item.Encode(nil), 0o666)
        if err != nil {
                log.Fatal(err)
        }
index 7b170d9f1eade20cff7e4f8f09e7369155d507abec0f78fced57641d5ede6a45..929356b294a89be2fbf2922f1ec96aa0fbcb3380b755ac2f6d795516e0102a86 100644 (file)
@@ -98,7 +98,12 @@ func main() {
                if err != nil {
                        log.Fatal(err)
                }
-               err = os.WriteFile(*sdPath, gyac.FromGo(sd).Encode(nil), 0o666)
+               var item gyac.Item
+               item, err = gyac.FromGo(sd)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               err = os.WriteFile(*sdPath, item.Encode(nil), 0o666)
                if err != nil {
                        log.Fatal(err)
                }
index f1f077237a5d112a9410ab46cb4dffdd617dd0ab4595fdf7163f270b12e05476..2f7436b8c85cd3d5c35a41bc206d276934feabe4eb9b093882eb9feca9c8c4a0 100644 (file)
@@ -2,6 +2,7 @@ package gost
 
 import (
        "crypto"
+       "errors"
        "hash"
        "io"
 
@@ -49,7 +50,7 @@ func NewSigner(a string, v []byte) (prv crypto.Signer, pub []byte, err error) {
                        gost3410.CurveIdtc26gost341012512paramSetC(), v,
                )
        default:
-               panic("unknown GOST algorithm")
+               err = errors.New("unsupported GOST R 34.10 algorithm")
        }
        if err != nil {
                return
index 30505e5a0aebdc22f9620672d7355f323f79ea99cb297d47620e5663c04ca603..e35cffc53ea36ec89ff15a8b9b315bff30f0710a910596db60b8a0d7b0909ab0 100644 (file)
@@ -52,7 +52,12 @@ func SignedDataParseItem(item gyac.Item) (sd *SignedData, err error) {
                return
        }
        var _sd SignedData
-       err = mapstruct.FromMap(&_sd, item.ToGo().(map[string]any))
+       var e any
+       e, err = item.ToGo()
+       if err != nil {
+               return
+       }
+       err = mapstruct.FromMap(&_sd, e.(map[string]any))
        if err != nil {
                return
        }
@@ -143,9 +148,14 @@ func (sd *SignedData) SignWith(
        sdTBS := SignedDataTBS{T: sd.Load.T, V: sd.Load.V, TBS: sigTBS}
        sig := Sig{TBS: sigTBS}
        sig.Sign.A = parent.Pub[0].A
+       var item gyac.Item
+       item, err = gyac.FromGo(sdTBS)
+       if err != nil {
+               return
+       }
        sig.Sign.V, err = prv.Sign(
                rand.Reader,
-               gyac.FromGo(sdTBS).Encode(nil),
+               item.Encode(nil),
                crypto.Hash(0),
        )
        if err != nil {
index 27ee36cf1879d609e9260832d4d6fe93ce6c523d85c09e6d00d59d99b6d5723a..c4d5b096c5dabf33f7b55f3b24dd5fc484ddc9ab9d3ec577c969b526ab05c50a 100644 (file)
@@ -28,34 +28,46 @@ import (
 
 // Convert an item to various native Go types, atom.Raw, Blob, uuid.UUID.
 // Pay attention that f TAI equals to leap second, then it is converted to Raw.
-func (item Item) ToGo() any {
+func (item Item) ToGo() (any, error) {
        switch item.T {
        case types.NIL:
-               return nil
+               return nil, nil
        case types.Bool:
-               return item.V.(bool)
+               return item.V.(bool), nil
        case types.UUID:
-               return item.V.(uuid.UUID)
+               return item.V.(uuid.UUID), nil
        case types.UInt:
-               return item.V.(uint64)
+               return item.V.(uint64), nil
        case types.Int:
-               return item.V.(int64)
+               return item.V.(int64), nil
        case types.List:
                var ret []any
+               var err error
                for _, v := range item.V.([]Item) {
-                       ret = append(ret, v.ToGo())
+                       var e any
+                       e, err = v.ToGo()
+                       if err != nil {
+                               return nil, err
+                       }
+                       ret = append(ret, e)
                }
-               return ret
+               return ret, nil
        case types.Map:
                ret := make(map[string]any)
+               var err error
                for k, v := range item.V.(map[string]Item) {
-                       ret[k] = v.ToGo()
+                       var e any
+                       e, err = v.ToGo()
+                       if err != nil {
+                               return nil, err
+                       }
+                       ret[k] = e
                }
-               return ret
+               return ret, nil
        case types.Blob:
-               return item.V.(Blob)
+               return item.V.(Blob), nil
        case types.BigInt:
-               return item.V.(*big.Int)
+               return item.V.(*big.Int), nil
        case types.Float:
                panic("float is unsupported")
        case types.TAI64:
@@ -65,28 +77,28 @@ func (item Item) ToGo() any {
                        tai := tai64n.TAI64(raw)
                        t, isLeap := tai64n.Leapsecs.Sub(tai.Time())
                        if isLeap {
-                               return atom.Raw{T: atom.TAI64, V: raw}
+                               return atom.Raw{T: atom.TAI64, V: raw}, nil
                        }
-                       return t
+                       return t, nil
                case tai64n.TAI64NSize:
                        tai := tai64n.TAI64N(raw)
                        t, isLeap := tai64n.Leapsecs.Sub(tai.Time())
                        if isLeap {
-                               return atom.Raw{T: atom.TAI64N, V: raw}
+                               return atom.Raw{T: atom.TAI64N, V: raw}, nil
                        }
-                       return t
+                       return t, nil
                case tai64n.TAI64NASize:
-                       return atom.Raw{T: atom.TAI64NA, V: raw}
+                       return atom.Raw{T: atom.TAI64NA, V: raw}, nil
                default:
-                       panic("unexpected TAI size")
+                       panic("wrong TAI64 value")
                }
        case types.Bin:
-               return item.V.([]byte)
+               return item.V.([]byte), nil
        case types.Str:
-               return item.V.(string)
+               return item.V.(string), nil
        case types.Raw:
-               return item.V.(atom.Raw)
+               return item.V.(atom.Raw), nil
        default:
-               panic(fmt.Errorf("unhandled type: %+v", item))
+               return nil, fmt.Errorf("unhandled type: %+v", item)
        }
 }