Debug crash with enum and FFI


#1

Hello guys,

I am trying to create plugin for Janus Gateway with Rust.
Janus Gateway is written in C, so, I generated Rust bindings using bindgen tool.

Unfortunately, I got a crash (with core dump). I very new to such a low level programming (I mostly do Ruby, but now I am very interested in Rust and C). So, I don’t know how to debug it properly.

I got a code like this (I remain only relevant parts)

extern "C" fn janus_echotest_handle_message(
    handle: *mut Session,
    transaction: *mut c_char,
    message: *mut json_t,
    jsep: *mut json_t,
) -> *mut PluginResult {

    let plugin_handle = unsafe { &*handle };
    let transaction = unsafe { std::ffi::CStr::from_ptr(transaction) };
    let message = unsafe { *message };
    let jsep = unsafe { &*jsep };

    println!("{:?}", plugin_handle);
    println!("{:?}", transaction);
    println!("{:?}", message);
    println!("{:?}", jsep); // crash occurs here

    ...
}

json_t comes from libjansson.
This is corresponding autogenerated bindings:

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum json_type {
    JSON_OBJECT = 0,
    JSON_ARRAY = 1,
    JSON_STRING = 2,
    JSON_INTEGER = 3,
    JSON_REAL = 4,
    JSON_TRUE = 5,
    JSON_FALSE = 6,
    JSON_NULL = 7,
}

#[repr(C)]
#[derive(Debug, Copy)]
pub struct json_t {
    pub type_: json_type,
    pub refcount: usize,
}

impl Clone for json_t {
    fn clone(&self) -> Self { *self }
}

I run Janus Gateway as /opt/janus/bin/janus. So, I thought that I should attach core dump to it like

gdb /opt/janus/bin/janus -c core

It gives the following output:

Reading symbols from /opt/janus/bin/janus...done.
[New LWP 2083]
[New LWP 2069]
[New LWP 2070]
[New LWP 2071]
[New LWP 2072]
[New LWP 2082]
[New LWP 2074]
[New LWP 2077]
[New LWP 2079]
[New LWP 2080]
[New LWP 2078]
[New LWP 2076]
[New LWP 2075]
[New LWP 2073]
[New LWP 2068]
[New LWP 2085]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/opt/janus/bin/janus'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f57d84c141a in janus_echotest::janus::{{impl}}::fmt (self=0x0, __arg_0=0x7f57b6ffbff8) at src/bindings.rs:7
7	#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
[Current thread is 1 (Thread 0x7f57b6ffd700 (LWP 2083))]

Could you please help me to understand what is going on?
What the problem is and how should I investigate it myself?

Thanks.


#2

Looks like you were called with one of your pointer parameters as null, so it would be invalid for you to dereference this.


#3

Thank you. Looks like you are totally right.
I didn’t want to add “premature” NULL checks.
I thought if there would a problem I would just add the checks. And now I completely forgot about it.