diff options
author | Ben Johnson <benbjohnson@yahoo.com> | 2016-08-18 08:44:57 -0600 |
---|---|---|
committer | Ben Johnson <benbjohnson@yahoo.com> | 2016-08-18 08:44:57 -0600 |
commit | 92410e067395f10c8c93fad62c3e6c4b7aca82f0 (patch) | |
tree | 3f90eabcfd6a26c8bbc021665ab996ed4325c492 | |
parent | Merge pull request #579 from asdine/master (diff) | |
download | dedo-92410e067395f10c8c93fad62c3e6c4b7aca82f0.tar.gz dedo-92410e067395f10c8c93fad62c3e6c4b7aca82f0.tar.xz |
fix Go 1.7 pointer reference bug
This commit fixes a bug where page end-of-header pointers were being
converted to byte slices even when the pointer did not point to
allocated memory. This occurs with pages that have a `page.count`
of zero.
Note: This was not an issue in Go 1.6 but the new Go 1.7 SSA backend
handles `nil` checks differently.
See https://github.com/golang/go/issues/16772
-rw-r--r-- | freelist.go | 18 | ||||
-rw-r--r-- | node.go | 5 | ||||
-rw-r--r-- | page.go | 6 |
3 files changed, 23 insertions, 6 deletions
diff --git a/freelist.go b/freelist.go index 0161948..1b7ba91 100644 --- a/freelist.go +++ b/freelist.go @@ -166,12 +166,16 @@ func (f *freelist) read(p *page) { } // Copy the list of page ids from the freelist. - ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] - f.ids = make([]pgid, len(ids)) - copy(f.ids, ids) + if count == 0 { + f.ids = nil + } else { + ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] + f.ids = make([]pgid, len(ids)) + copy(f.ids, ids) - // Make sure they're sorted. - sort.Sort(pgids(f.ids)) + // Make sure they're sorted. + sort.Sort(pgids(f.ids)) + } // Rebuild the page cache. f.reindex() @@ -189,7 +193,9 @@ func (f *freelist) write(p *page) error { // The page.count can only hold up to 64k elements so if we overflow that // number then we handle it by putting the size in the first element. - if len(ids) < 0xFFFF { + if len(ids) == 0 { + p.count = uint16(len(ids)) + } else if len(ids) < 0xFFFF { p.count = uint16(len(ids)) copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:], ids) } else { @@ -201,6 +201,11 @@ func (n *node) write(p *page) { } p.count = uint16(len(n.inodes)) + // Stop here if there are no items to write. + if p.count == 0 { + return + } + // Loop over each item and write it to the page. b := (*[maxAllocSize]byte)(unsafe.Pointer(&p.ptr))[n.pageElementSize()*len(n.inodes):] for i, item := range n.inodes { @@ -62,6 +62,9 @@ func (p *page) leafPageElement(index uint16) *leafPageElement { // leafPageElements retrieves a list of leaf nodes. func (p *page) leafPageElements() []leafPageElement { + if p.count == 0 { + return nil + } return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:] } @@ -72,6 +75,9 @@ func (p *page) branchPageElement(index uint16) *branchPageElement { // branchPageElements retrieves a list of branch nodes. func (p *page) branchPageElements() []branchPageElement { + if p.count == 0 { + return nil + } return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:] } |