初投稿です。お見苦しいところもあると思いますが、ご了承ください。
pythonから各言語をセグフォらせるのが流行ってきたので...
pythonを三行でセグフォらせる
pythonを2行でセグフォらせる
C言語で16文字でセグフォらせる
Pythonを33文字でセグフォらせる
Rustを5行でセグフォらせる
C 言語で 5 文字でセグフォらせる
実際のコード
無理に6行にした結果
import java.lang.reflect.*;
import sun.misc.Unsafe;
class A {public static void main(String[] a) throws Exception {Constructor<Unsafe> b=Unsafe.class.getDeclaredConstructor();
b.setAccessible(true);
b.newInstance().putLong(0, 0);} }
無理やり過ぎで可読性が皆無です
コードを整理すると
import java.lang.reflect.*;
import sun.misc.Unsafe;
class A {
public static void main(String[] a) throws Exception{
Constructor<Unsafe> b=Unsafe.class.getDeclaredConstructor();
b.setAccessible(true);
b.newInstance().putLong(0, 0);
}
}
あまり変わりませんね...
実行結果
Linux(Ubuntu)の場合
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f8b7c08ba84, pid=1986, tid=1987 #ここでセグフォ(アクセス違反)が起きている
#
# JRE version: OpenJDK Runtime Environment (14.0.1+7) (build 14.0.1+7-Ubuntu-1ubuntu1)
# Java VM: OpenJDK 64-Bit Server VM (14.0.1+7-Ubuntu-1ubuntu1, mixed mode, sharing, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# V [libjvm.so+0xe99a84]
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/user/hs_err_pid1986.log
#
# If you would like to submit a bug report, please visit:
# Unknown
#
Aborted
(Ubuntu+OpenJDK Runtime Environment 14.0.1)
WSL2で実行したため実際の結果とは異なる場合があるかもしれません。
実行すると禍々しいエラー文と750行近くのエラー文が生成されます。
エラー文の5行目に注目してすると...
SIGSEGV(0xb)atpc=0x00007f8b7c08ba84,pid=1986, tid=1987
とあるようにSIGSEGV
(アクセス違反)シグナルをを受け取ってますね
さらにlogファイルは呼び出されたファイルやメモリダンプが詳しく生成されます。
Ubuntuのlogファイル49行目:
49:siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000000
とあるようにアドレスの0番地
にアクセスしてSEGV_MAPERR
(マッピングされてないメモリにアクセスしたときに起こるエラー)
が起こっていることが分かりますね
Windowsの場合
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffd4fa119b7, pid=18520, tid=8224
#
# JRE version: Java(TM) SE Runtime Environment (14.0.1+7) (build 14.0.1+7)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (14.0.1+7, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# V [jvm.dll+0x7219b7]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\User\aa\hs_err_pid18520.log
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
#
(Windows + Java(TM) SE Runtime Environment 14.0.1)
先ほどのUbuntuと同じく禍々しいエラー文と共にclassファイルと同じディレクトリにログファイルが生成されます。
4行目に注目すると
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffd4fa119b7, pid=18520, tid=8224
EXCEPTION_ACCESS_VIOLATION
(アクセス違反)が起きていることが分かりますね。
同じくclassファイルと同じディレクトリに生成されたlogファイルを覗いてみると
Windowsのlogファイルの40行目:
40:#siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), writing address 0x0000000000000000
メモリの0番地
にwriting
(書き込み)してアクセス違反起こっていることが分かりますね。
##セグフォについて
なんだよ!Segmentation Fault
エラーでてないやんけ!詐欺やん!って思ってる人もいると思いますが、
UNIXライクのオペレーティングシステム上では、不正なメモリにアクセスをするプロセスは
SIGSEGV
シグナルを受け取る。Microsoft Windows上では、不正なメモリにアクセスするプロセスはSTATUS_ACCESS_VIOLATION
例外を受け取る
とのことから私はセグフォとして扱っています。
超大雑把な解説
sun.misc.Unsafe
でJavaでもメモリをアクセスする能力を手に入れれます。
じゃあUnsafe.getUnsafe().putLong(0, 0)
でもっと短くできんじゃないの?って思うかもしれませんが、
javaのunsafe
は名前の通りものすごく安全ではないクラスです。
finalの値を変更したりメモリを確保したり、アクセスしたりやりたい放題できます(ある程度制限があるらしいが)
そのため、コンストラクタがprivateでさらにgetunsafe()
はgetclassloder()
がnullの場合しかインスタンスを生成できません。
その抜け道として、リフレクションAPIで無理やりインスタンス化、さらにsetAccessible(true)
を使って普通はアクセスできないメソッドにアクセスできるようにします。
最後にputLong(address, x);
でaddress
にメモリ番地、x
に適当な値を入れることでjavaでもセグフォを引き寄せることができました!!やったね!
#参考にしたサイト等
sun.misc.Unsafe の魔力
何かの時にスッと使える力技 - Reflection 編
セグメンテーション違反-wikipedia
編集リクエストなど気軽に送りつけてください。
拙い文章ですが最後まで閲覧いただきありがとうございました!