Is private really private?

In Java and C# data encapsulation is really more of a wink and handshake than something whose enforcement has teeth (you can always use runtime introspection to strip away the privacy protection). C++ it's technically illegal and undefined but like everything else in C++ it's a hot mess (i.e. compiler dependent--stay classy C++).

So in Rust is private really and truly private? In other words, is a private member, not running in some debug mode, absolutely inaccessible from the "outside" (for lack of a better term)?

You can always use transmute or pointer casts to access private data of a struct. Of course, both of these are only possible if you use unsafe code. So I would say that private is really private as long as you only use safe code.

Unsafe Rust is similar to C++ where you can use pointer arithmetic to view or modify private data in a struct.

:unamused:

Thanks for the answer but I'm going to call this a "no" (which is disappointing).

Is there any programming language where private is really and truly private? No macro hacks, no production runtimes that break it, no magic keywords to make the selling point of the language irrelevant? I'm starting to see why Python made the decision they made. Since encapsulation is a con anyway just kill it entirely (I'm not counting the under-score convention they use).

I'm curious if there is a specific use-case or concern that you have in mind?

As long as you run the code on general-purpose computers, I'd say it is always possible to access the raw memory in some way and gain access to "private" fields. And as long as you allow some way to run c code in the same binary, you can do that violating access from within the program.

So if any language guarantees that "private" is really private, they are probably lying. :slight_smile:

6 Likes

I write public APIs for a living and I don't want others having access to things they shouldn't. I can't really stop them from scraping memory but that's a system access concern not an API concern.

The only way to circumvent privacy in rust is really reinterpreting the raw memory. That's of course unsafe and potentially dangerous.

Privacy is a tool for the progammer, not a security measure to protect against evil hackers.
As a tool it is very useful and I don't agree with the sentiment that...

... at all.

Rust is a systems programming language and as such it also provides the tools to write unsafe code. That doesn't make safe code less useful.

9 Likes

LOL. Right as finish typing your comment popped up.

It's true if someone gets complete access to a box then I can't stop them from memory surfing but as an API writing that's the sys admins concern :smile:

1 Like

Just to be clear I'm a large fan of encapsulation and don't view it as a con, I've met plenty pythonistas who do.

"Privacy is a tool for the programmer..." The whole point of encapsulation is data security if it can't keep hackers out, it won't keep programmers out either. Either data is private or it isn't. You can't be half pregnant.

At some level, no, never. Even in Python you could write a C extension, and then do the exact same things.

1 Like

You wouldn't need to in python. Privacy doesn't exist. I can access anything in a python class right in the language. PyCharm even gives me code completion.

In python they do a little name convention ( _myprivatevar) to signal "this is private please don't touch it" but there is nothing in the language that enforces that.

i view rust as pretty serious about privacy. if you (as a programmer) want to get around privacy rules, you really have to work at it. it will never be something that will happen by accident. this strong (but not invincible) privacy, combined with rust's strong type system means that it is one of the best languages for writing public APIs, in my opinion.

Strong? Work? :confused:
Assuming @Amanieu is correct all I have to do is create an unsafe code block and then I have C++ with a strange new syntax.

To me strong would be, in a production environment code marked private is inaccessible period unless you have total access to the box and are willing to root through raw memory.

By the way, this isn't some "oh Rust is terrible" thing for me. I've been doing some Python recently and was surprised to learn that Python just doesn't have any meaningful data encapsulation at all. So I got curious. I knew Java and C# had runtime introspection. I was surprised that it seems some C++ compilers allow the breaking of encapsulation (you would think every compiler writer would ensure it but given the byzantine nature of the C++ spec...). So I've been doing a language tour on a lazy Saturday.

Here is one way you can escape rust's privacy rules (surely there are others as well):

mod M {
    pub struct MyStruct {
        priv_field: u32,
    }

    impl MyStruct {
        pub fn new() -> MyStruct {
            MyStruct { priv_field: 42 }
        }
    }
}

struct MyStructHax {
    pub priv_field: u32
}

fn main() {
    let s = M::MyStruct::new();

    // this will not compile:
    //let x: u32 = s.priv_field;
    
    let s_exposed: MyStructHax = unsafe { std::mem::transmute(s) };
    let x = s_exposed.priv_field;
}

First a new struct was defined that has the same layout at the one you wish to expose, but with a public field. Then you use std::mem::transmute to convert to the new struct. Now the field is accessible.

This is not hard to do, but as I mentioned above, you have to be very deliberate about this -- you need to look up the struct definition you want to expose and use an unsafe transmute. You would never do this on accident. This is what I mean by having to do "work" to expose a private field.

C++ will happily let a programmer shoot themselves in their own foot, especially when the programmer doesn't mean to. Rust also will let a programmer shoot themselves in the root, but doing this by accident or unintentionally is very hard.

3 Likes

Okay. Fair enough. Still a "no" though. :wink:

1 Like

In the end a program is just code that reads and writes data in memory.
The only way to make some memory "private" is to put it in a separate process. Of course it's going to be stupidly slow and you'd lose all the benefits of using a fast language in the first place.

As far as I know, no language automatically does this for you (because, to be honest, that's silly thing to do). In other words, no language offers "truly private" fields.

10 Likes

Correct. But it was worth clarifying the details here, because they are important.

Final thought: I can't think of any way to gain access to a private module. I'm curious if anyone has some clever idea about how to do this.

Using mem::transmute is essentially scraping memory. It is an unsafe function with this documentation:

transmute is incredibly unsafe. There are a vast number of ways to
cause undefined behavior with this function. transmute should be
the absolute last resort.

No one should ever ever ever ever ever do this to get around a privacy boundary. But Rust is a low level language, unsafe code can do a lot of things it shouldn't, up to and including inline assembly and dereferencing arbitrary memory addresses.

1 Like

One would want to say this, but...

(actually, I wanted to link to RawVec, but if it's members were ever public, they're private now)