[bindings] Allow cloning opaque types when inner is NULL
authorMatt Corallo <git@bluematt.me>
Sat, 30 Jan 2021 22:15:22 +0000 (17:15 -0500)
committerMatt Corallo <git@bluematt.me>
Thu, 11 Feb 2021 03:25:10 +0000 (22:25 -0500)
Previously we'd segfault trying to deref the NULL page, but there
is no reason to not simply clone by creating another opaque instance
with a null inner. This comes up specifically when cloning
ChannelSigners as the pubkeys instance is NULL on construction
before get_pubkeys is called.

c-bindings-gen/src/main.rs

index d927d2ae71c816af9f92ee824861103715117d0f..97fc9b8731849df13ddfe041755c6c85e7c39058 100644 (file)
@@ -559,7 +559,8 @@ fn writeln_opaque<W: std::io::Write>(w: &mut W, ident: &syn::Ident, struct_name:
                writeln!(w, "impl Clone for {} {{", struct_name).unwrap();
                writeln!(w, "\tfn clone(&self) -> Self {{").unwrap();
                writeln!(w, "\t\tSelf {{").unwrap();
-               writeln!(w, "\t\t\tinner: Box::into_raw(Box::new(unsafe {{ &*self.inner }}.clone())),").unwrap();
+               writeln!(w, "\t\t\tinner: if self.inner.is_null() {{ std::ptr::null_mut() }} else {{").unwrap();
+               writeln!(w, "\t\t\t\tBox::into_raw(Box::new(unsafe {{ &*self.inner }}.clone())) }},").unwrap();
                writeln!(w, "\t\t\tis_owned: true,").unwrap();
                writeln!(w, "\t\t}}\n\t}}\n}}").unwrap();
                writeln!(w, "#[allow(unused)]").unwrap();
@@ -569,7 +570,7 @@ fn writeln_opaque<W: std::io::Write>(w: &mut W, ident: &syn::Ident, struct_name:
                writeln!(w, "}}").unwrap();
                writeln!(w, "#[no_mangle]").unwrap();
                writeln!(w, "pub extern \"C\" fn {}_clone(orig: &{}) -> {} {{", struct_name, struct_name, struct_name).unwrap();
-               writeln!(w, "\t{} {{ inner: Box::into_raw(Box::new(unsafe {{ &*orig.inner }}.clone())), is_owned: true }}", struct_name).unwrap();
+               writeln!(w, "\torig.clone()").unwrap();
                writeln!(w, "}}").unwrap();
        }