Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

operator char* #43

Open
quadrustech opened this issue Apr 17, 2024 · 8 comments
Open

operator char* #43

quadrustech opened this issue Apr 17, 2024 · 8 comments

Comments

@quadrustech
Copy link

Is it probably better to replace the operator "operator char*()" with operator const char*() ?

@adamyaxley
Copy link
Owner

Is there a particular use case that you have in mind where it would be better?

@geijnmh
Copy link

geijnmh commented Jun 30, 2024

I am not the OP, but I'd think the class obfuscated_data holds a private member m_data. The operator() automatically decrypts this and returns a pointer to this data for the caller to further process.
I suppose out of good practice one would not want to allow caller to manipulate this data?

If I turn around the question: is there a use case in which caller would want to adjust the data directly?

@MarioLiebisch
Copy link

MarioLiebisch commented Jun 30, 2024

I imagine there could be a case where you only want to obfuscate the initial value on disk, but change it at runtime. With this function's return value not being const, you allow the obfuscated strings to replace/obfuscate both const char *some_secret = "sesame"; as well as char *some_secret = "sesame";.

There are use cases where manipulation of encapsulated data is allowed or encouraged, it just has to be properly defined. Even STL's std::base_string class introduced this ability in a limited way by providing a version of operator[] returning a non-const reference and guaranteeing linear memory layout.

@geijnmh
Copy link

geijnmh commented Jun 30, 2024

Hi Mario,

Would it not be a segfault waiting to happen because the caller changes the "some_secret" variable into a longer string than was allocated during de-obfuscation? (m_data[N], with N known at compile-time)

@MarioLiebisch
Copy link

MarioLiebisch commented Jun 30, 2024

Yes, but you've got that very same issue when just using regular char[], too.

Even a operator const char*() will expose a similar issue for read access alone.

(Offensive/defensive programming; There's a limit on how far you can reasonably go to prevent mistakes from happening.)

@geijnmh
Copy link

geijnmh commented Jun 30, 2024

Hi,
thanks for sharing your thoughts. I agree that there is a limit how far we should "protect" callers against their own mistakes. But this principle can be applied to the whole encapsulation as well. e.g. why bother making m_data private and obfuscated_data a class, if we want to expose all the risks to the caller.. we could make it a struct with everything public and be done with it).

@MarioLiebisch
Copy link

m_data is private simply to automatically call decryption once you try to retrieve/use the string (again to make it kind of swappable/plug and play).

You can obviously still screw this up, e.g. by retrieving the pointer, then re-encrypting the data and after this possibly modifying the encrypted data, destroying everything.

You can do all this with a struct or raw standalone pointer, but that's not the idea behind C++. This comparison is a bit like using const char * vs. const std::string for example.

@geijnmh
Copy link

geijnmh commented Jul 5, 2024

Well, I disagree with your argument why m_data would be private because of automatic decryption. This is actually not true, it can still be done automatically on a public m_data.

Whether or not data() returns const char* or char* remains a matter of taste and encapsulation design. People who value the design principle of ownership of the class obfuscated_data and its responsibility of the memory management of its members, would rather choose const char*. Callers can do with the result as they please as long as they copy it into a piece of memory they own.
Those who value caller's responsibility for memory management, even for those items that are allocated by the class would say "Fine. just document this and return char*.

Both are possible and it is for the project maintainer to form an opinion about and I for myself will respect that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants