Écrivez le code le plus court qui cause une erreur de segmentation (SIGSEGV) dans n’importe quel langage de programmation.
Écrivez le code le plus court qui cause une erreur de segmentation (SIGSEGV) dans n’importe quel langage de programmation.
Réponses:
main;
C'est une déclaration de variable - le int
type est implicite (fonctionnalité copiée à partir du langage B) et sa 0
valeur par défaut. Lorsqu'elle est exécutée, cette option tente d'exécuter un nombre (les nombres ne sont pas exécutables) et les causes SIGSEGV
.
0
. static
les variables commencent comme 0
, et main;
sont static
, comme je l'ai déclaré en dehors de la fonction. c-faq.com/decl/initval.html
main
un int, il est situé dans .bss
, les fonctions sont généralement situées dans .text
. Lorsque le noyau charge le programme elf, il crée une page exécutable pour .text
et non. -executable for .bss
, donc en appelant main, vous passez à une page non-exécutable, et l'exécution de quelque chose sur une telle page est une faute de protection.
main __attribute__((section(".text#")))=0xc3;
FTFY (du moins ça a l'air de revenir sans planter sur mon x86).
const main=195;
. Ce qui est intéressant, c’est que ça marche, le but de ce défi de jouer au code était de faire en sorte que le code segfault, et non pas fonctionne :)
kill -11 $$
RET
Ce code segfaults.
exec'()'*7**6
Windows signale un code d'erreur c00000fd (débordement de pile) qui, je suppose, est un sous-type d'erreur de segmentation.
Merci à Alex A. et Mego, il a été confirmé qu’il pouvait également causer des erreurs de segmentation sur les systèmes Mac et Linux. Python est le langage de choix pour le crash portable de vos programmes.
Segmentation fault: 11
sur Mac
Segmentation fault (core dumped)
sur Linux
\def~#1{\meaning}\write0{\expandafter~\string}\bye
C’est en fait probablement un bogue , mais il n’est pas présent dans le TeX original, écrit par Knuth: compiler le code avec tex filename.tex
au lieu de pdftex filename.tex
ne produit pas de segfault.
OBTW
Ne fonctionne pas en ligne, uniquement dans l'interprète C.
>>> import ctypes;ctypes.string_at(0)
Segmentation fault
Source: http://bugs.python.org/issue1215#msg143236
>>> import sys;sys.setrecursionlimit(1<<30);f=lambda f:f(f);f(f)
Segmentation fault
Source: http://svn.python.org/view/python/trunk/Lib/test/crashers/recursive_call.py?view=markup
Voici la version Python sur laquelle je teste:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
En général, l'interpréteur Python est difficile à planter, mais ce qui précède est abusif sélectif ...
main(){raise(11);}
int func()
. c'est à dire une fonction retournant int
, prenant des paramètres non spécifiés. Dans ce cas, il raise
s’agit d’une fonction renvoyant int, prenant un argument int, donc cela fonctionne (même si le compilateur se plaint).
/(?{??})/
En 5.14, le moteur des expressions rationnelles a été rendu réentrant de sorte qu'il ne puisse pas être planté de cette façon, mais 5.12 et les versions antérieures segfont par défaut si vous essayez ceci.
Cela semblera étrange, mais sur les systèmes Windows 32 bits, la création et l’exécution d’un fichier .com vide peut entraîner une erreur de segmentation, selon ... quelque chose. DOS l'accepte simplement (le 8086 n'ayant pas de gestion de mémoire, il n'y a pas de segments significatifs à blâmer) et Windows 64 bits refuse de l'exécuter (x86-64 n'ayant pas de mode v86 pour exécuter un fichier .com).
<.
Oui, cela dépend de la mise en œuvre. SIGSEGV est le résultat probable d'un bon compilateur.
<
devrait soit n'avoir aucun effet ou envelopper.
foreign import ccall main::IO()
Cela produit une erreur de segmentation une fois compilé avec GHC et exécuté. Aucun indicateur d'extension n'est nécessaire, l'interface de fonction étrangère étant au standard Haskell 2010.
La version C est:
*(int*)0=0;
L'ensemble du programme (pas tout à fait conforme à ISO, supposons qu'il s'agisse de K & R C) comporte 19 caractères:
main(){*(int*)0=0;}
Variante d'assembleur:
orl $0,0
Le programme entier a une longueur de 24 caractères (juste pour l'évaluation, car ce n'est pas réellement un assembleur):
main(){asm("orl $0,0");}
EDIT :
Un couple de variantes C Le premier utilise l'initialisation zéro de la variable de pointeur global:
*p;main(){*p=0;}
Le second utilise une récursion infinie:
main(){main();}
La dernière variante est la plus courte - 7 (15) caractères.
EDIT 2 :
Inventé une autre variante qui est plus courte que l'une des précédentes - 6 (14) caractères. Il suppose que les chaînes littérales sont placées dans un segment en lecture seule.
main(){*""=0;}
EDIT 3 :
Et mon dernier essai - 1 caractère long:
P
Il suffit de le compiler comme ça:
cc -o segv -DP="main(){main();}" segv.c
main
s'agit d'une variable int globale initialisée à zéro. Nous obtenons donc le résultat d'une tentative d'exécution de zéro octet. En x86, ce serait quelque chose comme add %al,(%rax)
une instruction parfaitement valide qui tente d’atteindre la mémoire à une adresse stockée dans %rax
. Les chances d'avoir une bonne adresse sont minimes.
[dx0]dx
provoque un débordement de pile
[dx0]
stocke dx0
sur la pile, puis d
duplique l'élément de pile supérieur, puis x
affiche l'élément de pile supérieur ( dx0
) et l'exécute. Ce qui duplique l’élément supérieur de la pile et commence à l’exécuter ... c’est 0
nécessaire pour éviter que cela ne soit un appel final, de sorte qu’ils se développent tous.
Une solution légèrement tricheuse est de supprimer un personnage du tour basque de Joey Adams :
kill 11,$$
Cependant, obtenir une réelle erreur de segmentation dans Perl unpack p
est la solution évidente:
unpack p,1x8
Techniquement, cette erreur de segmentation n'est pas garantie , car l'adresse 0x31313131 (ou 0x3131313131313131 sur les systèmes 64 bits) peut simplement pointer sur un espace adresse valide par hasard. Mais les chances sont contre elle. De plus, si perl est porté sur des plates-formes où les pointeurs ont une longueur supérieure à 64 bits, x8
il faudra l'augmenter.
1x8
chose?
"11111111".
Obj.magic 0 0
Ceci utilise la fonction Obj.magic
, qui contraint deux types quelconques. Dans ce cas, il force 0 (stocké en tant que valeur immédiate 1 en raison du bit de balise utilisé par le GC) en un type de fonction (stocké sous la forme d'un pointeur). Ainsi, il essaie de déréférencer l'adresse 1, et ce sera bien sûr une erreur de segmentation.
it coerces 0 (stored as the immediate value 1)
- pourquoi 0 est-il stocké comme 1?
Obj.magic()0
est un caractère plus court :)
Golfé
. $0
Inclure récursivement le script en lui-même.
A expliqué
Une opération "source" récursive (.) Provoque éventuellement un débordement de pile et, comme Bash ne s'intègre pas à libsigsegv , il en résulte un SIGSEGV.
Notez qu'il ne s'agit pas d'un bogue, mais d'un comportement attendu, comme discuté ici .
Tester
./bang
Segmentation fault (core dumped)
⌠[]+⌡9!*.
Si ce qui précède ne plante pas, essayez d’augmenter le nombre (des nombres à plusieurs chiffres sont spécifiés dans En fait avec un signe deux-points)
Bloque l'interprète en exploitant un bogue dans Python impliquant des itertools.chain
objets profondément imbriqués , qui utilise en réalité pour implémenter l' +
opérateur.
System.Runtime.InteropServices.Marshal.ReadInt32(IntPtr.Zero);
unsafe{int i=*(int*)0;}
Compiler avec / unsafe pour que celui-ci fonctionne. Pour une raison quelconque, je ne comprends pas, *(int*)0=0
lève simplement une exception NullReferenceException, alors que cette version donne la violation d'accès appropriée.
int i=*(int*)0;
renvoie une exception NullReferenceException pour moi.
*(int*)-1=0
une violation d'accès.
*(int*)0=0
une exception est générée est probablement due à l'optimisation. En particulier, pour éviter les coûts de vérification null
, l'optimiseur peut supprimer les vérifications nulles, mais lorsqu'un défaut de segmentation se produit, il peut le redéfinir correctement NullReferenceException
.
$ pil
: ('0)
Segmentation fault
Ceci est le comportement prévu. Comme décrit sur leur site web:
Si certains langages de programmation prétendent être le "couteau suisse de la programmation", alors PicoLisp pourrait très bien s'appeler le "Scalpel of Programming": précis, précis, petit et léger, mais aussi dangereux pour les inexpérimentés.
real,pointer::p(:)=>null()
p(1)=0.
end
Compilation:
gfortran segv.f90 -o segv
Exécution:
./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)
Matériaux:
gfortran --version
GNU Fortran (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
main(a){*(&a-1)=1;}
Il corrompt la valeur d'adresse de retour de la fonction principale et obtient donc un SIGSEGV au retour de main
.
(Cela devient un thème pour moi, peut-être parce que c'est la seule langue que je sais en quelque sorte que personne d'autre ne connaît ici.)
inc(r0)
Incrémente le seul octet adressé par la valeur initiale de r0 [qui se trouve être 05162 en fonction du débogueur simh] dès le début du programme.
0000000 000407 000002 000000 000000 000000 000000 000000 000000
0000020 005210 000000
Et, comme toujours, les octets superflus à la fin peuvent être supprimés avec strip.
J'ai fait quelques tentatives pour obtenir la source plus courte, mais j'ai toujours eu une erreur de syntaxe ou SIGBUS.
En réponse à une de mes questions , Amro a proposé cette bizarrerie:
S = struct();
S = setfield(S, {}, 'g', {}, 0)
clear()
Efface absolument tout, pas seulement la portée actuelle qui provoque évidemment beaucoup de bouchons qui font exploser JS et segfault
j1Z
Ce serait la partie où j'explique comment j'ai trouvé cette réponse, sauf que je n'ai légitimement aucune idée . Si quelqu'un pouvait expliquer cela pour moi, je vous en serais reconnaissant.
La voici dans un interprète en ligne.
Explication
j
met la base en carré et s’appelle récursivement jusqu’à ce que la base soit au moins aussi grande que le nombre. Puisque la base est 0 , cela ne se produit jamais. Avec une limite de récursion suffisamment élevée, vous obtenez une erreur de segmentation.
j
sur 1
et 0
, qui tente de convertir 1
en base 0
. Pourquoi ces segfaults, je n'en ai aucune idée ...