Skip to content

Bug in mdb_env_open string marshaling — missing null terminator causes random file path #187

@devion-user

Description

@devion-user

nuget 2.0 .netstandard

Hi, I’ve been investigating some intermittent LightningException errors when opening environments, and traced the root cause to the way mdb_env_open is called from managed code.

In the current implementation:

[DllImport("lmdb", CallingConvention = CallingConvention.Cdecl)]
public static extern MDBResultCode mdb_env_open(
[NativeInteger] IntPtr env,
byte[] path,
EnvironmentOpenFlags flags,
UnixAccessMode mode);

internal static MDBResultCode mdb_env_open(
[NativeInteger] IntPtr env,
string path,
EnvironmentOpenFlags flags,
UnixAccessMode mode)
{
byte[] bytes = Encoding.UTF8.GetBytes(path);
return Lmdb.mdb_env_open(env, bytes, flags, mode);
}

The managed wrapper converts the string path to a UTF-8 byte[], but does not append a null terminator.
LMDB expects a const char* that is zero-terminated. Without the trailing \0, the native side reads past the end of the buffer, causing random memory reads and file names like data.mdbo to appear in Process Monitor. This also explains why the error was non-deterministic — it depended on whatever byte happened to follow the managed array in memory.

Fix

Either:

Add a null terminator manually when building the byte array:

byte[] bytes = Encoding.UTF8.GetBytes(path + "\0");

or

Change the P/Invoke to use proper string marshaling:

[DllImport("lmdb", CallingConvention = CallingConvention.Cdecl)]
private static extern MDBResultCode mdb_env_open(
IntPtr env,
[MarshalAs(UnmanagedType.LPUTF8Str)] string path,
EnvironmentOpenFlags flags,
UnixAccessMode mode);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions