Skip to content

Commit

Permalink
Merge pull request #5059 from hashicorp/hugo-backport-codeql-017
Browse files Browse the repository at this point in the history
Backport of #5027 onto release/0.17.x
  • Loading branch information
hugoghx authored Aug 30, 2024
2 parents 1e2f070 + db60cef commit 6ac1905
Show file tree
Hide file tree
Showing 17 changed files with 231 additions and 127 deletions.
7 changes: 7 additions & 0 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"io"
"math"
"net"
"net/http"
"net/url"
Expand Down Expand Up @@ -308,6 +309,12 @@ func (c *Config) ReadEnvironment() error {
if err != nil {
return err
}
// maxRetries is a 32-bit unsigned integer stored inside an uint64.
// c.MaxRetries is a signed integer that is at least 32 bits in size.
// Check bounds against lowest denominator before casting.
if maxRetries > math.MaxInt32 {
return fmt.Errorf("max retries must be less than or equal to %d", math.MaxInt32)
}
c.MaxRetries = int(maxRetries)
}

Expand Down
72 changes: 72 additions & 0 deletions api/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
package api

import (
"math"
"os"
"strconv"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestConfigSetAddress(t *testing.T) {
Expand Down Expand Up @@ -79,3 +83,71 @@ func TestConfigSetAddress(t *testing.T) {
})
}
}

func TestReadEnvironmentMaxRetries(t *testing.T) {
tests := []struct {
name string
inp string
expMaxRetries int
expErrContains string
}{
{
name: "invalidNaN",
inp: "bad",
expErrContains: "strconv.ParseUint: parsing \"bad\": invalid syntax",
},
{
name: "invalidNegativeNumber",
inp: "-1",
expErrContains: "strconv.ParseUint: parsing \"-1\": invalid syntax",
},
{
name: "invalidGreaterThanUint32",
inp: strconv.Itoa(math.MaxUint32 + 10),
expErrContains: "strconv.ParseUint: parsing \"4294967305\": value out of range",
},
{
name: "invalidGreaterThanInt32",
inp: strconv.Itoa(math.MaxInt32 + 10),
expErrContains: "max retries must be less than or equal to 2147483647",
},
{
name: "success1",
inp: "0",
expMaxRetries: 0,
},
{
name: "success2",
inp: "10000",
expMaxRetries: 10000,
},
{
name: "successMaxInt32",
inp: strconv.Itoa(math.MaxInt32),
expMaxRetries: math.MaxInt32,
},
{
name: "successNothing",
inp: "",
expMaxRetries: 0,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
os.Setenv(EnvBoundaryMaxRetries, tt.inp)
t.Cleanup(func() { os.Unsetenv(EnvBoundaryMaxRetries) })

var c Config
err := c.ReadEnvironment()
if tt.expErrContains != "" {
require.ErrorContains(t, err, tt.expErrContains)
require.Equal(t, 0, c.MaxRetries)
return
}

require.NoError(t, err)
require.Equal(t, tt.expMaxRetries, c.MaxRetries)
})
}
}
6 changes: 3 additions & 3 deletions internal/cmd/base/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ type Command struct {
FlagSkipCacheDaemon bool
FlagSkipClientAgent bool

FlagClientAgentPort uint
FlagClientAgentPort uint16

FlagScopeId string
FlagScopeName string
Expand All @@ -128,7 +128,7 @@ type Command struct {
FlagAuthMethodId string
FlagHostCatalogId string
FlagCredentialStoreId string
FlagVersion int
FlagVersion int64
FlagRecursive bool
FlagFilter string
FlagTags map[string][]string
Expand Down Expand Up @@ -500,7 +500,7 @@ func (c *Command) FlagSet(bit FlagSetBit) *FlagSets {
Hidden: true,
})

f.UintVar(&UintVar{
f.Uint16Var(&Uint16Var{
Name: "client-agent-port",
Target: &c.FlagClientAgentPort,
Default: 9300,
Expand Down
140 changes: 38 additions & 102 deletions internal/cmd/base/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,70 +98,6 @@ func (b *boolValue) Example() string { return "" }
func (b *boolValue) Hidden() bool { return b.hidden }
func (b *boolValue) IsBoolFlag() bool { return true }

// -- IntVar and intValue
type IntVar struct {
Name string
Aliases []string
Usage string
Default int
Hidden bool
EnvVar string
Target *int
Completion complete.Predictor
}

func (f *FlagSet) IntVar(i *IntVar) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseInt(v, 0, 64); err == nil {
initial = int(i)
}
}

def := ""
if i.Default != 0 {
def = strconv.FormatInt(int64(i.Default), 10)
}

f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newIntValue(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}

type intValue struct {
hidden bool
target *int
}

func newIntValue(def int, target *int, hidden bool) *intValue {
*target = def
return &intValue{
hidden: hidden,
target: target,
}
}

func (i *intValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
if err != nil {
return err
}

*i.target = int(v)
return nil
}

func (i *intValue) Get() any { return int(*i.target) }
func (i *intValue) String() string { return strconv.Itoa(int(*i.target)) }
func (i *intValue) Example() string { return "int" }
func (i *intValue) Hidden() bool { return i.hidden }

// -- Int64Var and int64Value
type Int64Var struct {
Name string
Expand Down Expand Up @@ -226,29 +162,29 @@ func (i *int64Value) String() string { return strconv.FormatInt(int64(*i.target
func (i *int64Value) Example() string { return "int" }
func (i *int64Value) Hidden() bool { return i.hidden }

// -- UintVar && uintValue
type UintVar struct {
// -- Uint64Var and uint64Value
type Uint64Var struct {
Name string
Aliases []string
Usage string
Default uint
Default uint64
Hidden bool
EnvVar string
Target *uint
Target *uint64
Completion complete.Predictor
}

func (f *FlagSet) UintVar(i *UintVar) {
func (f *FlagSet) Uint64Var(i *Uint64Var) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseUint(v, 0, 64); err == nil {
initial = uint(i)
initial = i
}
}

def := ""
if i.Default != 0 {
def = strconv.FormatUint(uint64(i.Default), 10)
strconv.FormatUint(i.Default, 10)
}

f.VarFlag(&VarFlag{
Expand All @@ -257,62 +193,62 @@ func (f *FlagSet) UintVar(i *UintVar) {
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newUintValue(initial, i.Target, i.Hidden),
Value: newUint64Value(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}

type uintValue struct {
type uint64Value struct {
hidden bool
target *uint
target *uint64
}

func newUintValue(def uint, target *uint, hidden bool) *uintValue {
func newUint64Value(def uint64, target *uint64, hidden bool) *uint64Value {
*target = def
return &uintValue{
return &uint64Value{
hidden: hidden,
target: target,
}
}

func (i *uintValue) Set(s string) error {
func (i *uint64Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
if err != nil {
return err
}

*i.target = uint(v)
*i.target = v
return nil
}

func (i *uintValue) Get() any { return uint(*i.target) }
func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i.target), 10) }
func (i *uintValue) Example() string { return "uint" }
func (i *uintValue) Hidden() bool { return i.hidden }
func (i *uint64Value) Get() any { return uint64(*i.target) }
func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i.target), 10) }
func (i *uint64Value) Example() string { return "uint" }
func (i *uint64Value) Hidden() bool { return i.hidden }

// -- Uint64Var and uint64Value
type Uint64Var struct {
// -- Uint16Var and uint16Value
type Uint16Var struct {
Name string
Aliases []string
Usage string
Default uint64
Default uint16
Hidden bool
EnvVar string
Target *uint64
Target *uint16
Completion complete.Predictor
}

func (f *FlagSet) Uint64Var(i *Uint64Var) {
func (f *FlagSet) Uint16Var(i *Uint16Var) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseUint(v, 0, 64); err == nil {
initial = i
if i, err := strconv.ParseUint(v, 0, 16); err == nil {
initial = uint16(i)
}
}

def := ""
if i.Default != 0 {
strconv.FormatUint(i.Default, 10)
strconv.FormatUint(uint64(i.Default), 10)
}

f.VarFlag(&VarFlag{
Expand All @@ -321,38 +257,38 @@ func (f *FlagSet) Uint64Var(i *Uint64Var) {
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newUint64Value(initial, i.Target, i.Hidden),
Value: newUint16Value(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}

type uint64Value struct {
type uint16Value struct {
hidden bool
target *uint64
target *uint16
}

func newUint64Value(def uint64, target *uint64, hidden bool) *uint64Value {
func newUint16Value(def uint16, target *uint16, hidden bool) *uint16Value {
*target = def
return &uint64Value{
return &uint16Value{
hidden: hidden,
target: target,
}
}

func (i *uint64Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
func (i *uint16Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 16)
if err != nil {
return err
}

*i.target = v
*i.target = uint16(v)
return nil
}

func (i *uint64Value) Get() any { return uint64(*i.target) }
func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i.target), 10) }
func (i *uint64Value) Example() string { return "uint" }
func (i *uint64Value) Hidden() bool { return i.hidden }
func (i *uint16Value) Get() any { return uint64(*i.target) }
func (i *uint16Value) String() string { return strconv.FormatUint(uint64(*i.target), 10) }
func (i *uint16Value) Example() string { return "uint" }
func (i *uint16Value) Hidden() bool { return i.hidden }

// -- StringVar and stringValue
type StringVar struct {
Expand Down
Loading

0 comments on commit 6ac1905

Please sign in to comment.