OVH Cloud OVH Cloud

Passer outre les protections private/protected

13 réponses
Avatar
Matthieu Moy
Bonjour,

Je voulais savoir si il était possible de forcer l'accès à un membre
de classe privé ou protégé depuis une autre classe (un peu comme avec
le mot clé "friend"), mais sans modifier le source de la classe à
laquelle on veut accéder. (Donc, une sorte de "friend" à l'envers,
quoi)

Ne me répondez pas « Ne le fait pas, c'est mal », je sais. Je voudrais
l'utiliser dans un contexte bien précis un peu long à détailler, mais
toujours est-il qu'on ne peut pas trop faire autrement.

Pour l'instant, j'ai un truc vraiment sale :

#define private public
#define protected public

(Et si je fais #define class struct, les template <class toto> ne
compilent plus :-( )

Hmm, je ne trouve pas ça très satisfaisant intellectuellement
parlant ;-)

Merci de vos réponses,

--
Matthieu

10 réponses

1 2
Avatar
Marc Boyer
Matthieu Moy wrote:
Bonjour,

Je voulais savoir si il était possible de forcer l'accès à un membre
de classe privé ou protégé depuis une autre classe (un peu comme avec
le mot clé "friend"), mais sans modifier le source de la classe à
laquelle on veut accéder. (Donc, une sorte de "friend" à l'envers,
quoi)

Ne me répondez pas « Ne le fait pas, c'est mal », je sais. Je voudrais
l'utiliser dans un contexte bien précis un peu long à détailler, mais
toujours est-il qu'on ne peut pas trop faire autrement.


Si tu ne nous explique pas le contexte, en effet, dur de
te donner une solution.

Pour l'instant, j'ai un truc vraiment sale :

#define private public
#define protected public


Quitte a faire des horreurs, autant limiter la casse
avec des choses dans le genre:
#define private friend taClasse; private

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(

Avatar
Matthieu Moy
Marc Boyer writes:

Ne me répondez pas « Ne le fait pas, c'est mal », je sais. Je voudrais
l'utiliser dans un contexte bien précis un peu long à détailler, mais
toujours est-il qu'on ne peut pas trop faire autrement.


Si tu ne nous explique pas le contexte, en effet, dur de
te donner une solution.


J'ai en mémoire à un instant donné à la fois l'arbre abstrait
syntaxique du programme (qui me vient du front-end de GCC) et l'état
de la mémoire au milieu de l'éxécution du programme.

Le problème à résoudre, c'est, étant donné l'arbre abstrait
représentant un membre de donnée, et un pointeur sur la classe en
mémoire, récupérer la valeur de la variable en question.

Apparament, il n'y a pas assez d'informations dans l'arbre abstrait
pour récupérer l'addresse en mémoire, donc, je n'ai rien trouvé de
mieux que de générer un bout de code C++ récupérant cette valeur et de
le compiler puis de l'éxecuter à coups de dlopen/dlsym.

Ca marche quand le membre est public, mais si il est privé, le bout de
code C++ généré à la volée ne compile pas !

--
Matthieu


Avatar
Marc Boyer
Matthieu Moy wrote:
Marc Boyer writes:
Ne me répondez pas « Ne le fait pas, c'est mal », je sais. Je voudrais
l'utiliser dans un contexte bien précis un peu long à détailler, mais
toujours est-il qu'on ne peut pas trop faire autrement.


Si tu ne nous explique pas le contexte, en effet, dur de
te donner une solution.


J'ai en mémoire à un instant donné à la fois l'arbre abstrait
syntaxique du programme (qui me vient du front-end de GCC) et l'état
de la mémoire au milieu de l'éxécution du programme.

Le problème à résoudre, c'est, étant donné l'arbre abstrait
représentant un membre de donnée, et un pointeur sur la classe en
mémoire, récupérer la valeur de la variable en question.

Apparament, il n'y a pas assez d'informations dans l'arbre abstrait
pour récupérer l'addresse en mémoire, donc, je n'ai rien trouvé de
mieux que de générer un bout de code C++ récupérant cette valeur et de
le compiler puis de l'éxecuter à coups de dlopen/dlsym.


Puisque tu génères toi même le code, pourquoi ne pas ajouter
un "friend maClass;" qui va bien ?

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(



Avatar
Matthieu Moy
Marc Boyer writes:

Puisque tu génères toi même le code, pourquoi ne pas ajouter
un "friend maClass;" qui va bien ?


Je génère le code qui lit les membres. Le code généré ressemble à ça :

#include "le_fichier_avec_la_déclaration_de_classe"

extern "C" int la_fonction_qui_recupere_la_valeur(MaClase * o) {
return o->le_membre_que_je_veux;
}

C'est pour ça que j'aimerais un « friend », mais « à l'envers » : Pas
« Lui, c'est mon ami », mais « Moi, je suis son ami » ...

--
Matthieu

Avatar
Gabriel Dos Reis
Matthieu Moy writes:

| Bonjour,
|
| Je voulais savoir si il était possible de forcer l'accès à un membre
| de classe privé ou protégé depuis une autre classe (un peu comme avec
| le mot clé "friend"), mais sans modifier le source de la classe à
| laquelle on veut accéder. (Donc, une sorte de "friend" à l'envers,
| quoi)

Toute solution à ce problème requiert au moins une violation de l'ODR
ou une connaissance intime de l'implémentation.
Les droits d'accès font partie de l'information de type que te donne
une définition de classe.

-- Gaby
Avatar
Andre Heinen
On Tue, 24 Feb 2004 13:14:55 +0100, Matthieu Moy
wrote:

Bonjour,

Je voulais savoir si il était possible de forcer l'accès à un membre
de classe privé ou protégé depuis une autre classe (un peu comme avec
le mot clé "friend"), mais sans modifier le source de la classe à
laquelle on veut accéder. (Donc, une sorte de "friend" à l'envers,
quoi)


C'est impossible, et il y a à cela une excellente raison.
Prenons un exemple:

class C {
void m(); // membre
friend void a(); // amie
};

*Toutes* les fonctions qui peuvent accéder à l'implémentation de
C, membres ou amies, sont listées dans C elle-même. Si tu dois
modifier C, tu as sous les yeux la liste des fonctions à
vérifier.

Si on pouvait faire "friend à l'envers", un utilisateur de ta
classe pourrait, dans un autre fichier, déclarer une fonction f()
qui cesserait de fonctionner dès que tu aurais modifié
l'implémentation de C.

Pour garantir que le code client continue à fonctionner en cas de
modification de C, les amies comme les membres doivent
nécessairement être déclarées dans C.

<snip>

Pour l'instant, j'ai un truc vraiment sale :

#define private public
#define protected public


8-( Aaaaarrgh!

<snip>

Hmm, je ne trouve pas ça très satisfaisant intellectuellement
parlant ;-)


Tu l'as dit!
;-)

Merci de vos réponses,


--
Andre Heinen
My address is "a dot heinen at europeanlink dot com"

Avatar
Marc Boyer
Matthieu Moy wrote:
Marc Boyer writes:
Puisque tu génères toi même le code, pourquoi ne pas ajouter
un "friend maClass;" qui va bien ?


Je génère le code qui lit les membres. Le code généré ressemble à ça :

#include "le_fichier_avec_la_déclaration_de_classe"


En gros, t'a la flemme de faire une génération de code un rien
plus subtile ;-)
Que dire alors ? Un coup de system+sed ?

C'est pour ça que j'aimerais un « friend », mais « à l'envers » : Pas
« Lui, c'est mon ami », mais « Moi, je suis son ami » ...


Oui, mais ça c'est pas possible.

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(


Avatar
Matthieu Moy
Marc Boyer writes:

Je génère le code qui lit les membres. Le code généré ressemble à ça :

#include "le_fichier_avec_la_déclaration_de_classe"


En gros, t'a la flemme de faire une génération de code un rien
plus subtile ;-)


Non ;-)

Je génère un #include parce que ce n'est pas moi qui ai écrit le
fichier en question, et il peut changer d'une execution à l'autre.

Que dire alors ? Un coup de system+sed ?


C'est comme ça que ça va se terminer ...

C'est pour ça que j'aimerais un « friend », mais « à l'envers » : Pas
« Lui, c'est mon ami », mais « Moi, je suis son ami » ...


Oui, mais ça c'est pas possible.


C'est un peu ce que je pensais, mais bon, on pouvait toujours
demander, hein ! (Depuis que je connais l'existance de const_cast<> en
C++, plus rien ne m'étonne en terme de violation des protections en
C++ :-P )

Merci quand même,

--
Matthieu


Avatar
Marc Boyer
In article , Matthieu Moy wrote:
Marc Boyer writes:

Je génère le code qui lit les membres. Le code généré ressemble à ça :

#include "le_fichier_avec_la_déclaration_de_classe"


En gros, t'a la flemme de faire une génération de code un rien
plus subtile ;-)


Non ;-)

Je génère un #include parce que ce n'est pas moi qui ai écrit le
fichier en question, et il peut changer d'une execution à l'autre.


Oui, mais puisque tu as l'arbre syntaxique, tu pourrais ajouter
un "friend" dans le dit arbre et regénérer le code ;-)

Que dire alors ? Un coup de system+sed ?


C'est comme ça que ça va se terminer ...


Puisque tu sorts du langage, en lui ajoutant un rien de
réflexivité, autant utiliser les outils qui vont bien.

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(



Avatar
Gabriel Dos Reis
Matthieu Moy writes:

[...]

| > Oui, mais ça c'est pas possible.
|
| C'est un peu ce que je pensais, mais bon, on pouvait toujours
| demander, hein ! (Depuis que je connais l'existance de const_cast<> en
| C++, plus rien ne m'étonne en terme de violation des protections en
| C++ :-P )

Je ne comprends pas ce commentaire. Il a toujours été possible de
bafouiller le système de types de C++ (même si des fois, il faut être
vraiment déterminé), bien avant l'invention des nouveaux styles de
casts. Cependant, les nouveaux styles de casts te permettent
d'exprimer clairement ce qui pourrait être interprêté comme une
violation du système de type de ce qui ne l'est pas. Par exemple,
dynamic_cast<> ne te laisse pas faire mumuse. Si tu utilises
const_cast<> sur quelque chose qui, en réalité, n'est pas const, ce
n'est pas une violation du système de type. Pourquoi cela devrait-il
être étonnant ?

-- Gaby
1 2