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

Bus Error when reading nil values #25

Open
missinglink opened this issue Nov 4, 2022 · 2 comments · May be fixed by #26
Open

Bus Error when reading nil values #25

missinglink opened this issue Nov 4, 2022 · 2 comments · May be fixed by #26

Comments

@missinglink
Copy link

missinglink commented Nov 4, 2022

I have encountered a signal SIGBUS: bus error using txn.RawRead = true when reading keys where the value was set to nil.

A fix for the issue is the following:

 // val.go
 func getBytes(val *C.MDB_val) []byte {
+       if val.mv_size == 0 {
+               return nil
+       }
        return (*[valMaxSize]byte)(val.mv_data)[:val.mv_size:val.mv_size]
 }

The following minimal diff can be used to trigger the error:

diff --git a/lmdb/env_test.go b/lmdb/env_test.go
index afdde18..ddcfc79 100644
--- a/lmdb/env_test.go
+++ b/lmdb/env_test.go
@@ -560,6 +560,12 @@ func setupFlags(t T, flags uint) *Env {
        if err != nil {
                t.Fatalf("setmaxdbs: %v", err)
        }
+
+       err = env.SetMapSize(3298534883328)
+       if err != nil {
+               t.Fatalf("Failed to set map size: %v", err)
+       }
+
        err = env.Open(path, flags, 0664)
        if err != nil {
                t.Fatalf("open: %s", err)
diff --git a/lmdb/txn_test.go b/lmdb/txn_test.go
index eaadaf7..b796558 100644
--- a/lmdb/txn_test.go
+++ b/lmdb/txn_test.go
@@ -1519,3 +1519,50 @@ func openDBI(env *Env, key string, flags uint) (DBI, error) {
        }
        return db, nil
 }
+
+func TestTxn_NilValue(t *testing.T) {
+       env := setup(t)
+       defer clean(env, t)
+
+       err := env.Update(func(txn *Txn) (err error) {
+               db, err := txn.OpenDBI("example", Create)
+               if err != nil {
+                       return err
+               }
+               for i := 0; i < 100000; i++ {
+                       // --------------- note: value is set to nil ---------------
+                       if err = txn.Put(db, []byte(fmt.Sprintf("key%d", i)), nil, 0); err != nil {
+                               return err
+                       }
+               }
+               return nil
+       })
+       if err != nil {
+               t.Errorf("update: %v", err)
+               return
+       }
+
+       err = env.View(func(txn *Txn) (err error) {
+               txn.RawRead = true                    // <---- disabling RawRead doesn't trigger the error
+
+               db, err := txn.OpenDBI("example", 0)
+               cur, err := txn.OpenCursor(db)
+               if err != nil {
+                       return err
+               }
+
+               for k, _, err := cur.Get(nil, nil, First); k != nil; k, _, err = cur.Get(
nil, nil, Next) {
+                       if err != nil {
+                               return err
+                       }
+                       if !bytes.HasPrefix(k, []byte("key")) {
+                               return fmt.Errorf("key: %q", k)
+                       }
+               }
+
+               return nil
+       })
+       if err != nil {
+               t.Errorf("view: %v", err)
+               return
+       }
+}

@AskAlexSharov I'm happy to draft a PR, do you have any insights into whether this is the ideal solution?

@missinglink missinglink linked a pull request Nov 4, 2022 that will close this issue
@AskAlexSharov
Copy link
Collaborator

It's because - this bindings was copied from LMDB bindings. and LMDB didn't support nil value (and we never used it in mdbx). Feel free to create PR

@missinglink
Copy link
Author

This is the lmdb-go repo, sorry for the confusion as I am also using the mdbx repo.

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

Successfully merging a pull request may close this issue.

2 participants