fusesource / leveldbjni

A Java Native Interface to LevelDB
BSD 3-Clause "New" or "Revised" License
536 stars 143 forks source link

DBIterator.hasPrev() causes invalid memory access exception #14

Closed abramsm closed 11 years ago

abramsm commented 12 years ago

Creating a simple test that calls iterator.hasPrev() produces a memory access violation. Is hasPrev() supported?

Example error:

Invalid memory access of location 0x10 rip=0x119586f16

KciNKh commented 12 years ago

Maybe this patch solve this problem:

diff --git a/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDBIterator.java b/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDBIterator.java
index 0bfd46f..35a94d5 100644
--- a/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDBIterator.java
+++ b/leveldbjni/src/main/java/org/fusesource/leveldbjni/internal/JniDBIterator.java
@@ -112,7 +112,11 @@ public class JniDBIterator implements DBIterator {
             try {
                 return iterator.isValid();
             } finally {
-                iterator.next();
+                if (iterator.isValid()) {
+                    iterator.next();
+                } else {
+                    iterator.seekToFirst();
+                }
             }
         } catch (NativeDB.DBException e) {
             throw new RuntimeException(e);
@@ -125,7 +129,11 @@ public class JniDBIterator implements DBIterator {
             try {
                 return peekNext();
             } finally {
-                iterator.next();
+                if (iterator.isValid()) {
+                    iterator.next();
+                } else {
+                    iterator.seekToFirst();
+                }
             }
         } catch (NativeDB.DBException e) {
             throw new RuntimeException(e);
yingbo commented 11 years ago

It fixes the problem. I tried install it on maven, got an error and the patch fixed it! Thanks!

ethlo commented 11 years ago

This is pretty ugly, yes. Please fix it :+1:

A fatal error has been detected by the Java Runtime Environment:

SIGSEGV (0xb) at pc=0x00007ff3364b04c4, pid=7036, tid=140683021571840

JRE version: 7.0_09-b30 Java VM: OpenJDK 64-Bit Server VM (23.2-b09 mixed mode linux-amd64 compressed oops) Problematic frame: C [libleveldbjni-64-1.4.so+0x394c4] leveldb::(anonymous namespace)::MergingIterator::key() const+0x4

Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again

If you would like to submit a bug report, please include instructions on how to reproduce the bug and visit: https://bugs.launchpad.net/ubuntu/+source/openjdk-7/ The crash happened outside the Java Virtual Machine in native code. See problematic frame for where to report the bug.

--------------- T H R E A D ---------------

Current thread (0x00007ff34800e800): JavaThread "main" [_thread_in_native, id=7042, stack(0x00007ff35176d000,0x00007ff35186e000)]

siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x0000000000000010

Registers: RAX=0x00007ff3366ce7f0, RBX=0x00007ff348c1c658, RCX=0x0000000000000031, RDX=0x0000000000000000 RSP=0x00007ff35186ad98, RBP=0x00007ff348c1c600, RSI=0x00007ff35186ae40, RDI=0x00007ff348c1c530 R8 =0x0000000040000000, R9 =0x0000000000000000, R10=0x00007ff345011f64, R11=0x00007ff33649e8e0 R12=0x0000000000000000, R13=0x00000006bd6fdff0, R14=0x00007ff35186ae58, R15=0x00007ff34800e800 RIP=0x00007ff3364b04c4, EFLAGS=0x0000000000010297, CSGSFS=0x0000000000000033, ERR=0x0000000000000004 TRAPNO=0x000000000000000e

Top of Stack: (sp=0x00007ff35186ad98) 0x00007ff35186ad98: 00007ff33649e8fd 00000006bd62f8f9 0x00007ff35186ada8: 00007ff35186ae00 00000006bd633080 0x00007ff35186adb8: 0000000000000000 0000000000000000 0x00007ff35186adc8: 00000006bd6fdff0 00007ff35186ae30 0x00007ff35186add8: 00007ff345011f90 00007ff345006158 0x00007ff35186ade8: 0000000000000000 00007ff35186adf0 0x00007ff35186adf8: 0000000000000000 00007ff35186ae58 0x00007ff35186ae08: 00000006bd6fe828 0000000000000000 0x00007ff35186ae18: 00000006bd6fdff0 0000000000000000 0x00007ff35186ae28: 00007ff35186ae50 00007ff35186aea0 0x00007ff35186ae38: 00007ff345006158 000000079a8f4558 0x00007ff35186ae48: 00007ff34500edd8 00007ff348c1c600 0x00007ff35186ae58: 000000079a938f80 00007ff35186ae60 0x00007ff35186ae68: 00000006bd6f95a8 00007ff35186aeb0 0x00007ff35186ae78: 00000006bd6f9e08 0000000000000000 0x00007ff35186ae88: 00000006bd6f95d0 00007ff35186ae50 0x00007ff35186ae98: 00007ff35186aeb0 00007ff35186aef8 0x00007ff35186aea8: 00007ff345006158 000000079a938f80 0x00007ff35186aeb8: 00007ff35186aeb8 00000006bd6f6f07 0x00007ff35186aec8: 00007ff35186af18 00000006bd6f7720 0x00007ff35186aed8: 0000000000000000 00000006bd6f6f48 0x00007ff35186aee8: 00007ff35186aeb0 00007ff35186af18 0x00007ff35186aef8: 00007ff35186af60 00007ff345006afe 0x00007ff35186af08: 0000000000000000 0000000000000000 0x00007ff35186af18: 000000079a938f58 00007ff35186af20 0x00007ff35186af28: 00000006bd6f4b0c 00007ff35186af70 0x00007ff35186af38: 00000006bd6f52e8 0000000000000000 0x00007ff35186af48: 00000006bd6f4b28 00007ff35186af18 0x00007ff35186af58: 00007ff35186af70 00007ff35186afc0 0x00007ff35186af68: 00007ff345006afe 000000079a938f30 0x00007ff35186af78: 000000079a939058 00007ff35186af80 0x00007ff35186af88: 00000006bd65140e 00007ff35186afd0

Instructions: (pc=0x00007ff3364b04c4) 0x00007ff3364b04a4: c5 48 89 df e8 9b db fd ff eb eb 90 31 c0 48 83 0x00007ff3364b04b4: 7f 40 00 0f 95 c0 c3 90 0f 1f 40 00 48 8b 57 40 0x00007ff3364b04c4: 48 8b 42 10 48 8b 52 18 c3 90 66 90 48 83 ec 38 0x00007ff3364b04d4: 48 8b 47 40 48 8b 38 48 8b 07 ff 50 48 48 83 c4

Register to memory mapping:

RAX=0x00007ff3366ce7f0: <offset 0x2577f0> in /tmp/libleveldbjni-64-1.4.so at 0x00007ff336477000 RBX=0x00007ff348c1c658 is an unknown value RCX=0x0000000000000031 is an unknown value RDX=0x0000000000000000 is an unknown value RSP=0x00007ff35186ad98 is pointing into the stack for thread: 0x00007ff34800e800 RBP=0x00007ff348c1c600 is an unknown value RSI=0x00007ff35186ae40 is pointing into the stack for thread: 0x00007ff34800e800 RDI=0x00007ff348c1c530 is an unknown value R8 =0x0000000040000000 is an unknown value R9 =0x0000000000000000 is an unknown value R10=0x00007ff345011f64 is an Interpreter codelet method entry point (kind = native) [0x00007ff345011d00, 0x00007ff345012540] 2112 bytes R11=0x00007ff33649e8e0: <offset 0x278e0> in /tmp/libleveldbjni-64-1.4.so at 0x00007ff336477000 R12=0x0000000000000000 is an unknown value R13=0x00000006bd6fdff0 is an oop {method}

Stack: [0x00007ff35176d000,0x00007ff35186e000], sp=0x00007ff35186ad98, free space=1015k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) C [libleveldbjni-64-1.4.so+0x394c4] leveldb::(anonymous namespace)::MergingIterator::key() const+0x4

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) j org.fusesource.leveldbjni.internal.NativeIterator$IteratorJNI.Next(J)V+0 j org.fusesource.leveldbjni.internal.NativeIterator.next()V+8 j org.fusesource.leveldbjni.internal.JniDBIterator.hasPrev()Z+31

phraktle commented 11 years ago

Any chance of rmerging this into the master? This is a pretty serious problem, and there's no convenient workaround from cilent code...

chirino commented 11 years ago

This issue is now fixed in master. KciNKh's patch has been applied.

phraktle commented 11 years ago

I don't think this patch was included in the 1.6 release. Can you please issue an update that includes this change?

Below is a disassembly of JniDBIterator in leveldbjni-all-1.6.jar:

/*     */   public boolean hasPrev() {
/* 108 */     if (!(this.iterator.isValid()))
/* 109 */       return false;
/*     */     try {
/* 111 */       this.iterator.prev();
/*     */       try {
/* 113 */         boolean bool = this.iterator.isValid();
/*     */ 
/* 115 */         return bool; } finally { this.iterator.next();
/*     */       }
/*     */     } catch (NativeDB.DBException e) {
/* 118 */       throw new RuntimeException(e);
/*     */     }
/*     */   }
planck0 commented 11 years ago

I have this issue in the 1.6 release, but only if the iterator happens to be at the first item of the Database and the database is not empty. In all other cases hasPrev() worksfine.

I then get (win7):

A fatal error has been detected by the Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000007fefb212e84, pid=800, tid=1584

JRE version: 7.0_17-b02 Java VM: Java HotSpot(TM) 64-Bit Server VM (23.7-b01 mixed mode windows-amd64 compressed oops) Problematic frame: C [leveldbjni-64-1.6.dll+0x22e84] JNI_OnLoad+0x1ead4'

Etc

chirino commented 11 years ago

Could you check to see if it happens against the 1.6.1 release?

planck0 commented 11 years ago

Wow, thanks for the incredible fast reply. But you're right. I didn't even see you posted a new version, but 1.6.1 fixes it. Thanks!