cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[SUGGESTION] Prevent aliasing when using `inout` / `move` with `in` parameters

Open bluetarpmedia opened this issue 5 months ago • 9 comments

Suggestion

cppfront could detect at runtime (and maybe even compile time?) and prevent aliasing of inout or move function parameters when the function also takes an in parameter of the same type.

When the size of a type exceeds 2 pointers, the in parameter is passed by T const& in C++, which opens up the possibility of aliasing with another reference parameter of the same type.

Motivating example 1

//  Appends the read-only string `other` twice
//  to the end of the mutable `str`.
append_twice: (inout str: std::string, in other: std::string) = {
    str += " (other)$";
    str += " (other)$";
}

main: () -> int = {
    s1: std::string = ("hello");
    s2: std::string = ("world");

    append_twice(s1, s2);     // OK: hello world world
    std::println("{}", s1);

    append_twice(s2, s2);     // Expected: world world world
    std::println("{}", s2);   // Actual:   world world world world

    return 0;
}

The program prints the following to stdout:

hello world world
world world world world

Repro on Godbolt.

Motivating example 2

main: () -> int = {
    s1: std::string = ("hello");

    some_forwarding_function(s1, s1);

    return 0;
}

some_forwarding_function: (forward x: std::string, forward y: std::string) = {
    sink(move x, y);
}

sink: (move x: std::string, in y: std::string) = {
    z: std::string = (move x);

    std::println("x: {}", x);  // OK: Moved-from
    std::println("y: {}", y);  // Expect this to have a value; `y` was passed as `in`
    std::println("z: {}", z);  // OK: Moved `x` into `z`
}

The program prints the following to stdout:

x: 
y: 
z: hello

Repro on Godbolt.

Runtime

For Cpp2 functions having inout/move and in parameters of the same type, cppfront could insert code in the lowered C++ that asserts that the relevant arguments have different addresses.

E.g. it would be as if the user had written this:

append_twice: (inout str: std::string, in other: std::string) = {
    assert(str& != other&);
    ...
}
sink: (move x: std::string, in y: std::string) = {
    assert(x& != y&);
    ...
}

Compile-time

If possible, it would be even better if cppfront could produce a diagnostic if it detects the same argument is passed to a Cpp2 function's inout/move and in parameters.

Will your feature suggestion eliminate X% of security vulnerabilities of a given kind in current C++ code?

No, I can't find any CVEs related to aliasing with function parameter const and non-const references.

Will your feature suggestion automate or eliminate X% of current C++ guidance literature?

No, I can't find this guidance written anywhere.

bluetarpmedia avatar Sep 05 '24 04:09 bluetarpmedia