Qual è il codice più breve per causare un overflow dello stack? [chiuso]


160

Per commemorare il lancio pubblico di StackTranslate.it, qual è il codice più corto per causare un overflow dello stack? Qualsiasi lingua benvenuta.

ETA: Giusto per essere chiari su questa domanda, visto che sono un utente occasionale di Scheme: la "ricorsione" di coda è davvero un'iterazione, e qualsiasi soluzione che può essere convertita in una soluzione iterativa in modo relativamente banale da un compilatore decente non lo farà essere contato. :-P

ETA2: ora ho selezionato una "migliore risposta"; vedi questo post per ragioni. Grazie a tutti quelli che hanno contribuito! :-)

Risposte:


212

Tutte queste risposte e nessun Befunge? Scommetterei una buona somma, è la soluzione più breve di tutte:

1

Non sto scherzando. Provalo tu stesso: http://www.quirkster.com/iano/js/befunge.html

EDIT: suppongo di dover spiegare questo. L'operando 1 inserisce un 1 nello stack interno di Befunge e la mancanza di qualsiasi altra cosa lo mette in loop secondo le regole della lingua.

Usando l'interprete fornito, alla fine - e intendo alla fine - colpire un punto in cui l'array Javascript che rappresenta lo stack di Befunge diventa troppo grande per essere riallocato dal browser. Se avessi un semplice interprete Befunge con uno stack più piccolo e limitato - come nel caso della maggior parte delle lingue sottostanti - questo programma causerebbe un overflow più evidente più veloce.


8
Hmm ... ma è davvero un overflow dello stack o solo un loop infinito? Il mio interprete JS non ha traboccato, è semplicemente andato in vacanza, per così dire.
Konrad Rudolph,

3
Non è un ciclo infinito, perché l'istruzione 1 inserisce un 1 nello stack. Alla fine, il tuo interprete Befunge esaurirà lo spazio dello stack, ma ci vorrà del tempo. :)
Patrick,

18
Tu ... hai bloccato il mio browser e ... hai mandato la mia ventola della CPU in overdrive.
Sam152,

2
Sorprendente! Il mio computer o browser (Opera) non si è arrestato in modo anomalo ma entrambi i processori funzionavano al 100% e la velocità della ventola era al 3.
Secko,

28
Ecco un programma Befunge che trabocca più velocemente: " carica 79 copie del numero 32 ogni due volte che lo avvolge, anziché 2 copie del numero 1.
KirarinSnow


174

Puoi anche provare questo in C # .net

throw new StackOverflowException();

29
Il pedante in me dice che non fa traboccare lo stack, ma genera solo un'eccezione. È come dire che il modo più rapido per essere attaccato dagli squali è stare in mare e urlare "Attacco di squalo!". Nonostante ciò, lo voterò. :)
Bernard,

Bene - c'è una differenza? Riesci a prenderlo e continuare? O è esattamente come uno stackoverflow in c #? In quel caso, è in qualche modo uno stackoverflow, poiché è indistinguibile da uno ... Tuttavia - votato per tutte le ragioni sopra
Mo.

18
Se una pila trabocca nel bosco senza che nessuno sia in grado di catturare, genera un'eccezione?

Non direi il "più breve" poiché non è che tu possa compilare un one-liner in quel modo. Si fa lanciare rapidamente un overflow dello stack anche se credo.
Dominic K,

159

Nemerle :

Ciò provoca l'arresto anomalo del compilatore con StackOverflowException:

def o(){[o()]}

119

Il mio attuale migliore (nell'assemblaggio x86) è:

push eax
jmp short $-1

che risulta in 3 byte di codice oggetto ( 50 EB FD). Per il codice a 16 bit, questo è anche possibile:

call $

che risulta anche in 3 byte ( E8 FD FF).


6
Il conteggio dei byte dopo la "compilazione" (o il montaggio) non è code-golf.
Louis Brandy,

37
La domanda dice "[...] qual è il codice più breve per causare un overflow dello stack?" Non specifica il codice sorgente, il codice interpretato, il codice macchina, il codice oggetto o il codice gestito ...
Anders Sandvig,

Per la cronaca, il server di golf di Shin ti consente di inviare il codice oggetto da giudicare, anche se conterà anche tutte le intestazioni ELF. Hmm ....
Chris Jester-Young,

Vedi, ad esempio, golf.shinh.org/p.rb?FizzBuzz#x86 per alcuni esempi di questo. (Onestamente non so come le persone possano creare binari ELF a 99 byte, però.) :-P
Chris Jester-Young,

7
@lbrandy: ci sono abbastanza persone che possono scrivere direttamente il codice oggetto. Non posso farlo per x86, ma per un certo microprocessore posso farlo. Conterrei tale codice.
Joey,

113

PIC18

La risposta PIC18 fornita da TK risulta nelle seguenti istruzioni (binarie):

overflow
   PUSH
   0000 0000 0000 0101
   CALL overflow
   1110 1100 0000 0000
   0000 0000 0000 0000

Tuttavia, CALL da solo eseguirà un overflow dello stack:

CALL $
1110 1100 0000 0000
0000 0000 0000 0000

PIC18 più piccolo e più veloce

Ma RCALL (chiamata relativa) è ancora più piccolo (non memoria globale, quindi non è necessario per i 2 byte extra):

RCALL $
1101 1000 0000 0000

Quindi il più piccolo sul PIC18 è una singola istruzione, 16 bit (due byte). Ciò richiederebbe 2 cicli di istruzioni per loop. A 4 cicli di clock per ciclo di istruzioni hai 8 cicli di clock. Il PIC18 ha uno stack di 31 livelli, quindi dopo il 32 ° loop si sovrapporrà allo stack, in 256 cicli di clock. A 64 MHz, dovresti sovraccaricare lo stack in 4 micro secondi e 2 byte .

PIC16F5x (anche più piccolo e più veloce)

Tuttavia, la serie PIC16F5x utilizza istruzioni a 12 bit:

CALL $
1001 0000 0000

Ancora una volta, due cicli di istruzione per loop, 4 clock per istruzione, quindi 8 cicli di clock per loop.

Tuttavia, il PIC16F5x ha uno stack a due livelli, quindi sul terzo loop traboccerebbe, in 24 istruzioni. A 20 MHz, traboccerebbe in 1,2 micro secondi e 1,5 byte .

Intel 4004

L' Intel 4004 ha un'istruzione di subroutine di chiamata a 8 bit:

CALL $
0101 0000

Per i curiosi che corrispondono a un ascii 'P'. Con uno stack a 3 livelli che richiede 24 cicli di clock per un totale di 32,4 micro secondi e un byte . (A meno che non overclocki il tuo 4004 - dai, sai che vuoi farlo.)

Che è piccolo come la risposta befunge, ma molto, molto più veloce del codice befunge in esecuzione negli interpreti correnti.


77

C #:

public int Foo { get { return Foo; } }

57

Hoot overflow!

//              v___v
let rec f o = f(o);(o)
//             ['---']
//             -"---"-

55

Ogni attività ha bisogno dello strumento giusto. Scopri il linguaggio SO Overflow , ottimizzato per produrre stack overflow:

so

7
Se stai creando un linguaggio specializzato per la generazione di overflow con un minimo di codice, ovviamente vorrai (1) un input vuoto produce codice di overflow dello stack (probabilmente un piccolo binario che esegue il codice nativo generato dalla voce del codice assembly) o (2 ) tutti i programmi di input producono detto binario.
Jared Updike,

Hmmm, non Turing completo. Non so se potresti chiamarla ancora una lingua ...
Adam Davis,

42

TeX:

\def~{~.}~

Risultati in:

! Capacità di TeX superata, scusa [dimensione dello stack di input = 5000].
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
...
<*> \ def ~ {~.} ~

LaTeX:

\end\end

Risultati in:

! Capacità di TeX superata, scusa [dimensione dello stack di input = 5000].
\ end # 1 -> \ csname end # 1
                      \ endcsname \ @checkend {# 1} \ expandafter \ endgroup \ if @ e ...
<*> \ end \ end

Poiché ~è attivo, può essere utilizzato al posto di \a. E ho scoperto il codice LaTeX completamente per caso. :)
Josh Lee

35

Assemblatore Z-80 - nella posizione di memoria 0x0000:

rst 00

un byte - 0xC7 - loop infinito di spingere il PC corrente nello stack e saltare all'indirizzo 0x0000.


2
Ricordo che una eprom vuota sarebbe stata tutta 0xffs che sono le prime 7 (= chiama 0x0038) istruzioni. Sarebbe utile per il debug dell'hardware con un oscilloscopio. Il bus degli indirizzi scorreva nello spazio di 64 KB quando lo stack traboccava ripetutamente, intervallato da letture di 0xff da 0x0038.
Bill Forster,


29

Un altro esempio di PHP:

<?
require(__FILE__);

4
Potresti anche essere cortocircuitato saltando la parentesi (ma includendo lo spazio al posto del primo).
alex,

26

Che ne dici di quanto segue in BASIC:

10 GOSUB 10

(Non ho un interprete BASIC, temo, quindi è una supposizione).


3
Non è davvero uno stack overflow poiché BASIC è un linguaggio stackless. Perfino VB (che ha uno stack) non avrebbe traboccato da questo dato che sta saltando, non creando un frame stack.
Daniel Spiewak,

21
Questo è un GOSUB, non un GOTO. Dal momento che RETURNè da dove è stato chiamato, sicuramente sta usando uno stack?
Tom,

3
Sì sono d'accordo. Ho avuto molti overflow dello stack in BASIC negli anni '80.
Nick

6
Ho eseguito questo in yabasic solo per divertirmi, e ha quasi buttato giù il mio computer. Grazie a dio malloc alla fine fallì, ma stavo chiamando come nessun domani.
Adam Rosenfield,

2
Oops mi dispiace Adam ... mi ricorda un momento in uni in cui qualcuno ha accidentalmente scritto un programma che ricorsivamente biforcava: ha eliminato un intero server Silicon Graphics.
stusmith,

26

Ho adorato la risposta di Cody, quindi ecco il mio contributo simile, in C ++:

template <int i>
class Overflow {
    typedef typename Overflow<i + 1>::type type;
};

typedef Overflow<0>::type Kaboom;

Non è una voce di codice golf in alcun modo, ma comunque, qualsiasi cosa per un overflow del meta stack! :-P


21

Ecco il mio contributo in C, del peso di 18 caratteri:

void o(){o();o();}

È molto più difficile ottimizzare la chiamata in coda! :-P


4
Non compilare per me: "riferimento indefinito a" main ": P
Andrew Johnson,

1
Non capisco: perché chiamare o () 2x?
Dinah,

3
@Dinah: uno dei vincoli del mio contest era che l'ottimizzazione della coda non conta come ricorsione; è solo un ciclo iterativo. Se hai scritto o () una sola volta, questo può essere ottimizzato per la coda in qualcosa del genere (da un compilatore competente): "o: jmp o". Con 2 chiamate di o, il compilatore deve usare qualcosa del tipo: "o: call o; jmp o". È l'istruzione "call" ricorsiva che fa traboccare lo stack.
Chris Jester-Young,

Hai ragione - non ho prestato attenzione a quella parte. Grazie per il chiarimento.
Dinah,


17

Javascript

Per tagliare qualche altro personaggio e farci cacciare da più negozi di software, andiamo con:

eval(i='eval(i)');

15

Groovy:

main()

$ groovy stack.groovy:

Caught: java.lang.StackOverflowError
    at stack.main(stack.groovy)
    at stack.run(stack.groovy:1)
 ...

Votato perché è abbastanza interessante. Espone una debolezza piuttosto fastidiosa nel compilatore Groovy (tali code di coda possono essere integrate al momento della compilazione).
Daniel Spiewak,

sei sicuro che sia una chiamata in coda? che cadere dalla fine del programma non invoca la shell dell'interprete?
Aaron,


14
Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky);

Speriamo in nessuna ricorsione della coda!


1
Hehe, divertente. Relativamente alle conversazioni, anche l'idea dell '"effetto camera dell'eco" è piuttosto interessante. Non del tutto inducendo lo overflow dello stack, ma comunque.
Chris Jester-Young,

8
Non sarebbe un'eccezione puntatore null? Scusa, lo so che è uno scherzo.
James,

12

C - Non è il più corto, ma è privo di ricorsioni. Inoltre non è portatile: si arresta in modo anomalo su Solaris, ma alcune implementazioni alloca () potrebbero restituire un errore qui (o chiamare malloc ()). È necessaria la chiamata a printf ().

#include <stdio.h>
#include <alloca.h>
#include <sys/resource.h>
int main(int argc, char *argv[]) {
    struct rlimit rl = {0};
    getrlimit(RLIMIT_STACK, &rl);
    (void) alloca(rl.rlim_cur);
    printf("Goodbye, world\n");
    return 0;
}

Puoi anche semplicemente fare "ulimit -s16" per impostare lo stack davvero piccolo. Più piccolo di circa 16 e il programma non funziona nemmeno (apparentemente argomenti insufficienti!).
Andrew Johnson,

11

perl in 12 caratteri:

$_=sub{&$_};&$_

bash in 10 caratteri (lo spazio nella funzione è importante):

i(){ i;};i


11

Python :

so=lambda:so();so()

In alternativa:

def so():so()
so()

E se la coda ottimizzata di Python chiama ...:

o=lambda:map(o,o());o()

Fortunatamente per te, Python non esegue l'ottimizzazione della coda; altrimenti, sarebbe squalificato come altre due risposte finora. :-P
Chris Jester-Young,

10

Sto selezionando la "migliore risposta" dopo questo post. Ma prima, vorrei riconoscere alcuni contributi molto originali:

  1. quelli di Aku. Ognuno esplora un modo nuovo e originale di causare lo straripamento dello stack. L'idea di fare f (x) ⇒ f (f (x)) è una che esplorerò nella prossima voce, di seguito. :-)
  2. Quello di Cody che ha dato al compilatore Nemerle un overflow dello stack.
  3. E (un po 'a malincuore), quello di GateKiller sul lancio di un'eccezione di overflow dello stack. :-P

Per quanto adoro quanto sopra, la sfida riguarda il code golf e, per essere onesti con gli intervistati, devo assegnare la "migliore risposta" al codice più corto, che è la voce Befunge; Non credo che nessuno sarà in grado di batterlo (anche se Konrad ha sicuramente provato), quindi congratulazioni Patrick!

Vedendo il gran numero di soluzioni stack-overflow-by-recursion, sono sorpreso che nessuno (al momento della stesura attuale) abbia sollevato il combinatore Y (vedi il saggio di Dick Gabriel, Il perché di Y , per un primer). Ho una soluzione ricorsiva che utilizza il combinatore Y, nonché l'approccio aku f (f (x)). :-)

((Y (lambda (f) (lambda (x) (f (f x))))) #f)

8

Ecco un altro interessante di Scheme:

((lambda (x) (xx)) (lambda (x) (xx)))

Molto bello, e c'è anche una buona simmetria. Inoltre, usare la formulazione (lambda (x) (xx)): ((Y (lambda (x) (xx))) #f) è anche molto divertente!
Chris Jester-Young,

Oh, è carino. Funziona anche in Ruby, anche se non è bello come in Scheme: lambda {| x | x.call x} .call lambda {| x | x.call x}
Wayne Conrad,

7

Giava

Versione leggermente più breve della soluzione Java.

class X{public static void main(String[]a){main(a);}}

5
Oppure (stesso numero di caratteri): vuoto statico pubblico principale (String ... a) {main ();}
Michael Myers

O per i ragazzi TDD (stesso numero di caratteri): classe pubblica ${@org.junit.Test pubblico vuoto $ () {$ ();}}
mhaller

Non è ancora il più breve (vedi la mia risposta)
Draemon,


5

3 byte:

label:
  pusha
  jmp label

Aggiornare

Secondo la (vecchia?) Documentazione Intel (?) , Si tratta anche di 3 byte:

label:
  call label


Sono 3 byte in modalità 32 bit. Bella risposta, considerando che riempirà lo stack molto più velocemente della mia risposta!
Chris Jester-Young,

Secondo penguin.cz/~literakl/intel/j.html#JMP , jmp è 3 byte con indirizzo di destinazione relativo a 8, 16 o 32 bit. Il pusha è anche 1 byte, per un totale di 4
Anders Sandvig,

Esistono tre tipi di jmp, short, near e far. Il jmp breve (utilizzando il codice operativo 0xEB) è di due byte. La destinazione deve essere tra -128 e 127 byte di distanza dall'istruzione successiva. :-)
Chris Jester-Young,

Forse hai ragione. Sono troppo pigro per scavare il mio assemblatore e verificare ...;)
Anders Sandvig,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.