nuclei/pkg/fuzz/type.go
Dwi Siswanto 622c5503fa
perf(*): replace encoding/json w/ sonic or go-json (fallback) (#6019)
* perf(*): replace `encoding/json` w/ sonic

Signed-off-by: Dwi Siswanto <git@dw1.io>

* feat(utils): add `json` pkg (sonic wrapper)

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore(*): use `sonic` wrapper instead

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore(*): replace `sonic.ConfigStd` -> `json` (wrapper)

Signed-off-by: Dwi Siswanto <git@dw1.io>

* test(model): adjust expected marshal'd JSON

Signed-off-by: Dwi Siswanto <git@dw1.io>

* feat(json): dynamic backend; `sonic` -> `go-json` (fallback)

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore(json): merge config - as its not usable

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore(json): rm go version constraints

Signed-off-by: Dwi Siswanto <git@dw1.io>

* chore: go mod tidy

Signed-off-by: Dwi Siswanto <git@dw1.io>

---------

Signed-off-by: Dwi Siswanto <git@dw1.io>
2025-02-11 03:01:37 +05:30

121 lines
2.6 KiB
Go

package fuzz
import (
"fmt"
"github.com/invopop/jsonschema"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
mapsutil "github.com/projectdiscovery/utils/maps"
"gopkg.in/yaml.v2"
)
var (
_ json.JSONCodec = &SliceOrMapSlice{}
_ yaml.Marshaler = &SliceOrMapSlice{}
_ yaml.Unmarshaler = &SliceOrMapSlice{}
)
type ValueOrKeyValue struct {
Key string
Value string
OriginalPayload string
}
func (v *ValueOrKeyValue) IsKV() bool {
return v.Key != ""
}
type SliceOrMapSlice struct {
Value []string
KV *mapsutil.OrderedMap[string, string]
}
func (v SliceOrMapSlice) JSONSchemaExtend(schema *jsonschema.Schema) *jsonschema.Schema {
schema = &jsonschema.Schema{
Title: schema.Title,
Description: schema.Description,
Type: "array",
Items: &jsonschema.Schema{
OneOf: []*jsonschema.Schema{
{
Type: "string",
},
{
Type: "object",
},
},
},
}
return schema
}
func (v SliceOrMapSlice) JSONSchema() *jsonschema.Schema {
gotType := &jsonschema.Schema{
Title: "Payloads of Fuzz Rule",
Description: "Payloads to perform fuzzing substitutions with.",
Type: "array",
Items: &jsonschema.Schema{
OneOf: []*jsonschema.Schema{
{
Type: "string",
},
{
Type: "object",
},
},
},
}
return gotType
}
// UnmarshalJSON implements json.Unmarshaler interface.
func (v *SliceOrMapSlice) UnmarshalJSON(data []byte) error {
// try to unmashal as a string and fallback to map
if err := json.Unmarshal(data, &v.Value); err == nil {
return nil
}
err := json.Unmarshal(data, &v.KV)
if err != nil {
return fmt.Errorf("object can be a key:value or a string")
}
return nil
}
// MarshalJSON implements json.Marshaler interface.
func (v SliceOrMapSlice) MarshalJSON() ([]byte, error) {
if v.KV != nil {
return json.Marshal(v.KV)
}
return json.Marshal(v.Value)
}
// UnmarshalYAML implements yaml.Unmarshaler interface.
func (v *SliceOrMapSlice) UnmarshalYAML(callback func(interface{}) error) error {
// try to unmarshal it as a string and fallback to map
if err := callback(&v.Value); err == nil {
return nil
}
// try with a mapslice
var node yaml.MapSlice
if err := callback(&node); err == nil {
tmpx := mapsutil.NewOrderedMap[string, string]()
// preserve order
for _, v := range node {
tmpx.Set(v.Key.(string), v.Value.(string))
}
v.KV = &tmpx
return nil
}
return fmt.Errorf("object can be a key:value or a string")
}
// MarshalYAML implements yaml.Marshaler interface.
func (v SliceOrMapSlice) MarshalYAML() (any, error) {
if v.KV != nil {
return v.KV, nil
}
return v.Value, nil
}