Atributos public e devolvendo ponteiros

Achei este post muito interessante.

[url=http://murilo.wordpress.com/2010/09/09/nunca-retorne-ponteiros-para-atributos-de-uma-classe/]http://murilo.wordpress.com/2010/09/09/ ... ma-classe/[/url]

O que vcs acham?

Caramba!

Quando eu li o título do artigo, pensei: “É óbvio que passar o ponteiro pode dar problema! Acesso direto à posição da memória de um objeto que pode ser alterado, deletado, etc fatalmente levará a um segmentation fault.” Mas parei por aí. Nem imaginava brincar com aritmética de ponteiro para ter acesso total ao objeto.

Mais do que isso, se você souber bem como é o objeto é provável que também seja possível até chamar funções private. Não fiz o teste (e não vai dar para fazer por agora), mas acho que é possível.

Legal, saber dessas coisas. :smiley:

Vinícius

Interessante isso :slight_smile:

Talvez seja possível até mesmo acessar os atributos private tendo o endereço do objeto? Imagino que o compilador deve no mínimo tentar ofuscar os outros valores.

O compilador não apenas ‘ofusca’ a parte private, como ele restringe o acesso. Uma função public da mesma classe , tem permissão para usar o private. Qualquer outra tentativa, seja ela outra função ou então um ponteiro, irá causar problemas, podendo o computador avisar uma tentativa de acessar memória restrita, ou no pior cenário, travar o programa.

Pode tentar, eu diria que seria tempo gasto. Se conseguir algo, por favor, me avise, para eu rever os conceitos. Já tentei coisas do gênero, e sempre falhei (ou realmente não dá, ou eu fiz caquinha -> bem possível, já que não sou nenhum gênio)

Mas você nem precisa de campos public para acessar membros private da classe. É só ter uma referência para um objeto que você acessa todos os seus atributos, com aritmética de ponteiro normal.

class C {
   private: int a;
   public: void printa() { cout << a << endl; }
};
int main() {
   C *c = new C();
   int *p = (int *)(c);
   *p = 666;
   c->printa();
}   

Para acessar um método private é só conseguir o endereço dele. Fiz o teste aqui e da certo, pegando o endereço da funcao num debugger [(dá pra fazer sem usar debugger; seria só o programa abrir ele mesmo, e procurar pelas instruções que setam o stackframe - que estão no começo de todas as funções)]. O problema é que a função deve ser acessível por algum método public - senão, o compilador simplesmente detecta que a função não é acessível, e a ignorando.

Mas não há nenhuma ofuscação ou método de proteção feito pelo compilador. Seria extremamente difícil fazer um método de proteção. Cada processo no Windows [ou no linux]só tem UM segmento de memória (para dados). Assim, para fazer algo protegido, deveria existir um processo para cada objeto instanciado ao longo do programa, o que é completamente inviável.

De qualquer forma, não tem problema nenhum em acessar os campos private de um objeto. Isso não é uma questão de segurança, é só uma questão de fixar uma interface. Se quisesse, o compilador poderia soltar só um warning e não um erro. Ou nem isso(como é no Smalltalk).

vc pode até clonar a classe, trocar os atributos private para public e depois fazer magia negra de ponteiros para acessar os dados. Porém, a ISO não estabelece que o alinhamento dos dados na classe original e na transgênica será igual. O truque pode até funcionar na prática, mas se ocorrer alguma situação exótica, prepare-se para o seg fault.

um truque que sempre funciona e que está de acordo com os padrões da linguagem é se a classe vítima tem algum método template. Basta então especializar esse template, injetando código externo malicioso. é como se vc fosse um advogado do capeta, encontrando brechas na lei.