Skip to content

Commit

Permalink
Merge pull request #108 from membraneframework/nested-struct-segfault
Browse files Browse the repository at this point in the history
Nested struct list segfault
  • Loading branch information
bartkrak authored Mar 4, 2024
2 parents 7615a5e + 27e1f63 commit edc3ad1
Show file tree
Hide file tree
Showing 19 changed files with 1,748 additions and 335 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ defmodule MyApp.Mixfile do

defp deps() do
[
{:unifex, "~>> 1.1.1"}
{:unifex, "~>> 1.1.3"}
]
end
end
Expand Down
11 changes: 11 additions & 0 deletions lib/unifex/app.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule Unifex.App do
@moduledoc false
use Application

@impl true
def start(_type, _args) do
children = [Unifex.Counter]
opts = [strategy: :one_for_one, name: __MODULE__]
Supervisor.start_link(children, opts)
end
end
51 changes: 30 additions & 21 deletions lib/unifex/code_generator/base_types/list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ defmodule Unifex.CodeGenerator.BaseTypes.List do

@impl true
def generate_destruction(name, ctx) do
counter_value = Unifex.Counter.get_and_increment()

~g"""
if(#{name} != NULL) {
for(unsigned int i = 0; i < #{name}_length; i++) {
#{BaseType.generate_destruction(ctx.subtype, :"#{name}[i]", ctx.generator, ctx)}
for(unsigned int i_#{counter_value} = 0; i_#{counter_value} < #{name}_length; i_#{counter_value}++) {
#{BaseType.generate_destruction(ctx.subtype, :"#{name}[i_#{counter_value}]", ctx.generator, ctx)}
}
unifex_free(#{name});
}
Expand All @@ -49,13 +51,15 @@ defmodule Unifex.CodeGenerator.BaseTypes.List do

@impl true
def generate_arg_serialize(name, ctx) do
counter_value = Unifex.Counter.get_and_increment()

~g"""
({
ERL_NIF_TERM list = enif_make_list(env, 0);
for(int i = #{name}_length-1; i >= 0; i--) {
for(int i_#{counter_value} = #{name}_length-1; i_#{counter_value} >= 0; i_#{counter_value}--) {
list = enif_make_list_cell(
env,
#{BaseType.generate_arg_serialize(ctx.subtype, :"#{name}[i]", ctx.generator, ctx)},
#{BaseType.generate_arg_serialize(ctx.subtype, :"#{name}[i_#{counter_value}]", ctx.generator, ctx)},
list
);
}
Expand All @@ -66,6 +70,7 @@ defmodule Unifex.CodeGenerator.BaseTypes.List do

@impl true
def generate_arg_parse(arg, var_name, ctx) do
counter_value = Unifex.Counter.get_and_increment()
elem_name = :"#{Unifex.CodeGenerator.Utils.sanitize_var_name("#{var_name}")}_i"

len_var_name = "#{var_name}_length"
Expand All @@ -83,12 +88,12 @@ defmodule Unifex.CodeGenerator.BaseTypes.List do
}
ERL_NIF_TERM list = #{arg};
for(unsigned int i = 0; i < #{len_var_name}; i++) {
for(unsigned int i_#{counter_value} = 0; i_#{counter_value} < #{len_var_name}; i_#{counter_value}++) {
ERL_NIF_TERM elem;
enif_get_list_cell(env, list, &elem, &list);
#{native_type} #{elem_name} = #{var_name}[i];
#{native_type} #{elem_name} = #{var_name}[i_#{counter_value}];
#{BaseType.generate_arg_parse(subtype, elem_name, ~g<elem>, postproc_fun, generator, ctx)}
#{var_name}[i] = #{elem_name};
#{var_name}[i_#{counter_value}] = #{elem_name};
}
}
get_list_length_result;
Expand All @@ -104,11 +109,13 @@ defmodule Unifex.CodeGenerator.BaseTypes.List do

@impl true
def generate_arg_serialize(name, ctx) do
counter_value = Unifex.Counter.get_and_increment()

~g"""
({
ei_x_encode_list_header(out_buff, #{name}_length);
for(unsigned int i = 0; i < #{name}_length; i++) {
#{BaseType.generate_arg_serialize(ctx.subtype, :"#{name}[i]", ctx.generator, ctx)}
for(unsigned int i_#{counter_value} = 0; i_#{counter_value} < #{name}_length; i_#{counter_value}++) {
#{BaseType.generate_arg_serialize(ctx.subtype, :"#{name}[i_#{counter_value}]", ctx.generator, ctx)}
}
ei_x_encode_empty_list(out_buff);
});
Expand All @@ -117,7 +124,9 @@ defmodule Unifex.CodeGenerator.BaseTypes.List do

@impl true
def generate_arg_parse(arg, var_name, ctx) do
elem_name = :"#{var_name}[i]"
counter_value = Unifex.Counter.get_and_increment()

elem_name = :"#{var_name}[i_#{counter_value}]"
len_var_name = "#{var_name}_length"
native_type = BaseType.generate_native_type(ctx.subtype, ctx.generator, ctx)
%{subtype: subtype, postproc_fun: postproc_fun, generator: generator} = ctx
Expand All @@ -131,34 +140,34 @@ defmodule Unifex.CodeGenerator.BaseTypes.List do
#{len_var_name} = (unsigned int) size;
int index = 0;
UnifexCNodeInBuff unifex_buff;
UnifexCNodeInBuff *unifex_buff_ptr = &unifex_buff;
UnifexCNodeInBuff unifex_buff_#{counter_value};
UnifexCNodeInBuff *unifex_buff_ptr_#{counter_value} = &unifex_buff_#{counter_value};
if(type == ERL_STRING_EXT) {
ei_x_buff buff = unifex_cnode_string_to_list(#{arg}, #{len_var_name});
unifex_buff.buff = buff.buff;
unifex_buff.index = &index;
unifex_buff_#{counter_value}.buff = buff.buff;
unifex_buff_#{counter_value}.index = &index;
} else {
unifex_buff.buff = #{arg}->buff;
unifex_buff.index = #{arg}->index;
unifex_buff_#{counter_value}.buff = #{arg}->buff;
unifex_buff_#{counter_value}.index = #{arg}->index;
}
int header_res = ei_decode_list_header(unifex_buff_ptr->buff, unifex_buff_ptr->index, &size);
int header_res = ei_decode_list_header(unifex_buff_ptr_#{counter_value}->buff, unifex_buff_ptr_#{counter_value}->index, &size);
#{len_var_name} = (unsigned int) size;
#{var_name} = (#{native_type} *)malloc(sizeof(#{native_type}) * #{len_var_name});
for(unsigned int i = 0; i < #{len_var_name}; i++) {
for(unsigned int i_#{counter_value} = 0; i_#{counter_value} < #{len_var_name}; i_#{counter_value}++) {
#{BaseType.generate_initialization(subtype, elem_name, generator, ctx)}
}
for(unsigned int i = 0; i < #{len_var_name}; i++) {
for(unsigned int i_#{counter_value} = 0; i_#{counter_value} < #{len_var_name}; i_#{counter_value}++) {
#{BaseType.generate_arg_parse(subtype,
elem_name,
"unifex_buff_ptr",
"unifex_buff_ptr_#{counter_value}",
postproc_fun,
generator,
ctx)}
}
if(#{len_var_name}) {
header_res = ei_decode_list_header(unifex_buff_ptr->buff, unifex_buff_ptr->index, &size);
header_res = ei_decode_list_header(unifex_buff_ptr_#{counter_value}->buff, unifex_buff_ptr_#{counter_value}->index, &size);
}
header_res;
})
Expand Down
14 changes: 14 additions & 0 deletions lib/unifex/counter.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule Unifex.Counter do
@moduledoc false
use Agent

@spec start_link(any) :: Agent.on_start()
def start_link(_opts) do
Agent.start_link(fn -> 0 end, name: __MODULE__)
end

@spec get_and_increment() :: integer()
def get_and_increment do
Agent.get_and_update(__MODULE__, fn state -> {state, state + 1} end)
end
end
5 changes: 3 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Unifex.MixProject do
use Mix.Project

@version "1.1.1"
@version "1.1.3"
@github_url "https://github.com/membraneframework/unifex"

def project do
Expand All @@ -28,7 +28,8 @@ defmodule Unifex.MixProject do

def application do
[
extra_applications: []
extra_applications: [],
mod: {Unifex.App, []}
]
end

Expand Down
Loading

0 comments on commit edc3ad1

Please sign in to comment.