Skip to content

Commit

Permalink
fix race condition in Reader due to concurrent map write
Browse files Browse the repository at this point in the history
```
fatal error: concurrent map writes
github.com/richardlehane/msoleps.addDefaults(...)
	/go/pkg/mod/github.com/richardlehane/msoleps@v1.0.3/sets.go:20
github.com/richardlehane/msoleps.(*Reader).start(0xc001bb1f78, {0xc8a180?, 0xc00037be80?})
	/go/pkg/mod/github.com/richardlehane/msoleps@v1.0.3/msoleps.go:125 +0x2de
github.com/richardlehane/msoleps.(*Reader).Reset(...)
	/go/pkg/mod/github.com/richardlehane/msoleps@v1.0.3/msoleps.go:76
...
```
  • Loading branch information
jonathaningram committed Nov 20, 2023
1 parent b5577ac commit d0092b8
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 15 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ language: go
go:
- 1.2
- stable
- tip
- tip

script:
- go test -v -race ./...
30 changes: 16 additions & 14 deletions msoleps.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,18 @@ func (r *Reader) start(rdr io.Reader) error {
plen += len(psb.idsOffs)
}
r.Property = make([]*Property, plen)
dict, ok := propertySets[pss.fmtidA]
if !ok {
dict = ps.dict
if dict == nil {
dict = make(map[uint32]string)
dicta := make(map[uint32]string)
if propertySet, ok := propertySets[pss.fmtidA]; ok {
for k, v := range propertySet {
dicta[k] = v
}
} else if ps.dict != nil {
dicta = ps.dict
}
dict = addDefaults(dict)
dicta = addDefaults(dicta)
for i, v := range ps.idsOffs {
r.Property[i] = &Property{}
r.Property[i].Name = dict[v.id]
r.Property[i].Name = dicta[v.id]
// don't try to evaluate dictionary property
if v.id == 0x00000000 {
r.Property[i].T = types.Null{}
Expand All @@ -142,18 +143,19 @@ func (r *Reader) start(rdr io.Reader) error {
if pss.numPropertySets != 2 {
return nil
}
dict, ok = propertySets[pss.fmtidB]
if !ok {
dict = psb.dict
if dict == nil {
dict = make(map[uint32]string)
dictb := make(map[uint32]string)
if propertySet, ok := propertySets[pss.fmtidB]; ok {
for k, v := range propertySet {
dictb[k] = v
}
} else if psb.dict != nil {
dictb = psb.dict
}
dict = addDefaults(dict)
dictb = addDefaults(dictb)
for i, v := range psb.idsOffs {
i += len(ps.idsOffs)
r.Property[i] = &Property{}
r.Property[i].Name = dict[v.id]
r.Property[i].Name = dictb[v.id]
// don't try to evaluate dictionary property
if v.id == 0x00000000 {
r.Property[i].T = types.Null{}
Expand Down
15 changes: 15 additions & 0 deletions msoleps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package msoleps

import (
"os"
"sync"
"testing"
)

Expand All @@ -21,6 +22,20 @@ func testFile(t *testing.T, path string) *Reader {
return doc
}

func TestReader_concurrency(t *testing.T) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
_ = testFile(t, testDocSum)
}()
go func() {
defer wg.Done()
_ = testFile(t, testDocSum)
}()
wg.Wait()
}

func TestDocSum(t *testing.T) {
doc := testFile(t, testDocSum)
if len(doc.Property) != 12 {
Expand Down

0 comments on commit d0092b8

Please # to comment.