diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2016-03-21 20:42:27 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2016-03-21 20:42:27 +0100 |
commit | 02effd9dc46201df250564cdbbee1ca2291eb8b4 (patch) | |
tree | 7f856a7d3bba34c42a4328c0a7db461494f02989 /hugolib/scratch.go | |
parent | f52b040ee126ec0c48f1d273681a860fe7814314 (diff) |
Protect against concurrent Scratch read and write
Fixes #2005
Diffstat (limited to 'hugolib/scratch.go')
-rw-r--r-- | hugolib/scratch.go | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/hugolib/scratch.go b/hugolib/scratch.go index 29dfd492f..ec0b18420 100644 --- a/hugolib/scratch.go +++ b/hugolib/scratch.go @@ -17,11 +17,13 @@ import ( "github.com/spf13/hugo/helpers" "reflect" "sort" + "sync" ) // Scratch is a writable context used for stateful operations in Page/Node rendering. type Scratch struct { values map[string]interface{} + mu sync.RWMutex } // For single values, Add will add (using the + operator) the addend to the existing addend (if found). @@ -29,6 +31,9 @@ type Scratch struct { // // If the first add for a key is an array or slice, then the next value(s) will be appended. func (c *Scratch) Add(key string, newAddend interface{}) (string, error) { + c.mu.Lock() + defer c.mu.Unlock() + var newVal interface{} existingAddend, found := c.values[key] if found { @@ -59,18 +64,27 @@ func (c *Scratch) Add(key string, newAddend interface{}) (string, error) { // Set stores a value with the given key in the Node context. // This value can later be retrieved with Get. func (c *Scratch) Set(key string, value interface{}) string { + c.mu.Lock() + defer c.mu.Unlock() + c.values[key] = value return "" } // Get returns a value previously set by Add or Set func (c *Scratch) Get(key string) interface{} { + c.mu.RLock() + defer c.mu.RUnlock() + return c.values[key] } // SetInMap stores a value to a map with the given key in the Node context. // This map can later be retrieved with GetSortedMapValues. func (c *Scratch) SetInMap(key string, mapKey string, value interface{}) string { + c.mu.Lock() + defer c.mu.Unlock() + _, found := c.values[key] if !found { c.values[key] = make(map[string]interface{}) @@ -82,6 +96,9 @@ func (c *Scratch) SetInMap(key string, mapKey string, value interface{}) string // GetSortedMapValues returns a sorted map previously filled with SetInMap func (c *Scratch) GetSortedMapValues(key string) interface{} { + c.mu.RLock() + defer c.mu.RUnlock() + if c.values[key] == nil { return nil } |