[PATCH] D99393: [OCaml] Fix a possible crash in llvm_struct_name

Josh Berdine via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 25 17:04:50 PDT 2021


jberdine created this revision.
jberdine added a reviewer: vaivaswatha.
Herald added a reviewer: whitequark.
jberdine requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

The implementation of `llvm_struct_name` before this diff calls
`caml_copy_string`, which allocates, while the `result` local variable
points to a block allocated by `caml_alloc_small` that has not yet
been initialized. If the allocation in `caml_copy_string` triggers a
garbage collection, then the GC root `result` contains a pointer to
uninitialized data, which may crash the GC or lead to a memory
corruption.

This diff fixes this by allocating and initializing the string first
and then allocating and initializing the option, thereby leaving no
dangling pointers when allocations are made.

The conversion from a C string to an OCaml string option is refactored
into a function, `cstr_to_string_option`. This function is also used
to simplify the definitions of `llvm_get_mdstring` and
`llvm_string_of_const`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99393

Files:
  llvm/bindings/ocaml/llvm/llvm_ocaml.c


Index: llvm/bindings/ocaml/llvm/llvm_ocaml.c
===================================================================
--- llvm/bindings/ocaml/llvm/llvm_ocaml.c
+++ llvm/bindings/ocaml/llvm/llvm_ocaml.c
@@ -56,6 +56,18 @@
   CAMLreturn(String);
 }
 
+CAMLprim value cstr_to_string_option(const char *CStr, mlsize_t Len) {
+  CAMLparam0();
+  CAMLlocal2 (Option, String);
+  if (!CStr)
+    CAMLreturn(Val_int(0));
+  String = caml_alloc_string(Len);
+  memcpy((char *)String_val(String), CStr, Len);
+  Option = caml_alloc_small(1, 0);
+  Store_field(Option, 0, (value)String);
+  CAMLreturn(Option);
+}
+
 void llvm_raise(value Prototype, char *Message) {
   CAMLparam1(Prototype);
   caml_raise_with_arg(Prototype, llvm_string_of_message(Message));
@@ -529,17 +541,11 @@
 }
 
 /* lltype -> string option */
-CAMLprim value llvm_struct_name(LLVMTypeRef Ty)
-{
-  CAMLparam0();
-  CAMLlocal1(result);
-  const char *C = LLVMGetStructName(Ty);
-  if (C) {
-    result = caml_alloc_small(1, 0);
-    Store_field(result, 0, caml_copy_string(C));
-    CAMLreturn(result);
-  }
-  CAMLreturn(Val_int(0));
+CAMLprim value llvm_struct_name(LLVMTypeRef Ty) {
+  const char * CStr = LLVMGetStructName(Ty);
+  if (!CStr)
+    return Val_int(0);
+  return cstr_to_string_option (CStr, strlen(CStr));
 }
 
 /* lltype -> lltype array */
@@ -877,19 +883,8 @@
 
 /* llvalue -> string option */
 CAMLprim value llvm_get_mdstring(LLVMValueRef V) {
-  CAMLparam0();
-  CAMLlocal2(Option, Str);
-  const char *S;
   unsigned Len;
-
-  if ((S = LLVMGetMDString(V, &Len))) {
-    Str = caml_alloc_string(Len);
-    memcpy((char *)String_val(Str), S, Len);
-    Option = alloc(1,0);
-    Store_field(Option, 0, Str);
-    CAMLreturn(Option);
-  }
-  CAMLreturn(Val_int(0));
+  return cstr_to_string_option(LLVMGetMDString(V, &Len), Len);
 }
 
 CAMLprim value llvm_get_mdnode_operands(LLVMValueRef V) {
@@ -1045,21 +1040,11 @@
 
 /* llvalue -> string option */
 CAMLprim value llvm_string_of_const(LLVMValueRef Const) {
-  const char *S;
   size_t Len;
-  CAMLparam0();
-  CAMLlocal2(Option, Str);
-
   if(LLVMIsAConstantDataSequential(Const) && LLVMIsConstantString(Const)) {
-    S = LLVMGetAsString(Const, &Len);
-    Str = caml_alloc_string(Len);
-    memcpy((char *)String_val(Str), S, Len);
-
-    Option = alloc(1, 0);
-    Field(Option, 0) = Str;
-    CAMLreturn(Option);
+    return cstr_to_string_option(LLVMGetAsString(Const, &Len), Len);
   } else {
-    CAMLreturn(Val_int(0));
+    return Val_int(0);
   }
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D99393.333468.patch
Type: text/x-patch
Size: 2496 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210326/627ccbf8/attachment-0001.bin>


More information about the llvm-commits mailing list