¿Los especificadores de acceso no son infalibles?

Si tengo una clase como esta,

class Sample { private: int X; }; 

Entonces no podemos acceder a X desde el exterior, por lo que esto es ilegal,

  Sample s; sX = 10; // error - private access 

¡Pero podemos hacerlo accesible sin editar la clase ! Todo lo que necesitamos hacer es esto,

 #define private public //note this define! class Sample { private: int X; }; //outside code Sample s; sX = 10; //no error! 

Código de trabajo en ideone: http://www.ideone.com/FaGpZ

Eso significa que podemos cambiar los especificadores de acceso definiendo dichas macros justo antes de la definición de la clase, o antes de #include ,

 #define public private //make public private //or #define protected private //make protected private //or #define so on 

¿No es un problema con C ++ (Macros / especificadores de acceso / lo que sea)?

De todos modos, el punto de este tema es:

Usando macros, podemos fácilmente violar la encapsulación. ¡Los especificadores de acceso no son infalibles! Estoy en lo cierto

¡Pero podemos hacerlo accesible sin editar la clase! Todo lo que necesitamos hacer es esto,

Técnicamente, todo lo que ha demostrado es que “podemos convertir un progtwig legal en comportamiento indefinido” sin editar una clase específica.

Eso no es noticia. También puede convertirlo en un comportamiento indefinido simplemente agregando una línea como esta al final de main() :

 int i = 0; i = ++i; 

Los especificadores de acceso en C ++ no son una característica de seguridad. No protegen contra los bashs de piratería, y no protegen contra las personas que intentan introducir errores en su código.

Simplemente permiten que el comstackdor lo ayude a mantener ciertas clases invariantes. Permiten que el comstackdor le informe si intenta acceder accidentalmente a un miembro privado como si fuera público. Todo lo que has demostrado es que “si específicamente bash romper mi progtwig, puedo”. Eso, con suerte, debería ser una sorpresa para absolutamente nadie.

Como dijo @Gman, la redefinición de palabras clave en el lenguaje C ++ es un comportamiento indefinido . Puede parecer que funciona en su comstackdor, pero ya no es un progtwig C ++ bien definido, y el comstackdor podría, en principio, hacer lo que quiera.

En primer lugar, es ilegal hacer eso. private es una palabra clave, y no puede usarla como identificador en una macro; Su progtwig estaría mal formado.

Pero en cualquier caso, no es un problema con las macros en absoluto. Es con el tonto que los usó de una manera tonta. 🙂 (Están ahí para ayudarte a estar seguro, no están para ayudarte a estar seguro y bloquear todo acceso a ellos sin importar lo que intentes. C ++ protege contra Murphy, no con Maquiavelo).

Tenga en cuenta que puede acceder a datos privados de una manera bien formada y bien definida, como se muestra aquí . Nuevamente, esto no es un problema con el idioma, simplemente no es el trabajo del idioma hacer más de lo necesario para mantener las manos indiscretas.

Pero podemos hacerlo accesible sin editar la clase.

Sin embargo, no sin editar el archivo fuente que contiene la clase.

Sí, las macros te permiten dispararte en el pie. Esto no es nada nuevo … pero este es un ejemplo particularmente no preocupante, ya que para “violar la encapsulación” debe obligar a la clase a definir la macro con cabeza de hueso o incluir un archivo de encabezado que lo haga.

Para decirlo de otra manera: ¿puede ver esto como un problema en el desarrollo de software responsable y real ?

@Nawaz, tu publicación es interesante, nunca había pensado en esto antes. Sin embargo, creo que la respuesta a su pregunta es simple: piense en la seguridad de C ++ (o probablemente en cualquier idioma) como una forma de organizar su código, en lugar de una policía.

Básicamente, dado que todas las variables están definidas en su propio código, debe poder acceder a TODAS, sin importar dónde las defina. Por lo tanto, no debe sorprenderse al encontrar una manera de acceder a un miembro privado.

En realidad, hay incluso un método más fácil para acceder a las variables privadas. Imagina que tienes una biblioteca con esta clase:

 class VerySecure { private: int WorldMostSecureCode; }; 

Y digamos que estoy usando tu clase muy segura en mi código. Puedo acceder fácilmente al miembro privado de esta manera:

 VerySecury a; int *myhacker = (int*)(&a); int b = (*myhacker); printf("Here is your supposed world secret: %d :-) \n", b); 

¡¡¿Como es eso?!!

No. Se va a romper el caos con los métodos privados. Si el comstackdor puede decir que no se puede acceder a estos métodos privados en otro lugar, entonces pueden estar en línea y optimizados, y es posible que no aparezcan en el archivo objeto, por lo que serán inaccesibles.

Toma esto como un ejemplo. Funciona, no puede vincular o no puede ejecutar el ejecutable según los indicadores de optimización / borrado que usa y cómo comstack el objeto (es decir, puede poner la implementación en una biblioteca compartida o no)

 class A { // i need this one ... private: void stupid_private(); public: void unlock(std::string password); }; 

archivo de implementación:

 #include  #include "a.h++" // uncomment this for more g++ fun // __attribute__((visibility("hidden"))) void A::stupid_private() { std::cout << "let's output something silly." << std::endl; } void A::unlock(std::string password) { if (password == "jumbo") stupid_private(); } 

el archivo de usuario:

 #define private public #include "a.h++" int main() { A a; a.stupid_private(); return 0; } 
Intereting Posts