O que faz ((void (*) ()) buf) (); significar?


59

Estou resolvendo um desafio de exploração binária no picoCTF e me deparei com este pedaço de código:

((void (*)())buf)();

onde bufé uma matriz de caracteres.

Eu resolvi o desafio, mas não consigo entender o que exatamente está fazendo. Eu olhei para esta discussão, mas não consegui entender.

O que ((void (*)())buf)();significa isso ?


14
O que ((void (*)())buf)();significa isso ? Isso significa que o autor não entende typedef. typedef void (*voidFuncPtrType)();tornaria esse código claro.
— Andrew Henle

33
@AndrewHenle ao projetar os desafios do CTF, a clareza não é realmente o objetivo principal e pode até ser esperada alguma ofuscação como parte do desafio. Muito provavelmente, o autor estava ciente de que essa não é a maneira mais legível de fazer as coisas.
— ManfP 14/01

2
Isso significa que seu programa tem UB.
— R .. GitHub Pare de ajudar o gelo

4
Isso significa que a regra de declaração do tipo "espiral" de C é muito complicada. Há uma razão para que praticamente qualquer outra linguagem de tipo estaticamente que não seja descendente direta de C use regras da esquerda para a direita.
— Mason Wheeler

2
@MasonWheeler "Espiral" é um mito urbano. A declaração é tão ou tão "espiral" quanto seria a expressão correspondente. Os operadores são simplesmente aplicados em precedência e ordem da esquerda para a direita (sem contar nada de novo aqui, é claro): "Eu preciso desreferenciar isso e depois chamá-lo, e o resultado tem o tipo void": voila, ponteiro para a função nula .
— Peter - Restabelece Monica

Respostas:


129

void (*)() é um tipo, sendo o tipo "ponteiro para a função que recebe argumentos indeterminados e não retorna valor".

(void (*)()) é uma conversão de tipo para o tipo acima.

(void (*)())buflança bufpara o tipo acima.

((void (*)())buf)() chama a função (sem passar argumentos).

Resumindo: Diz ao compilador para tratar bufcomo um ponteiro para uma função e chamar essa função.


15
Acho o cdeclutilitário (ou site ) útil para traduzir as expressões C mais complexas para o inglês.
— bta 14/01

3
O @bta cdecl não é útil aqui, pois a sintaxe não é uma declaração. É uma chamada de função através de uma
— conversão

3
@bolov - Em toda a instrução, não, mas faz explicar a parte mais complexa do mesmo. A partir daí, decodificar o resto é bastante direto.
— bta 15/01

5
@AvD Se qualquer local bufou local copyestiver em um endereço executável e o próprio código for independente da posição, isso funcionará. É claro que não é tão portátil quanto possível, mas isso deve funcionar em muitos ambientes bare-metal, bem como em sistemas operacionais x86 mais antigos que não definem o bit de não execução (NX) na pilha e na pilha.
— wrtlprnft 15/01

4
@ AvD: Não vai necessariamente falhar. A menos que a área de dados esteja protegida contra a execução (que depende da arquitetura e do ambiente de tempo de execução), você pode usar este truque para compilar uma função em uma matriz no tempo de execução e chamá-la em tempo real. Eu usei esse truque pela primeira vez há 35 anos no DEC Vax para compilar máquinas de Turing para um experimento fracassado na evolução das máquinas de Turing.
— TonyK 15/01

11

O ponteiro bufé convertido no ponteiro para a função nula, obtendo um número não especificado de parâmetros e depois desreferenciado (ou seja, a função chamada).


9

É um typecast, seguido por uma chamada de função. Em primeiro lugar, bufé convertido para o ponteiro para uma função que retorna void. O último par de parênteses significa que a função é chamada.


7

Ele converte a matriz de caracteres em um ponteiro para uma função sem argumentos e retornando voide depois a chama. A desreferenciação do ponteiro não é necessária devido ao funcionamento dos ponteiros de função.

Uma explicação:

Essa "matriz de caracteres" é na verdade uma matriz de código de máquina. Quando você converte a matriz para a void (*)()e chama, ela executa o código da máquina dentro da matriz. Se você fornecesse o conteúdo do array, eu poderia desmontá-lo e dizer o que ele está fazendo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.