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.