Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport of fix race condition in string generator helper into release/1.13.x #19900

3 changes: 3 additions & 0 deletions changelog/19875.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
helper/random: Fix race condition in string generator helper
```
11 changes: 9 additions & 2 deletions helper/random/string_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"math"
"sort"
"sync"
"time"
"unicode"

Expand Down Expand Up @@ -76,7 +77,8 @@ type StringGenerator struct {
Rules serializableRules `mapstructure:"-" json:"rule"` // This is "rule" in JSON so it matches the HCL property type

// CharsetRule to choose runes from. This is computed from the rules, not directly configurable
charset runes
charset runes
charsetLock sync.RWMutex
}

// Generate a random string from the charset and adhering to the provided rules.
Expand Down Expand Up @@ -116,7 +118,10 @@ func (g *StringGenerator) generate(rng io.Reader) (str string, err error) {
// If performance improvements need to be made, this can be changed to read a batch of
// potential strings at once rather than one at a time. This will significantly
// improve performance, but at the cost of added complexity.
candidate, err := randomRunes(rng, g.charset, g.Length)
g.charsetLock.RLock()
charset := g.charset
g.charsetLock.RUnlock()
candidate, err := randomRunes(rng, charset, g.Length)
if err != nil {
return "", fmt.Errorf("unable to generate random characters: %w", err)
}
Expand Down Expand Up @@ -229,6 +234,8 @@ func (g *StringGenerator) validateConfig() (err error) {
merr = multierror.Append(merr, fmt.Errorf("specified rules require at least %d characters but %d is specified", minLen, g.Length))
}

g.charsetLock.Lock()
defer g.charsetLock.Unlock()
// Ensure we have a charset & all characters are printable
if len(g.charset) == 0 {
// Yes this is mutating the generator but this is done so we don't have to compute this on every generation
Expand Down