From 2269044fc355c549600b3f6495dfcbb176480f75 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 29 Nov 2021 01:03:22 +0000 Subject: [PATCH] CHECK_ACCESS inner pointers using the new __unmangle_inner_ptr meth --- gen_type_mapping.py | 6 ++++-- genbindings.py | 3 +++ genbindings.sh | 10 +++++++++- java_strings.py | 10 +++++++++- typescript_strings.py | 8 ++++++++ 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/gen_type_mapping.py b/gen_type_mapping.py index 39ee2605..01bd9291 100644 --- a/gen_type_mapping.py +++ b/gen_type_mapping.py @@ -257,9 +257,10 @@ class TypeMappingGenerator: opaque_arg_conv = ty_info.rust_obj + " " + ty_info.var_name + "_conv;\n" opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.inner = (void*)(" + ty_info.var_name + " & (~1));\n" if ty_info.is_ptr and holds_ref: - opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.is_owned = false;" + opaque_arg_conv += ty_info.var_name + "_conv.is_owned = false;\n" else: - opaque_arg_conv = opaque_arg_conv + ty_info.var_name + "_conv.is_owned = (" + ty_info.var_name + " & 1) || (" + ty_info.var_name + " == 0);" + opaque_arg_conv += ty_info.var_name + "_conv.is_owned = (" + ty_info.var_name + " & 1) || (" + ty_info.var_name + " == 0);\n" + opaque_arg_conv += "CHECK_INNER_FIELD_ACCESS_OR_NULL(" + ty_info.var_name + "_conv);" if not is_free and (not ty_info.is_ptr or not holds_ref or ty_info.requires_clone == True) and ty_info.requires_clone != False: if (ty_info.rust_obj.replace("LDK", "") + "_clone") in self.clone_fns: # TODO: This is a bit too naive, even with the checks above, we really need to know if rust wants a ref or not, not just if its pass as a ptr. @@ -290,6 +291,7 @@ class TypeMappingGenerator: opaque_ret_conv_suf += indent + "CHECK((((uint64_t)" + ty_info.var_name + "_var.inner) & 1) == 0); // We rely on a free low bit, malloc guarantees this.\n" opaque_ret_conv_suf += indent + "CHECK((((uint64_t)&" + ty_info.var_name + "_var) & 1) == 0); // We rely on a free low bit, pointer alignment guarantees this.\n" + opaque_ret_conv_suf += "CHECK_INNER_FIELD_ACCESS_OR_NULL(" + ty_info.var_name + "_var);\n" if holds_ref: opaque_ret_conv_suf += indent + ty_info.var_name + "_ref = (uint64_t)" + ty_info.var_name + "_var.inner & ~1;" else: diff --git a/genbindings.py b/genbindings.py index 042f5b92..1d01ac6c 100755 --- a/genbindings.py +++ b/genbindings.py @@ -402,6 +402,9 @@ with open(sys.argv[1]) as in_h, open(f"{sys.argv[2]}/bindings{consts.file_ext}", method_comma_separated_arguments = re_match.group(3) method_arguments = method_comma_separated_arguments.split(',') + if method_name.startswith("__"): + return + is_free = method_name.endswith("_free") if method_name.startswith("COption") or method_name.startswith("CResult"): struct_meth = method_name.rsplit("Z", 1)[0][1:] + "Z" diff --git a/genbindings.sh b/genbindings.sh index 912cc1cd..13f4c6c3 100755 --- a/genbindings.sh +++ b/genbindings.sh @@ -78,7 +78,15 @@ if [ "$4" = "true" ]; then else ./genbindings.py "./lightning.h" src/main/java/org/ldk/impl src/main/java/org/ldk src/main/jni/ $DEBUG_ARG java $4 fi -echo "#define LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ LDKCVec_TransactionOutputsZ" > src/main/jni/bindings.c +rm -f src/main/jni/bindings.c +if [ "$3" = "true" ]; then + echo "#define LDK_DEBUG_BUILD" > src/main/jni/bindings.c +elif [ "$3" = "leaks" ]; then + # For leak checking we use release libldk which doesn't expose + # __unmangle_inner_ptr, but the C code expects to be able to call it. + echo "#define __unmangle_inner_ptr(a) (a)" > src/main/jni/bindings.c +fi +echo "#define LDKCVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ LDKCVec_TransactionOutputsZ" >> src/main/jni/bindings.c echo "#define CVec_C2Tuple_TxidCVec_C2Tuple_u32TxOutZZZZ_free CVec_TransactionOutputsZ_free" >> src/main/jni/bindings.c cat src/main/jni/bindings.c.body >> src/main/jni/bindings.c javac -h src/main/jni src/main/java/org/ldk/enums/*.java src/main/java/org/ldk/impl/*.java diff --git a/java_strings.py b/java_strings.py index a83671db..6e77fc34 100644 --- a/java_strings.py +++ b/java_strings.py @@ -163,6 +163,7 @@ void __attribute__((constructor)) spawn_stderr_redirection() { self.c_file_pfx = self.c_file_pfx + """#define MALLOC(a, _) malloc(a) #define FREE(p) if ((uint64_t)(p) > 4096) { free(p); } #define CHECK_ACCESS(p) +#define CHECK_INNER_FIELD_ACCESS_OR_NULL(v) """ if not DEBUG: self.c_file_pfx += """#define DO_ASSERT(a) (void)(a) @@ -319,7 +320,7 @@ void __wrap_free(void* ptr) { __real_free(ptr); } -static void CHECK_ACCESS(void* ptr) { +static void CHECK_ACCESS(const void* ptr) { DO_ASSERT(!pthread_mutex_lock(&allocation_mtx)); allocation* it = allocation_ll; while (it->ptr != ptr) { @@ -336,6 +337,13 @@ static void CHECK_ACCESS(void* ptr) { } DO_ASSERT(!pthread_mutex_unlock(&allocation_mtx)); } +#define CHECK_INNER_FIELD_ACCESS_OR_NULL(v) \\ + if (v.is_owned && v.inner != NULL) { \\ + const void *p = __unmangle_inner_ptr(v.inner); \\ + if (p != NULL) { \\ + CHECK_ACCESS(p); \\ + } \\ + } void* __real_realloc(void* ptr, size_t newlen); void* __wrap_realloc(void* ptr, size_t len) { diff --git a/typescript_strings.py b/typescript_strings.py index 270eeccc..8a83ae4a 100644 --- a/typescript_strings.py +++ b/typescript_strings.py @@ -124,6 +124,7 @@ void free(void *ptr); #define DO_ASSERT(a) (void)(a) #define CHECK(a) #define CHECK_ACCESS(p) +#define CHECK_INNER_FIELD_ACCESS_OR_NULL(v) """ else: self.c_file_pfx = self.c_file_pfx + """ @@ -189,6 +190,13 @@ static void CHECK_ACCESS(void* ptr) { } } } +#define CHECK_INNER_FIELD_ACCESS_OR_NULL(v) \\ + if (v.is_owned && v.inner != NULL) { \\ + const void *p = __unmangle_inner_ptr(v.inner); \\ + if (p != NULL) { \\ + CHECK_ACCESS(p); \\ + } \\ + } void* __wrap_malloc(size_t len) { void* res = __real_malloc(len); -- 2.30.2