Skip to content

code that should segfault? #362

@VRichardJP

Description

@VRichardJP

Hi

I am looking at node.c and arguments.c code, and there is part that, in my understanding, should cause a segfault (but I guess it doesn't?)

If you look from line 286 (node.c in master branch):

  ...
  node->impl->options = rcl_node_get_default_options();
  node->context = context;
  // Initialize node impl.
  ret = rcl_node_options_copy(options, &(node->impl->options));
  ...

node->impl->options is filled with 0, and then it is copied to options with the following function (from line 562):

  ...
  options_out->domain_id = options->domain_id;
  options_out->allocator = options->allocator;
  options_out->use_global_arguments = options->use_global_arguments;
  if (NULL != options->arguments.impl) {
    rcl_ret_t ret = rcl_arguments_copy(&(options->arguments), &(options_out->arguments));
    ...

and the arguments are copied by rcl_arguments_copy as defined in arguments.c from line 479:

  ...
  args_out->impl = allocator.allocate(sizeof(rcl_arguments_impl_t), allocator.state);
  if (NULL == args_out->impl) {
    return RCL_RET_BAD_ALLOC;
  }

  args_out->impl->allocator = allocator;

  // Zero so it's safe to call rcl_arguments_fini() if an error occurrs while copying.
  args_out->impl->num_remap_rules = 0;
  args_out->impl->num_unparsed_args = 0;
  args_out->impl->num_param_files_args = 0;

  // Copy unparsed args
  args_out->impl->unparsed_args = allocator.allocate(
    sizeof(int) * args->impl->num_unparsed_args, allocator.state);
  if (NULL == args_out->impl->unparsed_args) {
    if (RCL_RET_OK != rcl_arguments_fini(args_out)) {
      RCL_SET_ERROR_MSG("Error while finalizing arguments due to another error");
    }
    return RCL_RET_BAD_ALLOC;
  }
  ...

So args_out->impl is allocated. Since the allocation here is just a malloc, args_out->impl
may contain any kind of value.

Since at this point args->impl->num_unparsed_args is 0, this line:

  allocator.allocate(
    sizeof(int) * args->impl->num_unparsed_args, allocator.state);

is just a malloc(0), which returns NULL. So the if statement is triggered and we call rcl_arguments_fini(args_out) (from line 567). At this point args->impl->remap_rules may contain anything (it has not been initialized yet), so the code may then enter the if statement at line 574:

    if (args->impl->remap_rules) {
      ...
      args->impl->allocator.deallocate(args->impl->remap_rules, args->impl->allocator.state);
      ...
}

and then call free on the uninitialized pointer, resulting in a SegFault

Is my understanding correct?

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions