github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/scanners/azure/arm/parser/armjson/decode_object.go (about) 1 package armjson 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 ) 8 9 func (n *node) decodeObject(v reflect.Value) error { 10 switch v.Kind() { 11 case reflect.Struct: 12 return n.decodeObjectToStruct(v) 13 case reflect.Map: 14 return n.decodeObjectToMap(v) 15 case reflect.Interface: 16 target := reflect.New(reflect.TypeOf(make(map[string]interface{}, len(n.Content())))).Elem() 17 if err := n.decodeObjectToMap(target); err != nil { 18 return err 19 } 20 v.Set(target) 21 return nil 22 default: 23 return fmt.Errorf("cannot set object value to target of type %s", v.Kind()) 24 } 25 } 26 27 func (n *node) decodeObjectToMap(v reflect.Value) error { 28 properties, err := n.objectAsMap() 29 if err != nil { 30 return err 31 } 32 33 newMap := reflect.MakeMap(v.Type()) 34 valueType := v.Type().Elem() 35 36 for key, value := range properties { 37 target := reflect.New(valueType).Elem() 38 addressable := target 39 if target.Kind() == reflect.Ptr { 40 target.Set(reflect.New(valueType.Elem())) 41 } else { 42 addressable = target.Addr() 43 } 44 if err := value.(*node).decodeToValue(addressable); err != nil { 45 return err 46 } 47 newMap.SetMapIndex(reflect.ValueOf(key), target) 48 } 49 50 v.Set(newMap) 51 return nil 52 53 } 54 55 func (n *node) objectAsMap() (map[string]Node, error) { 56 if n.kind != KindObject { 57 return nil, fmt.Errorf("not an object") 58 } 59 properties := make(map[string]Node) 60 contents := n.content 61 for i := 0; i < len(contents); i += 2 { 62 key := contents[i] 63 if key.Kind() != KindString { 64 return nil, fmt.Errorf("invalid object key - please report this bug") 65 } 66 keyStr := key.(*node).raw.(string) 67 68 if i+1 >= len(contents) { 69 return nil, fmt.Errorf("missing object value - please report this bug") 70 } 71 properties[keyStr] = contents[i+1] 72 } 73 return properties, nil 74 } 75 76 func (n *node) decodeObjectToStruct(v reflect.Value) error { 77 78 temp := reflect.New(v.Type()).Elem() 79 v.Set(temp) 80 81 properties, err := n.objectAsMap() 82 if err != nil { 83 return err 84 } 85 86 t := v.Type() 87 for i := 0; i < t.NumField(); i++ { 88 fv := t.Field(i) 89 tags := strings.Split(fv.Tag.Get("json"), ",") 90 var tagName string 91 for _, tag := range tags { 92 if tag != "omitempty" && tag != "-" { 93 tagName = tag 94 } 95 } 96 if tagName == "" { 97 tagName = fv.Name 98 } 99 100 value, ok := properties[tagName] 101 if !ok { 102 // TODO: should we zero this value? 103 continue 104 } 105 106 subject := v.Field(i) 107 108 // if fields are nil pointers, initialise them with values of the correct type 109 if subject.Kind() == reflect.Ptr { 110 if subject.IsNil() { 111 subject.Set(reflect.New(subject.Type().Elem())) 112 } 113 } else { 114 subject = subject.Addr() 115 } 116 117 if err := value.(*node).decodeToValue(subject); err != nil { 118 return err 119 } 120 } 121 return nil 122 }