eliasfano: To fix checkptr fatal error (#697)

```
 go test -race -run=TestEliasFano ./recsplit/eliasfano32
fatal error: checkptr: converted pointer straddles multiple allocations

goroutine 35 [running]:
runtime.throw({0x13bb5bf?, 0x13446ca?})
	runtime/panic.go:1047 +0x5d fp=0xc000137790 sp=0xc000137760 pc=0x108a13d
runtime.checkptrAlignment(0xa9?, 0x0?, 0x0?)
	runtime/checkptr.go:26 +0x6c fp=0xc0001377b0 sp=0xc000137790 pc=0x1059f8c
github.com/ledgerwatch/erigon-lib/recsplit/eliasfano32.Min({0xc00012c280, 0x40, 0x40})
	github.com/ledgerwatch/erigon-lib/recsplit/eliasfano32/elias_fano.go:324 +0x36f fp=0xc000137868 sp=0xc0001377b0 pc=0x133e66f
github.com/ledgerwatch/erigon-lib/recsplit/eliasfano32.TestEliasFano(0x0?)
	github.com/ledgerwatch/erigon-lib/recsplit/eliasfano32/elias_fano_test.go:58
```
This commit is contained in:
Alex Sharov 2022-10-22 10:55:19 +07:00 committed by GitHub
parent 222bb666e9
commit 9819f6af24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 19 deletions

View File

@ -1409,7 +1409,7 @@ func (s *state) Encode(buf []byte) ([]byte, error) {
if err := binary.Write(ee, binary.BigEndian, uint16(len(s.Root))); err != nil {
return nil, fmt.Errorf("encode root len: %w", err)
}
if n, err := ee.Write(s.Root[:]); err != nil || n != len(s.Root) {
if n, err := ee.Write(s.Root); err != nil || n != len(s.Root) {
return nil, fmt.Errorf("encode root: %w", err)
}
d := make([]byte, len(s.Depths))

View File

@ -280,9 +280,8 @@ func (ef *EliasFano) Write(w io.Writer) error {
if _, e := w.Write(numBuf[:]); e != nil {
return e
}
p := (*[maxDataSize]byte)(unsafe.Pointer(&ef.data[0]))
b := (*p)[:]
if _, e := w.Write(b[:len(ef.data)*8]); e != nil {
b := unsafe.Slice((*byte)(unsafe.Pointer(&ef.data[0])), len(ef.data)*uint64Size)
if _, e := w.Write(b); e != nil {
return e
}
return nil
@ -295,17 +294,14 @@ func (ef *EliasFano) AppendBytes(buf []byte) []byte {
buf = append(buf, numBuf[:]...)
binary.BigEndian.PutUint64(numBuf[:], ef.u)
buf = append(buf, numBuf[:]...)
p := (*[maxDataSize]byte)(unsafe.Pointer(&ef.data[0]))
b := (*p)[:]
buf = append(buf, b[:len(ef.data)*8]...)
b := unsafe.Slice((*byte)(unsafe.Pointer(&ef.data[0])), len(ef.data)*uint64Size)
buf = append(buf, b...)
return buf
}
const maxDataSize = 0xFFFFFFFFFFFF //2^48
// Read inputs the state of golomb rice encoding from a reader s
func ReadEliasFano(r []byte) (*EliasFano, int) {
p := (*[maxDataSize / 8]uint64)(unsafe.Pointer(&r[16]))
p := unsafe.Slice((*uint64)(unsafe.Pointer(&r[16])), (len(r)-16)/uint64Size)
ef := &EliasFano{
count: binary.BigEndian.Uint64(r[:8]),
u: binary.BigEndian.Uint64(r[8:16]),
@ -318,10 +314,12 @@ func ReadEliasFano(r []byte) (*EliasFano, int) {
func Max(r []byte) uint64 { return binary.BigEndian.Uint64(r[8:16]) - 1 }
const uint64Size = 8
func Min(r []byte) uint64 {
count := binary.BigEndian.Uint64(r[:8])
u := binary.BigEndian.Uint64(r[8:16])
p := (*[maxDataSize / 8]uint64)(unsafe.Pointer(&r[16]))
p := unsafe.Slice((*uint64)(unsafe.Pointer(&r[16])), (len(r)-16)/uint64Size)
var l uint64
if u/(count+1) == 0 {
l = 0
@ -650,9 +648,8 @@ func (ef *DoubleEliasFano) Write(w io.Writer) error {
if _, e := w.Write(numBuf[:]); e != nil {
return e
}
p := (*[maxDataSize]byte)(unsafe.Pointer(&ef.data[0]))
b := (*p)[:]
if _, e := w.Write(b[:len(ef.data)*8]); e != nil {
b := unsafe.Slice((*byte)(unsafe.Pointer(&ef.data[0])), len(ef.data)*uint64Size)
if _, e := w.Write(b); e != nil {
return e
}
return nil
@ -665,8 +662,7 @@ func (ef *DoubleEliasFano) Read(r []byte) int {
ef.uPosition = binary.BigEndian.Uint64(r[16:24])
ef.cumKeysMinDelta = binary.BigEndian.Uint64(r[24:32])
ef.posMinDelta = binary.BigEndian.Uint64(r[32:40])
p := (*[maxDataSize / 8]uint64)(unsafe.Pointer(&r[40]))
ef.data = p[:]
ef.data = unsafe.Slice((*uint64)(unsafe.Pointer(&r[40])), (len(r)-40)/uint64Size)
ef.deriveFields()
return 40 + 8*len(ef.data)
}

View File

@ -52,10 +52,16 @@ func TestEliasFano(t *testing.T) {
v, ok = ef.Search(11)
assert.True(t, ok, "search4")
assert.Equal(t, uint64(14), v, "search4")
buf := bytes.NewBuffer(nil)
ef.Write(buf)
assert.Equal(t, ef.Max(), Max(buf.Bytes()))
assert.Equal(t, ef.Min(), Min(buf.Bytes()))
assert.Equal(t, ef.AppendBytes(nil), buf.Bytes())
ef2, _ := ReadEliasFano(buf.Bytes())
assert.Equal(t, ef.Min(), ef2.Min())
assert.Equal(t, ef.Max(), ef2.Max())
assert.Equal(t, ef2.Max(), Max(buf.Bytes()))
assert.Equal(t, ef2.Min(), Min(buf.Bytes()))
}
func TestIterator(t *testing.T) {

View File

@ -1375,7 +1375,7 @@ func DecodeAccountBytes(enc []byte) (nonce uint64, balance *uint256.Int, hash []
pos++
if codeHashBytes > 0 {
codeHash := make([]byte, length.Hash)
copy(codeHash[:], enc[pos:pos+codeHashBytes])
copy(codeHash, enc[pos:pos+codeHashBytes])
}
}
return