Repository: projectdiscovery/goflags (go)

Issue:
DynamicVar incorrect parsing on bool values
when we pass `t,f,true,false,0,1` as dynamic flag values, always returns default value.

ex:
```console
...
flagset.DynamicVar(&options.hasPoc, "poc", "true", "display cves that has public published poc"),
...
$ go run . -poc=false  # hasPoc = true
$ go run . -poc #haPoc=true
```

expected:
```console
$ go run . -poc=false  # hasPoc = false
$ go run . -poc # haPoc=true
```

Pull request:
Fix dynamicvar incorrect parsing on bool values
- closes #150 

Patch:
diff --git a/dynamic_var.go b/dynamic_var.go
index ceff9b2..a8c7546 100644
--- a/dynamic_var.go
+++ b/dynamic_var.go
@@ -16,19 +16,24 @@ type dynamicFlag struct {
 
 func (df *dynamicFlag) Set(value string) error {
 	fieldKind := reflect.TypeOf(df.field).Elem().Kind()
-	var isBoolValue bool
-	if _, err := strconv.ParseBool(value); err == nil {
-		isBoolValue = true
-	}
-	if fieldKind == reflect.Bool && isBoolValue {
-		boolField := df.field.(*bool)
-		*boolField = true
-		return nil
+	var (
+		optionWithoutValue bool
+		pv                 bool
+	)
+	if value == "t" || value == "T" || value == "true" || value == "TRUE" {
+		pv = true
+		optionWithoutValue = true
+	} else if value == "f" || value == "F" || value == "false" || value == "FALSE" {
+		pv = false
 	}
+
 	switch fieldKind {
+	case reflect.Bool:
+		boolField := df.field.(*bool)
+		*boolField = pv
 	case reflect.Int:
 		intField := df.field.(*int)
-		if isBoolValue {
+		if optionWithoutValue {
 			*intField = df.defaultValue.(int)
 			return nil
 		}
@@ -39,7 +44,7 @@ func (df *dynamicFlag) Set(value string) error {
 		*intField = newValue
 	case reflect.Float64:
 		floatField := df.field.(*float64)
-		if isBoolValue {
+		if optionWithoutValue {
 			*floatField = df.defaultValue.(float64)
 			return nil
 		}
@@ -50,14 +55,14 @@ func (df *dynamicFlag) Set(value string) error {
 		*floatField = newValue
 	case reflect.String:
 		stringField := df.field.(*string)
-		if isBoolValue {
+		if optionWithoutValue {
 			*stringField = df.defaultValue.(string)
 			return nil
 		}
 		*stringField = value
 	case reflect.Slice:
 		sliceField := df.field.(*[]string)
-		if isBoolValue {
+		if optionWithoutValue {
 			*sliceField = df.defaultValue.([]string)
 			return nil
 		}
diff --git a/go.mod b/go.mod
index 9629fa6..de4a101 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
 	github.com/gorilla/css v1.0.0 // indirect
 	github.com/microcosm-cc/bluemonday v1.0.25 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/projectdiscovery/utils v0.0.58
+	github.com/projectdiscovery/utils v0.0.60
 	github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
 	golang.org/x/net v0.17.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 31ec68b..f2d3250 100644
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ=
 github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss=
-github.com/projectdiscovery/utils v0.0.58 h1:kk2AkSO84QZc9rDRI8jWA2Iia4uzb4sUcfh4h0xA20I=
-github.com/projectdiscovery/utils v0.0.58/go.mod h1:rsR5Kzjrb+/Yp7JSnEblLk4LfU4zH5Z7wQn8RzaGSdY=
+github.com/projectdiscovery/utils v0.0.60 h1:aIPFjFbOHplk12yy5dLWiuGK9A+sxBeqkMAqzrOrB2M=
+github.com/projectdiscovery/utils v0.0.60/go.mod h1:TVnAjN6sPBwzxqrJO7WPLWlb6OK4RRl39iZStF8/8mw=
 github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
 github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=


Test patch:
diff --git a/dynamic_var_test.go b/dynamic_var_test.go
new file mode 100644
index 0000000..eed51db
--- /dev/null
+++ b/dynamic_var_test.go
@@ -0,0 +1,107 @@
+package goflags
+
+import (
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestDynamicVar(t *testing.T) {
+	t.Run("with bool as type", func(t *testing.T) {
+		var b bool
+		flagSet := NewFlagSet()
+		flagSet.CreateGroup("Option", "option",
+			flagSet.DynamicVar(&b, "kev", false, "kev with or without value"),
+		)
+		os.Args = []string{
+			os.Args[0],
+			"-kev=false",
+		}
+		err := flagSet.Parse()
+		assert.Nil(t, err)
+		assert.Equal(t, false, b)
+		tearDown(t.Name())
+	})
+
+	t.Run("without value for int as type", func(t *testing.T) {
+		var i int
+		flagSet := NewFlagSet()
+		flagSet.CreateGroup("Option", "option",
+			flagSet.DynamicVarP(&i, "concurrency", "c", 25, "concurrency for the process"),
+		)
+		os.Args = []string{
+			os.Args[0],
+			"-c",
+		}
+		err := flagSet.Parse()
+		assert.Nil(t, err)
+		assert.Equal(t, 25, i)
+		tearDown(t.Name())
+	})
+
+	t.Run("with value for int as type", func(t *testing.T) {
+		var i int
+		flagSet := NewFlagSet()
+		flagSet.CreateGroup("Option", "option",
+			flagSet.DynamicVarP(&i, "concurrency", "c", 25, "concurrency for the process"),
+		)
+		os.Args = []string{
+			os.Args[0],
+			"-c=100",
+		}
+		err := flagSet.Parse()
+		assert.Nil(t, err)
+		assert.Equal(t, 100, i)
+		tearDown(t.Name())
+	})
+
+	t.Run("with value for float64 as type", func(t *testing.T) {
+		var f float64
+		flagSet := NewFlagSet()
+		flagSet.CreateGroup("Option", "option",
+			flagSet.DynamicVarP(&f, "percentage", "p", 0.0, "percentage for the process"),
+		)
+		os.Args = []string{
+			os.Args[0],
+			"-p=100.0",
+		}
+		err := flagSet.Parse()
+		assert.Nil(t, err)
+		assert.Equal(t, 100.0, f)
+		tearDown(t.Name())
+	})
+
+	t.Run("with value for string as type", func(t *testing.T) {
+		var s string
+		flagSet := NewFlagSet()
+		flagSet.CreateGroup("Option", "option",
+			flagSet.DynamicVarP(&s, "name", "n", "", "name of the user"),
+		)
+		os.Args = []string{
+			os.Args[0],
+			"-n=test",
+		}
+		err := flagSet.Parse()
+		assert.Nil(t, err)
+		assert.Equal(t, "test", s)
+		tearDown(t.Name())
+	})
+
+	t.Run("with value for string slice as type", func(t *testing.T) {
+		var s []string
+		flagSet := NewFlagSet()
+		flagSet.CreateGroup("Option", "option",
+			flagSet.DynamicVarP(&s, "name", "n", []string{}, "name of the user"),
+		)
+		os.Args = []string{
+			os.Args[0],
+			"-n=test1,test2",
+		}
+		err := flagSet.Parse()
+		assert.Nil(t, err)
+		assert.Equal(t, []string{"test1", "test2"}, s)
+		tearDown(t.Name())
+	})
+
+}