github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/helper/raftutil/msgpack.go (about) 1 package raftutil 2 3 import ( 4 "bytes" 5 "fmt" 6 "time" 7 "unicode" 8 9 "github.com/hashicorp/go-msgpack/codec" 10 "github.com/hashicorp/nomad/nomad/structs" 11 ) 12 13 // fixTime converts any suspected time.Time binary string representation to time.Time 14 func fixTime(v interface{}) { 15 switch v2 := v.(type) { 16 case map[string]interface{}: 17 for ek, ev := range v2 { 18 if s, ok := ev.(string); ok { 19 t, err := maybeDecodeTime(s) 20 if err == nil && isReasonableTime(t) { 21 v2[ek] = *t 22 } 23 } else { 24 fixTime(ev) 25 } 26 } 27 case []interface{}: 28 for _, e := range v2 { 29 fixTime(e) 30 } 31 default: 32 return 33 } 34 } 35 36 // maybeDecodeTime returns a time.Time representation if the string represents a msgpack 37 // representation of a date. 38 func maybeDecodeTime(v string) (*time.Time, error) { 39 if isASCII(v) { 40 return nil, fmt.Errorf("simple ascii string") 41 } 42 43 tt := &time.Time{} 44 var err error 45 46 err = tt.UnmarshalBinary([]byte(v)) 47 if err == nil { 48 return tt, nil 49 } 50 51 switch len(v) { 52 case 4, 8, 12: 53 default: 54 return nil, fmt.Errorf("bad length: %d", len(v)) 55 } 56 57 var nb bytes.Buffer 58 err = codec.NewEncoder(&nb, structs.MsgpackHandle).Encode(v) 59 if err != nil { 60 return nil, err 61 } 62 63 err = codec.NewDecoder(&nb, structs.MsgpackHandle).Decode(tt) 64 if err != nil { 65 return nil, err 66 } 67 68 return tt, nil 69 } 70 71 // isASCII returns true if all string characters are ASCII characters 72 func isASCII(s string) bool { 73 for i := 0; i < len(s); i++ { 74 if s[i] > unicode.MaxASCII { 75 return false 76 } 77 } 78 79 return true 80 } 81 82 // isReasonableTime returns true if the time is within some N years of current time 83 // 84 // It's can be used to rule out bad date interpretation (e.g. dates million years away). 85 func isReasonableTime(t *time.Time) bool { 86 if t.IsZero() { 87 return true 88 } 89 90 now := time.Now() 91 return t.Before(now.AddDate(20, 0, 0)) && t.After(now.AddDate(-20, 0, 0)) 92 }