Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of unsafe is unsound #9

Closed
Stebalien opened this issue Aug 23, 2019 · 8 comments
Closed

Use of unsafe is unsound #9

Stebalien opened this issue Aug 23, 2019 · 8 comments

Comments

@Stebalien
Copy link

Casting to a uintptr, saving the uintptr, and then casting it back is unsound.

bbloom/bbloom.go

Lines 80 to 88 in e2d15f3

func NewWithBoolset(bs *[]byte, locs uint64) (bloomfilter Bloom) {
bloomfilter = New(float64(len(*bs)<<3), float64(locs))
ptr := uintptr(unsafe.Pointer(&bloomfilter.bitset[0]))
for _, b := range *bs {
*(*uint8)(unsafe.Pointer(ptr)) = b
ptr++
}
return bloomfilter
}

bbloom/bbloom.go

Lines 232 to 246 in e2d15f3

func (bl Bloom) JSONMarshal() []byte {
bloomImEx := bloomJSONImExport{}
bloomImEx.SetLocs = uint64(bl.setLocs)
bloomImEx.FilterSet = make([]byte, len(bl.bitset)<<3)
ptr := uintptr(unsafe.Pointer(&bl.bitset[0]))
for i := range bloomImEx.FilterSet {
bloomImEx.FilterSet[i] = *(*byte)(unsafe.Pointer(ptr))
ptr++
}
data, err := json.Marshal(bloomImEx)
if err != nil {
log.Fatal("json.Marshal failed: ", err)
}
return data
}

@AndreasBriese
Copy link
Owner

AndreasBriese commented Aug 23, 2019 via email

@Stebalien
Copy link
Author

I'm saying that converting a uintptr back to a unsafe.Pointer across multiple statements is unsound.

https://golang.org/pkg/unsafe/#Pointer

@AndreasBriese
Copy link
Owner

AndreasBriese commented Aug 23, 2019 via email

@Stebalien
Copy link
Author

the ptr is not carried around multiple statements. the ptr is locally casted, incremented and changed by a bitoperation. This behaviour is not volatile at runtime - at least not in the golang binary.

Take a look at the functions I'm quoting in the issue description. You can't save a uintptr to the stack then convert it back to an unsafe.Pointer later.

Take the JSONMarshal function. The garbage collector is allowed to pause the function between lines 236 and 238, move anything it wants, update the pointers, then restart the function. At that point, the saved uintptr could be pointing at anything.

@AndreasBriese
Copy link
Owner

AndreasBriese commented Aug 23, 2019 via email

@Stebalien
Copy link
Author

That's exactly what I'm looking at:

Note that both conversions must appear in the same expression, with only the intervening arithmetic between them:
// INVALID: uintptr cannot be stored in variable
// before conversion back to Pointer.
u := uintptr(p)
p = unsafe.Pointer(u + offset)

@AndreasBriese
Copy link
Owner

AndreasBriese commented Aug 23, 2019

I considered Your comments and opted for the way documented at https://golang.org/pkg/unsafe/#Pointer
in the latest push.
5f4d56d#diff-eebbf48a54279308068f73108bc90f16
Thx for discussing this thoroughly. That should solve the issues you pointed at.
Andreas

@Stebalien
Copy link
Author

That looks safe. Thanks!

jarifibrahim pushed a commit to dgraph-io/badger that referenced this issue Apr 22, 2020
This commit fixes the `checkptr` issue reported in
#1294.
The `checkptr` issue was fixed in the upstream library
AndreasBriese/bbloom#9 . 

This PR updates the go.mod file to use the latest
version of `AndreasBriese/bbloom`
mYmNeo pushed a commit to mYmNeo/badger that referenced this issue Jan 16, 2023
This commit fixes the `checkptr` issue reported in
dgraph-io#1294.
The `checkptr` issue was fixed in the upstream library
AndreasBriese/bbloom#9 . 

This PR updates the go.mod file to use the latest
version of `AndreasBriese/bbloom`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants