((Void (*) ()) buf) (); anlamına gelmek?


59

Ben picoCTF ikili bir sömürü meydan okuma çözüyorum ve bu kod parçası rastladı:

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

bufbir karakter dizisi nerede .

Zorluğu çözdüm ama tam olarak ne yaptığını anlayamıyorum. Bu konuya baktım ama başaramadım.

Ne anlama ((void (*)())buf)();geliyor?


14
Ne anlama ((void (*)())buf)();geliyor? Bu yazarın anlamadığı anlamına gelir typedef. typedef void (*voidFuncPtrType)();bu kodu netleştirecektir.
Andrew Henle

33
CTand zorlukları tasarlama konusunda açıklık, netlik aslında en önemli hedef değildir ve meydan okumanın bir parçası olarak bazı şaşırtmalar bile beklenebilir. Büyük olasılıkla, yazar bunun bir şey yapmanın en okunabilir yolu olmadığının farkındaydı.
ManfP

2
Programınızın UB'si olduğu anlamına gelir.
R. .. GitHub DURDURMAK BUZ

4
Bu, C'nin "spiral" tip bildirim kuralının çok karmaşık olduğu anlamına gelir. Doğrudan C'den türetilmemiş, statik olarak yazılan diğer her dilin soldan sağa kuralları kullanmasının bir nedeni vardır.
Mason Wheeler

2
@MasonWheeler "Spiral" kentsel bir efsanedir. Beyan, karşılık gelen ifade kadar az ya da çok "spiral" dir. Operatörler basitçe önceliğe ve soldan sağa sırayla uygulanır (elbette burada yeni bir şey söylemezsiniz): "Bunu iptal etmeliyim, sonra çağırmalıyım ve sonuç void türüne sahip": voila, işaretçi void işlevi .
Peter - Monica'yı

Yanıtlar:


129

void (*)() bir türdür, tür "belirsiz argümanları alan ve değer döndürmeyen işlev gösterici" dir.

(void (*)()) , yukarıdaki türe bir tür dökümdür.

(void (*)())bufbufYukarıdaki tipte dökümler .

((void (*)())buf)() işlevi çağırır (bağımsız değişken iletilmez).

Kısacası: Derleyiciye bufbir işleve bir işaretçi olarak davranmasını ve bu işlevi çağırmasını söyler.


15
cdeclYardımcı programı (veya web sitesini ) daha karmaşık C ifadelerini İngilizce'ye çevirmek için yararlı buluyorum .
bta

3
@bta cdecl burada sözdizimi bir bildirim olmadığından yararlı değildir. Daha önce beyan edilmiş bir sembolün oyuncu kadrosu üzerinden bir işlev çağrısı
bolov

3
@bolov - tüm tablosunda, hayır, ama o does açıklamak en karmaşık kısmı bunu. Oradan, gerisini çözmek oldukça basittir.
bta

5
@AvD bufveya nerede bulunursa copyçalıştırılabilir bir adresteyse ve kodun kendisi konumdan bağımsızsa, bu işe yarayacaktır. Tabii ki taşınabilir değil, ancak bu birçok çıplak metal ortamda ve yığın ve yığın üzerinde yürütme (NX) bitini ayarlamayan eski x86 işletim sistemlerinde çalışmalıdır.
wrtlprnft

4
@AvD: Mutlaka çökmeyecek. Veri alanı yürütmeye karşı korunmadıkça (mimariye ve çalışma zamanı ortamına bağlıdır), bu hileyi çalışma zamanında bir diziye bir işlev olarak derlemek ve anında çağırmak için kullanabilirsiniz. Bu numarayı 35 yıl önce bir DEC Vax üzerinde Turing makinelerini Turing makine evriminde başarısız bir deney için derlemek için kullandım.
TonyK

11

işaretçi buf, belirtilmemiş sayıda parametre alınarak işaretçi işlevine dönüştürülür ve ardından kaydı sililir (yani işlev çağrılır).


9

Tipik bir tahmin ve ardından bir işlev çağrısı gelir. İlk bufolarak, işaretçiyi döndüren bir işleve dönüştürülür void. Son parantez çifti, işlevin daha sonra çağrıldığı anlamına gelir.


7

Karakter dizisini argüman almayan ve geri dönen bir işleve bir işaretçiye çevirir voidve sonra çağırır. İşlev işaretleyicilerinin çalışma şekli nedeniyle işaretçinin kaydının kaldırılması gerekli değildir.

Bir açıklama:

Bu "karakter dizisi" aslında bir makine kodu dizisidir. Diziyi a'ya çevirip void (*)()çağırdığınızda, dizinin içindeki makine kodunu çalıştırır. Dizinin içeriğini sağladıysanız, sizin için sökebilir ve ne yaptığını söyleyebilirim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.