Napisz najkrótszy kod, który wywołuje błąd segmentacji (SIGSEGV) w dowolnym języku programowania.
Napisz najkrótszy kod, który wywołuje błąd segmentacji (SIGSEGV) w dowolnym języku programowania.
Odpowiedzi:
main;
Jest to deklaracja zmiennej - int
typ jest domyślny (funkcja skopiowana z języka B) i 0
jest wartością domyślną. Podczas wykonywania próbuje wykonać liczbę (liczby nie są wykonywalne) i powoduje SIGSEGV
.
0
. static
zmienne zaczynają się 0
i main;
są static
, jak zadeklarowałem, poza funkcją. c-faq.com/decl/initval.html
main
int, jest ona zlokalizowana .bss
, zwykle funkcje są zlokalizowane .text
, kiedy jądro ładuje program elf, tworzy stronę wykonywalną .text
i nie -wykonalne .bss
, więc wywołując main, przeskakujesz na stronę niewykonywalną, a wykonanie czegoś na takiej stronie jest błędem ochrony.
main __attribute__((section(".text#")))=0xc3;
FTFY (przynajmniej wydaje się, że powraca bez awarii na moim x86).
const main=195;
. Interesujące jest to, że działa, celem tego golfowego wyzwania golfowego było sprawienie, by kod działał nieprawidłowo, a nie działał :).
kill -11 $$
RET
Ten kod nie działa poprawnie.
exec'()'*7**6
System Windows zgłasza kod błędu c00000fd (przepełnienie stosu), który, jak zakładam, jest podtypem błędu segmentacji.
Dzięki Alex A. i Mego potwierdzono, że powoduje błędy segmentacji również w systemach Mac i Linux. Python jest wybranym językiem do przenośnego zawieszania programów.
Segmentation fault: 11
na Macu
Segmentation fault (core dumped)
w systemie Linux
\def~#1{\meaning}\write0{\expandafter~\string}\bye
Jest to prawdopodobnie błąd , ale nie jest obecny w oryginalnym TeX-ie napisanym przez Knutha: kompilacja kodu tex filename.tex
zamiast pdftex filename.tex
nie powoduje awarii pliku.
OBTW
Nie działa online, tylko w tłumaczu C.
>>> import ctypes;ctypes.string_at(0)
Segmentation fault
Źródło: http://bugs.python.org/issue1215#msg143236
>>> import sys;sys.setrecursionlimit(1<<30);f=lambda f:f(f);f(f)
Segmentation fault
Źródło: http://svn.python.org/view/python/trunk/Lib/test/crashers/recursive_call.py?view=markup
To jest wersja Pythona, na której testuję:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Generalnie interpreter Pythona jest trudny do rozbicia, ale powyższe jest selektywną obelgą ...
main(){raise(11);}
int func()
. tj. funkcja zwracająca int
, przyjmująca nieokreślone parametry. W tym przypadku raise
funkcja zwraca int, biorąc argument int, więc to działa (nawet jeśli kompilator narzeka).
/(?{??})/
W wersji 5.14 silnik regex został ponownie wprowadzony, aby nie można go było rozbić w ten sposób, ale w wersji 5.12 i wcześniejszej nastąpi awaria, jeśli spróbujesz tego.
Wydaje się to dziwne, ale w 32-bitowych systemach Windows tworzenie i wykonywanie pustego pliku .com może powodować awarie, w zależności od ... czegoś. DOS po prostu akceptuje to (8086 nie ma zarządzania pamięcią, nie ma żadnych znaczących segmentów do uszkodzenia), a 64-bitowy system Windows odmawia uruchomienia (x86-64 nie ma trybu v86 do uruchomienia pliku .com).
<.
Tak, to zależy od implementacji. SIGSEGV jest prawdopodobnie wynikiem dobrego kompilatora.
<
powinno mieć żadnego efektu ani się zawijać.
foreign import ccall main::IO()
Powoduje to segfault po skompilowaniu z GHC i uruchomieniu. Flagi rozszerzeń nie są potrzebne, ponieważ interfejs funkcji zagranicznej znajduje się w standardzie Haskell 2010.
Wersja C to:
*(int*)0=0;
Cały program (niezupełnie zgodny z ISO, załóżmy, że to K&R C) ma 19 znaków:
main(){*(int*)0=0;}
Wariant asemblera:
orl $0,0
Cały program ma 24 znaki (tylko do oceny, ponieważ tak naprawdę nie jest asemblerem):
main(){asm("orl $0,0");}
EDYCJA :
Kilka wariantów C. Pierwszy wykorzystuje zerową inicjalizację globalnej zmiennej wskaźnika:
*p;main(){*p=0;}
Drugi wykorzystuje nieskończoną rekurencję:
main(){main();}
Ostatni wariant jest najkrótszy - 7 (15) znaków.
EDYCJA 2 :
Wymyślił jeszcze jeden wariant, który jest krótszy niż którykolwiek z powyższych - 6 (14) znaków. Zakłada, że dosłowne ciągi znaków są umieszczane w segmencie tylko do odczytu.
main(){*""=0;}
EDYCJA 3 :
I moja ostatnia próba - 1 postać:
P
Po prostu skompiluj to w ten sposób:
cc -o segv -DP="main(){main();}" segv.c
main
jest globalna zmienna int inicjowana zerem, więc otrzymujemy wynik próby wykonania kilku bajtów zerowych. W x86 byłoby to coś w rodzaju add %al,(%rax)
całkowicie poprawnej instrukcji, która próbuje dotrzeć do pamięci pod adresem zapisanym w %rax
. Szanse na dobry adres są minimalne.
[dx0]dx
powoduje przepełnienie stosu
[dx0]
zapisuje dx0
na stosie, następnie d
duplikuje element górnego stosu, a następnie x
wysuwa element górnego stosu ( dx0
) i wykonuje go. Który duplikuje element najwyższego stosu i zaczyna go wykonywać ... 0
musi tam być, aby zapobiec wywołaniu ogona, więc wszystkie się gromadzą.
Nieco cheatycznym rozwiązaniem jest ogolenie jednego kawałka sztuczki Joey Adamsa :
kill 11,$$
Jednak, aby uzyskać prawdziwy błąd w Perlu, unpack p
jest oczywiste rozwiązanie:
unpack p,1x8
Technicznie nie jest to gwarantowane segfault, ponieważ adres 0x31313131 (lub 0x313131313131313131 w systemach 64-bitowych) może przypadkowo wskazywać prawidłową przestrzeń adresową. Ale szanse są przeciwne. Ponadto, jeśli perl jest kiedykolwiek przenoszony na platformy, na których wskaźniki są dłuższe niż 64 bity, x8
należy je zwiększyć.
1x8
sprawa?
"11111111".
Obj.magic 0 0
Korzysta z funkcji Obj.magic
, która niesłusznie wymusza dowolne dwa typy. W tym przypadku wymusza 0 (przechowywany jako bezpośrednia wartość 1, z powodu bitu znacznika używanego przez GC) na typ funkcji (przechowywany jako wskaźnik). W ten sposób próbuje się wyrejestrować adres 1, co oczywiście spowoduje awarię.
it coerces 0 (stored as the immediate value 1)
- dlaczego 0 jest przechowywane jako 1?
Obj.magic()0
jest o jeden char krótszy :)
Grał w golfa
. $0
Rekurencyjnie dołącz skrypt do siebie.
Wyjaśniono
Rekurencyjna operacja „source” (.) Powoduje ostatecznie przepełnienie stosu, a ponieważ Bash nie integruje się z libsigsegv , skutkuje to SIGSEGV.
Zauważ, że nie jest to błąd, ale oczekiwane zachowanie, jak omówiono tutaj .
Test
./bang
Segmentation fault (core dumped)
⌠[]+⌡9!*.
Jeśli powyższe nie ulega awarii, spróbuj zwiększyć liczbę (liczby wielocyfrowe są określone w rzeczywistości z wiodącym dwukropkiem)
Zawiesza interpreter, wykorzystując błąd w pythonie dotyczący głęboko zagnieżdżonych itertools.chain
obiektów, który faktycznie używa do implementacji +
operatora.
System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr.Zero);
unsafe{int i=*(int*)0;}
Musi się skompilować z / unsafe, aby ten działał. Z jakiegoś powodu nie rozumiem, *(int*)0=0
po prostu zgłasza wyjątek NullReferenceException, podczas gdy ta wersja zapewnia prawidłowe naruszenie praw dostępu.
int i=*(int*)0;
powroty NullReferenceException dla mnie.
*(int*)-1=0
. Uzyskać naruszenie zasad dostępu.
*(int*)0=0
zgłoszenia wyjątku jest prawdopodobnie optymalizacja. W szczególności, aby uniknąć kosztu sprawdzania null
, optymalizator może usunąć kontrole zerowe, ale gdy wystąpi awaria, może ponownie go wyrzucić NullReferenceException
.
$ pil
: ('0)
Segmentation fault
To jest zamierzone zachowanie. Jak opisano na ich stronie internetowej:
Jeśli niektóre języki programowania twierdzą, że są „szwajcarskim wojskowym nożem programistycznym”, to PicoLisp można nazwać „skalpelem programowania”: ostry, dokładny, mały i lekki, ale także niebezpieczny w rękach niedoświadczonego.
real,pointer::p(:)=>null()
p(1)=0.
end
Kompilacja:
gfortran segv.f90 -o segv
Wykonanie:
./segv
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7FF85FCAE777
#1 0x7FF85FCAED7E
#2 0x7FF85F906D3F
#3 0x40068F in MAIN__ at segv.f90:?
Erreur de segmentation (core dumped)
Materiały:
gfortran --version
GNU Fortran (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
main(a){*(&a-1)=1;}
Koryguje wartość adresu zwrotnego funkcji głównej, więc po powrocie otrzymuje SIGSEGV main
.
(staje się to dla mnie tematem, być może dlatego, że jest to jedyny język, jaki znam, którego nikt inny tutaj nie zna).
inc(r0)
Inkrementuje pojedynczy bajt adresowany przez wartość początkową r0 [która według debuggera simh to 05162] w chwili uruchomienia programu.
0000000 000407 000002 000000 000000 000000 000000 000000 000000
0000020 005210 000000
I jak zawsze, zewnętrzne bajty na końcu można usunąć za pomocą paska.
Podjąłem kilka prób skrócenia źródła, ale zawsze otrzymywałem błąd składniowy lub SIGBUS.
W odpowiedzi na moje pytanie Amro wymyślił to dziwactwo:
S = struct();
S = setfield(S, {}, 'g', {}, 0)
clear()
Czyści absolutnie wszystko, nie tylko obecny zakres, co oczywiście powoduje wiele borków, co powoduje wysadzenie JS i uszkodzenie pliku
j1Z
W tej części wyjaśniam, w jaki sposób wymyśliłem tę odpowiedź, chyba że nie mam żadnych zasad . Gdyby ktokolwiek mógł mi to wyjaśnić, byłbym wdzięczny.
Wyjaśnienie
j
podnosi kwadrat do kwadratu i wywołuje się rekurencyjnie, aż baza będzie co najmniej tak duża jak liczba. Ponieważ podstawa wynosi 0 , to nigdy się nie zdarza. Przy dostatecznie wysokim limicie rekurencji otrzymujesz segfault.
j
na 1
i 0
, który próbuje przekonwertować 1
na bazę 0
. Skąd ta awaria, nie mam pojęcia ...