Skip to content

Commit

Permalink
set cap more carefully on unsafe slices
Browse files Browse the repository at this point in the history
Treating a pointer as a pointer to a large array of bytes,
or converting back the other way, isn't totally insane, but
it does create slices with an extremely large cap. This bit
me while I was trying to build the 16-byte packed Container
structure, but it's probably actually worth fixing in general.
  • Loading branch information
seebs authored and vdarulis committed Sep 2, 2020
1 parent 7f38974 commit 4708c36
Showing 1 changed file with 12 additions and 11 deletions.
23 changes: 12 additions & 11 deletions roaring/roaring.go
Original file line number Diff line number Diff line change
Expand Up @@ -1005,17 +1005,17 @@ func (b *Bitmap) unmarshalPilosaRoaring(data []byte) error {
c.array = nil
c.bitmap = nil
runCount := binary.LittleEndian.Uint16(data[offset : offset+runCountHeaderSize])
c.runs = (*[0xFFFFFFF]interval16)(unsafe.Pointer(&data[offset+runCountHeaderSize]))[:runCount]
c.runs = (*[0xFFFFFFF]interval16)(unsafe.Pointer(&data[offset+runCountHeaderSize]))[:runCount:runCount]
opsOffset = int(offset) + runCountHeaderSize + len(c.runs)*interval16Size
case containerArray:
c.runs = nil
c.bitmap = nil
c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[offset]))[:c.n]
c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[offset]))[:c.n:c.n]
opsOffset = int(offset) + len(c.array)*2 // sizeof(uint32)
case containerBitmap:
c.array = nil
c.runs = nil
c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[offset]))[:bitmapN]
c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[offset]))[:bitmapN:bitmapN]
opsOffset = int(offset) + len(c.bitmap)*8 // sizeof(uint64)
}
}
Expand Down Expand Up @@ -2205,14 +2205,14 @@ func (c *Container) arrayWriteTo(w io.Writer) (n int64, err error) {
//}

// Write sizeof(uint16) * cardinality bytes.
nn, err := w.Write((*[0xFFFFFFF]byte)(unsafe.Pointer(&c.array[0]))[:2*c.n])
nn, err := w.Write((*[0xFFFFFFF]byte)(unsafe.Pointer(&c.array[0]))[: 2*c.n : 2*c.n])
return int64(nn), err
}

func (c *Container) bitmapWriteTo(w io.Writer) (n int64, err error) {
statsHit("Container/bitmapWriteTo")
// Write sizeof(uint64) * bitmapN bytes.
nn, err := w.Write((*[0xFFFFFFF]byte)(unsafe.Pointer(&c.bitmap[0]))[:(8 * bitmapN)])
nn, err := w.Write((*[0xFFFFFFF]byte)(unsafe.Pointer(&c.bitmap[0]))[:(8 * bitmapN):(8 * bitmapN)])
return int64(nn), err
}

Expand All @@ -2227,7 +2227,8 @@ func (c *Container) runWriteTo(w io.Writer) (n int64, err error) {
if err != nil {
return 0, err
}
nn, err := w.Write((*[0xFFFFFFF]byte)(unsafe.Pointer(&c.runs[0]))[:interval16Size*len(c.runs)])
runs := c.runs
nn, err := w.Write((*[0xFFFFFFF]byte)(unsafe.Pointer(&runs[0]))[: interval16Size*len(runs) : interval16Size*len(runs)])
return int64(runCountHeaderSize + nn), err
}

Expand Down Expand Up @@ -4152,11 +4153,11 @@ func readOffsets(b *Bitmap, data []byte, pos int, keyN uint32) error {
case containerArray:
c.runs = nil
c.bitmap = nil
c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[offset]))[:c.n]
c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[offset]))[:c.n:c.n]
case containerBitmap:
c.array = nil
c.runs = nil
c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[offset]))[:bitmapN]
c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[offset]))[:bitmapN:bitmapN]
default:
return fmt.Errorf("unsupported container type %d", c.containerType)
}
Expand All @@ -4174,7 +4175,7 @@ func readWithRuns(b *Bitmap, data []byte, pos int, keyN uint32) {
c.array = nil
c.bitmap = nil
runCount := binary.LittleEndian.Uint16(data[pos : pos+runCountHeaderSize])
c.runs = (*[0xFFFFFFF]interval16)(unsafe.Pointer(&data[pos+runCountHeaderSize]))[:runCount]
c.runs = (*[0xFFFFFFF]interval16)(unsafe.Pointer(&data[pos+runCountHeaderSize]))[:runCount:runCount]

for o := range c.runs { // must convert from start:length to start:end :(
c.runs[o].last = c.runs[o].start + c.runs[o].last
Expand All @@ -4183,12 +4184,12 @@ func readWithRuns(b *Bitmap, data []byte, pos int, keyN uint32) {
case containerArray:
c.runs = nil
c.bitmap = nil
c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[pos]))[:c.n]
c.array = (*[0xFFFFFFF]uint16)(unsafe.Pointer(&data[pos]))[:c.n:c.n]
pos += int(c.n * 2)
case containerBitmap:
c.array = nil
c.runs = nil
c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[pos]))[:bitmapN]
c.bitmap = (*[0xFFFFFFF]uint64)(unsafe.Pointer(&data[pos]))[:bitmapN:bitmapN]
pos += bitmapN * 8
}
}
Expand Down

0 comments on commit 4708c36

Please sign in to comment.