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  }