เขียนรหัสที่สั้นที่สุดที่ทำให้เกิด Segmentation Fault (SIGSEGV)ในภาษาการเขียนโปรแกรมใด ๆ
เขียนรหัสที่สั้นที่สุดที่ทำให้เกิด Segmentation Fault (SIGSEGV)ในภาษาการเขียนโปรแกรมใด ๆ
คำตอบ:
main;
มันคือการประกาศตัวแปร - intประเภทมีนัย (คัดลอกคุณสมบัติจากภาษา B) และ0เป็นค่าเริ่มต้น เมื่อดำเนินการนี้จะพยายามที่จะดำเนินการเป็นจำนวน (ตัวเลขไม่ได้ปฏิบัติการ) SIGSEGVและสาเหตุ
0ที่จริงมันเป็น staticตัวแปรเริ่มต้นเป็น0และmain;เป็นstaticตามที่ฉันประกาศไว้นอกฟังก์ชั่น c-faq.com/decl/initval.html
mainint มันอยู่ใน.bssโดยปกติแล้วฟังก์ชั่นจะอยู่ใน.textเมื่อเคอร์เนลโหลดโปรแกรม elf มันสร้างหน้าปฏิบัติการสำหรับ.textและไม่ - ใช้.bssงานได้ดังนั้นเมื่อเรียก main คุณจะข้ามไปยังหน้าที่ไม่สามารถเรียกใช้ได้และการดำเนินการบางอย่างในหน้านั้นเป็นความผิด
main __attribute__((section(".text#")))=0xc3;FTFY (อย่างน้อยก็ดูเหมือนว่าจะกลับมาโดยไม่ขัดข้องกับ x86 ของฉัน)
const main=195;หรือสั้น ที่น่าสนใจคือมันใช้งานได้เป้าหมายของการแข่งขันกอล์ฟรหัสนี้คือการทำให้รหัส segfault ไม่ทำงาน :)
kill -11 $$
RET
รหัส segfaults นี้
exec'()'*7**6
Windows รายงานรหัสข้อผิดพลาดของ c00000fd (Stack Overflow) ซึ่งฉันคิดว่าเป็นประเภทย่อยของความผิดพลาดในการแบ่งกลุ่ม
ขอบคุณ Alex A. และ Mego จึงได้รับการยืนยันว่าทำให้เกิดข้อผิดพลาดในการแบ่งส่วนในระบบ Mac และ Linux เช่นกัน Python เป็นภาษาที่ใช้ในการหยุดโปรแกรมของคุณ
Segmentation fault: 11บน Mac
Segmentation fault (core dumped)บน Linux
\def~#1{\meaning}\write0{\expandafter~\string}\bye
นี่อาจเป็นจุดบกพร่องแต่ไม่มีใน TeX ดั้งเดิมที่เขียนโดย Knuth: การคอมไพล์โค้ดด้วยtex filename.texแทนที่จะpdftex filename.texไม่สร้าง segfault
>>> import ctypes;ctypes.string_at(0)
Segmentation fault
ที่มา: http://bugs.python.org/issue1215#msg143236
>>> import sys;sys.setrecursionlimit(1<<30);f=lambda f:f(f);f(f)
Segmentation fault
ที่มา: http://svn.python.org/view/python/trunk/Lib/test/crashers/recursive_call.py?view=markup
นี่เป็นเวอร์ชั่น Python ที่ฉันกำลังทดสอบ:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
โดยทั่วไปแล้ว Python interpreter นั้นยากที่จะผิดพลาด แต่ข้างต้นนั้นเป็นการเลือกที่ผิด ...
main(){raise(11);}
int func()ทำได้โดยไม่ต้องประกาศที่มองเห็นเรียบเรียงโดยปริยายบอกว่ามันเป็น เช่นฟังก์ชันที่ส่งคืนintโดยรับพารามิเตอร์ที่ไม่ระบุ ในกรณีนี้raiseคือฟังก์ชันที่ส่งคืนค่า int รับอาร์กิวเมนต์ int ดังนั้นจึงสามารถใช้งานได้ (แม้ว่าคอมไพเลอร์จะบ่น)
/(?{??})/
ใน 5.14 เอ็นจิ้น regex นั้นถูกสร้างขึ้นมาใหม่เพื่อที่จะไม่สามารถชนได้ด้วยวิธีนี้ แต่ 5.12 และก่อนหน้านี้จะเป็น segfault ถ้าคุณลองทำสิ่งนี้
สิ่งนี้จะดูแปลก แต่ในระบบ Windows แบบ 32 บิตการสร้างและดำเนินการไฟล์. com ว่างอาจทำให้เกิด segfault ขึ้นอยู่กับ ... บางสิ่งบางอย่าง DOS เพิ่งยอมรับ (8086 ที่ไม่มีการจัดการหน่วยความจำไม่มีเซ็กเมนต์ที่มีความหมายต่อความผิดพลาด) และ Windows 64 บิตปฏิเสธที่จะเรียกใช้ (x86-64 ไม่มีโหมด v86 ในการเรียกใช้ไฟล์. com)
<.
ใช่นี้ขึ้นอยู่กับการใช้งาน SIGSEGV เป็นผลมาจากคอมไพเลอร์ที่ดี
<ควรจะไม่มีผลกระทบหรือล้อมรอบ
foreign import ccall main::IO()
สิ่งนี้จะสร้าง segfault เมื่อรวบรวมกับ GHC และเรียกใช้ ไม่จำเป็นต้องตั้งค่าสถานะส่วนขยายเนื่องจากอินเตอร์เฟสของฟังก์ชันต่างประเทศอยู่ในมาตรฐาน Haskell 2010
รุ่น C คือ:
*(int*)0=0;
โปรแกรมทั้งหมด (ไม่ตรงตามมาตรฐาน ISO สมมุติว่า K&R C) มีความยาว 19 ตัวอักษร:
main(){*(int*)0=0;}
แอสเซมเบลอร์ตัวแปร:
orl $0,0
โปรแกรมทั้งหมดยาว 24 ตัวอักษร (เพียงเพื่อการประเมินผลเนื่องจากไม่ใช่แอสเซมเบลอร์จริง ๆ ):
main(){asm("orl $0,0");}
แก้ไข :
คู่สายพันธุ์ C อันแรกใช้ zero-initialization ตัวแปรโกลบอลพอยน์เตอร์:
*p;main(){*p=0;}
อันที่สองใช้การเรียกซ้ำแบบไม่สิ้นสุด:
main(){main();}
ตัวแปรสุดท้ายคืออักขระที่สั้นที่สุดหนึ่ง - 7 (15) ตัว
แก้ไข 2 :
คิดค้นตัวแปรอีกตัวหนึ่งซึ่งสั้นกว่าตัวแปรใด ๆ ข้างต้น - 6 (14) ตัวอักษร มันจะถือว่าสตริงตัวอักษรถูกใส่ลงในเซ็กเมนต์แบบอ่านอย่างเดียว
main(){*""=0;}
แก้ไข 3 :
และความพยายามครั้งสุดท้ายของฉัน - ความยาว 1 ตัวอักษร:
P
เพียงแค่รวบรวมมันเช่นนั้น:
cc -o segv -DP="main(){main();}" segv.c
mainคือตัวแปรโกลบอลโกลบอลที่กำหนดค่าเริ่มต้นเป็นศูนย์ดังนั้นสิ่งที่เราได้รับคือผลลัพธ์ของการพยายามดำเนินการศูนย์ไบต์บางส่วน ใน x86 มันจะเป็นสิ่งที่ต้องการซึ่งเป็นคำแนะนำที่ถูกต้องสมบูรณ์ซึ่งพยายามที่จะเข้าถึงหน่วยความจำที่อยู่ที่เก็บไว้ในadd %al,(%rax) %raxโอกาสของการมีที่อยู่ที่ดีมีเพียงเล็กน้อย
[dx0]dx
ทำให้เกิดการล้นสแต็ค
[dx0]เก็บdx0ในสแต็กจากนั้นdทำซ้ำองค์ประกอบสแต็คด้านบนจากนั้นxจะปรากฏองค์ประกอบสแต็คด้านบน ( dx0) และดำเนินการ ซึ่งทำซ้ำองค์ประกอบสแต็คด้านบนและเริ่มดำเนินการ ... 0ความจำเป็นที่จะต้องมีเพื่อป้องกันไม่ให้นี่เป็นการเรียกแบบหางดังนั้นพวกมันจึงสร้างขึ้นทั้งหมด
ทางออกที่โกงเล็กน้อยคือการโกนเคล็ดลับทุบตีของ Joey Adams :
kill 11,$$
อย่างไรก็ตามเพื่อให้ได้ segfault ที่แท้จริงใน Perl unpack pเป็นทางออกที่ชัดเจน
unpack p,1x8
ในทางเทคนิคสิ่งนี้ไม่ได้รับประกันว่าจะได้รับ segfault เนื่องจากที่อยู่ 0x31313131 (หรือ 0x313131313131313131 บนระบบ 64 บิต) อาจชี้ไปยังพื้นที่ที่อยู่ที่ถูกต้องโดยบังเอิญ แต่ราคาถูกกว่านั้น นอกจากนี้ถ้า perl ถูกพอร์ตไปยังแพลตฟอร์มที่พอยน์เตอร์ยาวกว่า 64 บิตx8จะต้องเพิ่มขึ้น
1x8อะไร
"11111111".
import os
os.kill(os.getpid(),11)
กำลังส่งสัญญาณ 11 (SIGSEGV) ในไพ ธ อน
from os import*และkill(getpid(),11)
Obj.magic 0 0
สิ่งนี้ใช้ฟังก์ชั่นObj.magicซึ่งเป็นการข่มขู่ชนิดสองอย่างไม่ปลอดภัย ในกรณีนี้มันจะรวมเป็น 0 (จัดเก็บเป็นค่าทันที 1 เนื่องจากบิตแท็กที่ใช้โดย GC) กับประเภทฟังก์ชั่น (เก็บไว้เป็นตัวชี้) ดังนั้นจึงพยายามปฏิเสธที่อยู่ 1 และแน่นอนว่าจะแยกจากกัน
it coerces 0 (stored as the immediate value 1)- ทำไมถึงถูกจัดเก็บเป็น 1
Obj.magic()0เป็นหนึ่ง :) ถ่านสั้น
แข็งแรงเล่นกอล์ฟ
. $0
รวมสคริปต์ซ้ำเข้าไปในตัวเอง
อธิบาย
การดำเนินการ "ซอร์ส" (.) แบบเรียกซ้ำทำให้เกิดการล้นสแต็กในที่สุดและเนื่องจากBashไม่ได้รวมเข้ากับlibsigsegvผลลัพธ์นี้จึงเป็น SIGSEGV
โปรดทราบว่านี้ไม่ได้เป็นข้อผิดพลาด แต่พฤติกรรมที่คาดหวังตามที่กล่าวไว้ที่นี่
ทดสอบ
./bang
Segmentation fault (core dumped)
⌠[]+⌡9!*.
หากข้างต้นไม่ผิดพลาดให้ลองเพิ่มจำนวน (ระบุตัวเลขหลายหลักในจริงด้วยเครื่องหมายโคลอน)
ขัดข้องล่ามโดยใช้ประโยชน์จากบั๊กในงูหลามที่เกี่ยวข้องกับitertools.chainวัตถุที่ซ้อนกันอย่างล้ำลึกซึ่งใช้ในการปฏิบัติงาน+จริง
System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr.Zero);
unsafe{int i=*(int*)0;}
ต้องรวบรวมด้วย / ไม่ปลอดภัยเพื่อให้การทำงานนี้ ด้วยเหตุผลบางอย่างที่ฉันไม่เข้าใจ*(int*)0=0เพียงแค่โยน NullReferenceException ในขณะที่รุ่นนี้ให้การละเมิดการเข้าถึงที่เหมาะสม
int i=*(int*)0;ผลตอบแทน NullReferenceException สำหรับฉัน
*(int*)-1=0และรับการละเมิดการเข้าถึง
*(int*)0=0เกิดข้อยกเว้นเกิดขึ้นเนื่องจากการปรับให้เหมาะสม โดยเฉพาะอย่างยิ่งที่จะหลีกเลี่ยงค่าใช้จ่ายในการตรวจสอบเพื่อnullเพิ่มประสิทธิภาพการตรวจสอบอาจลบ null แต่เมื่อ segfault เกิดขึ้นมันอาจ rethrow NullReferenceExceptionว่ามันเป็นที่เหมาะสม
$ pil
: ('0)
Segmentation fault
นี่คือพฤติกรรมที่ตั้งใจไว้ ตามที่อธิบายไว้ในเว็บไซต์:
หากภาษาโปรแกรมบางโปรแกรมอ้างว่าเป็น "Swiss Army Knife of Programming" ดังนั้น PicoLisp อาจถูกเรียกว่า "Scalpel of Programming": คมชัดแม่นยำขนาดเล็กและเบา แต่ก็มีอันตรายในมือของผู้ไม่มีประสบการณ์
real,pointer::p(:)=>null()
p(1)=0.
end
รวบรวม:
gfortran segv.f90 -o segv
การดำเนินการ:
./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)
วัสดุ:
gfortran --version
GNU Fortran (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
main(a){*(&a-1)=1;}
มันคุ้มค่าที่อยู่ corrupts การกลับมาของฟังก์ชั่นหลักจึงได้รับ SIGSEGV mainในการกลับมาของ
memf 1
memfหมายถึงหน่วยความจำว่าง1ถูกตีความว่าเป็นตัวชี้
สิ่งนี้มักจะมีประโยชน์สำหรับการแก้ไขจุดบกพร่อง
a=(<int*>0)[0]
(สิ่งนี้กำลังกลายเป็นธีมของฉันอาจเป็นเพราะเป็นภาษาเดียวที่ฉันรู้ว่าไม่มีใครอยู่ที่นี่)
inc(r0)
เพิ่มไบต์เดียวที่จ่าหน้าโดยค่าเริ่มต้นของ r0 [ซึ่งเกิดขึ้นเป็น 05162 ตาม simh debugger] เมื่อเริ่มต้นโปรแกรม
0000000 000407 000002 000000 000000 000000 000000 000000 000000
0000020 005210 000000
และเช่นเคยไบต์ภายนอกที่อยู่ด้านท้ายสามารถลบออกด้วยแถบ
ฉันพยายามทำให้แหล่งที่มาสั้นลง แต่ได้รับข้อผิดพลาดทางไวยากรณ์หรือ SIGBUS เสมอ
ในการตอบสนองต่อคำถามของฉัน Amro ก็คิดเรื่องนี้ขึ้นมา
S = struct();
S = setfield(S, {}, 'g', {}, 0)
clear()
ล้างทุกอย่างไม่เพียง แต่ขอบเขตปัจจุบันซึ่งทำให้บอร์กจำนวนมากซึ่งส่งผลให้ JS เกิดระเบิดและแยกกันไม่ออก
j1Z
นี้จะเป็นส่วนหนึ่งที่ผมอธิบายวิธีการที่ฉันมากับคำตอบนี้นอกจากฉันถูกต้องตามกฎหมายมีเงื่อนงำ หากใครสามารถอธิบายสิ่งนี้ให้ฉันฉันจะขอบคุณ
คำอธิบาย
jยกกำลังสองฐานและเรียกตัวเองซ้ำ ๆ จนกว่าฐานจะใหญ่อย่างน้อยเท่ากับจำนวน เนื่องจากฐานเป็น0นั่นไม่เคยเกิดขึ้น ด้วยการ จำกัด การเรียกซ้ำที่สูงพอคุณจะได้รับ segfault
jเกี่ยวกับการ1และ0ซึ่งพยายามที่จะแปลงเป็นฐาน1 0ทำไม segfaults นั้นฉันไม่มีความคิด ...
jยกกำลังสองฐานและเรียกตัวเองซ้ำ ๆ จนกว่าฐานจะใหญ่อย่างน้อยเท่ากับจำนวน เนื่องจากฐานเป็น0นั่นไม่เคยเกิดขึ้น ด้วยการ จำกัด การเรียกซ้ำที่สูงพอคุณจะได้รับ segfault