Skip to content

Bindings introduce UB for referencesΒ #212

@Caellian

Description

@Caellian

I wasn't entirely sure how to use Request::header_map(), expecting something akin to C API due to Option<&mut T> argument, so I looked at the implementation both in cef-rs and cef.

Description

The way the function is currently implemented allows UB to occur from safe Rust by passing None as argument:

fn header_map(&self, header_map: Option<&mut CefStringMultimap>) {
  //...
  let arg_header_map = arg_header_map
    .map(|arg| arg.into_raw())
    .unwrap_or(std::ptr::null_mut());
  f(arg_self_, arg_header_map)
  //...
}

Here, in impl ImplRequest for Request, f can be invoked with a null pointer.

GetHeaderMap is defined as:

public virtual void GetHeaderMap( HeaderMap& headerMap )= 0;

A reference is required to be initialized to refer to a valid object or function: see reference initialization.

Source: C++ Reference

In CEF implementation this reference is directly assigned to.

So bindings effectively invoke *nullptr = headermap_ when None value is passed as argument which is UB (that results in segfault). This is impossible to achieve using the C++ API and reference is only degraded into a pointer in the C ABI exposed by bindgen.

Solution

header_map signature should be:

fn header_map(&self, header_map: &mut CefStringMultimap) {...}
// or better yet, given that argument will be replaced (deep copied into)
fn header_map(&self) -> CefStringMultimap {...}

Related Issues

I described in detail only this one issue I stumbled across.

This is UB every time an argument which is a reference declaration in the original C++ API is defaulted as null. All of those shouldn't be wrapped in Option in the first place because C++ API doesn't allow it. There's ~950 occurences/binding I found using regex: \.unwrap_or\(std::ptr::null(_mut)?\(\)\) (some are false positives)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions