6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

6行でJavaをセグフォらせる

Last updated at Posted at 2020-07-02

初投稿です。お見苦しいところもあると思いますが、ご了承ください。

pythonから各言語をセグフォらせるのが流行ってきたので...

pythonを三行でセグフォらせる
pythonを2行でセグフォらせる
C言語で16文字でセグフォらせる
Pythonを33文字でセグフォらせる
Rustを5行でセグフォらせる
C 言語で 5 文字でセグフォらせる

実際のコード

無理に6行にした結果

a.java
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);} }

無理やり過ぎで可読性が皆無です
コードを整理すると

a.java
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)の場合

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行目に注目してすると...

4行目
SIGSEGV(0xb)atpc=0x00007f8b7c08ba84,pid=1986, tid=1987

とあるようにSIGSEGV(アクセス違反)シグナルをを受け取ってますね

さらにlogファイルは呼び出されたファイルやメモリダンプが詳しく生成されます。

Ubuntuのlogファイル49行目:

has_err_pid{posess_id}.log
49:siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000000

とあるようにアドレスの0番地にアクセスしてSEGV_MAPERR(マッピングされてないメモリにアクセスしたときに起こるエラー)
が起こっていることが分かりますね

Windowsの場合

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行目に注目すると

4行目
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffd4fa119b7, pid=18520, tid=8224

EXCEPTION_ACCESS_VIOLATION(アクセス違反)が起きていることが分かりますね。
同じくclassファイルと同じディレクトリに生成されたlogファイルを覗いてみると

Windowsのlogファイルの40行目:

has_err_pid{prosess_id}.log
40:#siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), writing address 0x0000000000000000

メモリの0番地writing(書き込み)してアクセス違反起こっていることが分かりますね。

##セグフォについて

なんだよ!Segmentation Faultエラーでてないやんけ!詐欺やん!って思ってる人もいると思いますが、

"wikipedia -セグメンテーション違反-"より

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

編集リクエストなど気軽に送りつけてください。
拙い文章ですが最後まで閲覧いただきありがとうございました!

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?