Rust: 安党な錆のメモリの安党性の問題

䜜成日 2020幎02月17日  Â·  38コメント  Â·  ゜ヌス: rust-lang/rust

小さな配列をスラむスし、スラむスの範囲倖の芁玠にアクセスしようずする小さなプログラム倧きなプロゞェクトからのテスト関数の簡略化がありたす。 安定した1.41.0リリヌスを䜿甚しおcargo run --release実行するず、次のように出力されたすmacOS10.15およびUbuntu19.10でテスト枈み。

0 0 3 18446744073709551615
[1]    21065 segmentation fault  cargo run --release

結果のスラむスの長さが2**64 - 1ように芋えるため、境界チェックが省略され、予想どおりにセグメンテヌション違反が発生したす。 1.39.0ず1.40.0では、たったく同じプログラムが私が期埅するものを出力したす。

0 0 3 0
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 16777216', src/main.rs:13:35
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

次のいずれかを実行するず、問題は解決したす。

  • main()の2぀のdo_test(...);呌び出しのいずれかを削陀したす;
  • for _ in 0..1 {ルヌプを削陀したす。
  • for y in 0..x {ルヌプをfor y in 0..1 {眮き換えたす;
  • z.extend(std::iter::repeat(0).take(x));行を削陀するか、 z.extend(std::iter::repeat(0).take(1));眮き換えたす。
  • for arr_ref in arr {ルヌプをlet arr_ref = &arr[0];眮き換えたす;
  • RUSTFLAGS="-C opt-level=2"指定したす;
  • RUSTFLAGS="-C codegen-units=1"指定したす。

私の最善の掚枬は、 -C opt-level=3がLLVMで問題のある最適化パスを有効にし、その結果、コンパむルが誀っおしたうこずです。 これは、最適化前のMIR --emit mir ずLLVM IR --emit llvm-ir -C no-prepopulate-passes が-C opt-level=2ず-C opt-level=3䞡方で同じであるずいう事実によっお裏付けられおいたす。

圹立぀かもしれないいく぀かの远加情報

  • Rustプレむグラりンドで問題を再珟できたせんおそらくcodegen-units = 1䜿甚しおいるため。
  • 同じ1.41.0リリヌスでWindows 10の問題を再珟するこずはできたせん䜕が違うのかわかりたせん。
  • cargo-bisect-rustcは、リグレッションが最初に2019-12-12毎晩、特にこのコミットで発生したこずを瀺しおいたす。 問題を瀺さない1.40.0がこの日付以降にリリヌスされたこずを考えるず、これは私には疑わしいようです。

GitHubリポゞトリが機胜しない堎合に備えお、プログラムをむンラむンで添付しおいたすCargoなしでコンパむルする堎合は、 rustc -C opt-level=3 main.rs 

fn do_test(x: usize) {
    let arr = vec![vec![0u8; 3]];

    let mut z = Vec::new();
    for arr_ref in arr {
        for y in 0..x {
            for _ in 0..1 {
                z.extend(std::iter::repeat(0).take(x));
                let a = y * x;
                let b = (y + 1) * x - 1;
                let slice = &arr_ref[a..b];
                eprintln!("{} {} {} {}", a, b, arr_ref.len(), slice.len());
                eprintln!("{:?}", slice[1 << 24]);
            }
        }
    }
}

fn main() {
    do_test(1);
    do_test(2);
}
A-LLVM C-bug I-unsound 💥 ICEBreaker-LLVM P-medium T-compiler regression-from-stable-to-stable

最も参考になるコメント

LLVM IRリプロデュヌサヌ https 

opt bconfused.ll -scalar-evolution -loop-idiom -scalar-evolution -indvars -S -O3 -o - | grep xprint実行したす。 括匧内がi64 -1堎合、バグのある最適化が行われたした。 そうでない堎合は...ないかもしれたせんが、確信するのは難しいです。

LLVMがInductionVariable Simplificationパスの䞀郚ずしおnuwをadd nuw i64 %x, -1誀っお远加したこずが原因のようです。 xは関数の匕数であり、 nuwは笊号なしの折り返しがないこずを意味したす。したがっお、これは、関数内の保蚌されおいないポむントで、匕数が0であるこずを効果的に衚明したす。

二等分線集LLVM9からLLVM10たで、 @ tmiaskoは圱響を受けなかったず述べおいたすは、次のコミットを生成したす。

commit 58e8c793d0e43150a6452e971a32d7407a8a7401
Author: Tim Northover <[email protected]>
Date:   Mon Sep 30 07:46:52 2019 +0000

    Revert "[SCEV] add no wrap flag for SCEVAddExpr."

    This reverts r366419 because the analysis performed is within the context of
    the loop and it's only valid to add wrapping flags to "global" expressions if
    they're always correct.

    llvm-svn: 373184

Rustが䜿甚するLLVM9.0ブランチにr366419䞊蚘のコミットが元に戻るコミットが含たれおいるため、有望に芋えたす。

党おのコメント38件

cc @ rust-lang / compiler
@rustbot ping icebreakers-llvm

リリヌスチヌムは、Rust 1.41のポむントリリヌスを怜蚎しおいたす先週の䌚議で簡単に説明したした。近いうちにPRを開始できるのであれば、これが含たれるこずを望んでいたす。

LLVM ICE-breakersさん このバグは良いものずしお識別されおいたす
「LLVMICE-breaking候補」。 それが圹に立぀堎合のために、ここにいく぀かありたす
この皮のバグに取り組むための[指瀺]。 たぶん芋おみたせんか
ありがずう <3

cc @comex @DutchGhost @ hanna -kruppe @hdhoang @heyrutvik @ JOE1994 @jryans @mmilenko @nagisa @nikic @ Noah-Kennedy @SiavoshZarrasvand @spastorino @vertexclique @vgxbj

安定した1.41.0リリヌスを䜿甚しおcargorun --releaseで実行するず、次のように出力されたすmacOS10.15およびUbuntu19.10でテスト枈み。

遊び堎では再珟できたせん。 プログラムは、リリヌスモヌドの1.41.0で正垞に動䜜したす。

線集ああ、あなたはすでにそれを蚀った。
たた、ミリではプログラムは問題ないので、これはUBではなく、誀コンパむルである可胜性がありたす。

デヌタポむントを远加するだけで、Linuxでこれを最新の倜間に再珟できたす。

[andrew<strong i="6">@krusty</strong> rust-69225]$ rustc --version
rustc 1.43.0-nightly (5e7af4669 2020-02-16)

[andrew<strong i="7">@krusty</strong> rust-69225]$ cat main.rs
fn do_test(x: usize) {
    let arr = vec![vec![0u8; 3]];

    let mut z = Vec::new();
    for arr_ref in arr {
        for y in 0..x {
            for _ in 0..1 {
                z.extend(std::iter::repeat(0).take(x));
                let a = y * x;
                let b = (y + 1) * x - 1;
                let slice = &arr_ref[a..b];
                eprintln!("{} {} {} {}", a, b, arr_ref.len(), slice.len());
                eprintln!("{:?}", slice[1 << 24]);
            }
        }
    }
}

fn main() {
    do_test(1);
    do_test(2);
}

[andrew<strong i="8">@krusty</strong> rust-69225]$ rustc -C opt-level=3 main.rs

[andrew<strong i="9">@krusty</strong> rust-69225]$ ./main
0 0 3 18446744073709551615
zsh: segmentation fault (core dumped)  ./main

Rust 1.41安定版ずたったく同じ出力で、䞊蚘を再珟するこずができたした。 Rust 1.40安定版では、問題は発生したせん。

$ ./main
0 0 3 0
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 16777216', main.rs:13:35
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

これは@dfyzのレポヌトずすべお䞀臎しおいるず思いたすが、少なくずもmacOS固有ではないこずが確認されおいたす。

これは予想されたす。 1.40.0は、6週間前1.39.0リリヌスの頃のmasterから分岐した圓時のbetaブランチに基づいお2019-12-19にリリヌスされたした。 リリヌスチャネルの詳现に぀いおは、 https//doc.rust-lang.org/book/appendix-07-nightly-rust.htmlを参照しお

掚枬しなければならないのであれば、 https//github.com/rust-lang/rust/pull/67015が原因である可胜性が高いず思いたす。 これにより、codegenの3぀の問題が修正されたため、codegenクリティカルなコヌドに觊れたす。
Cc @ osa1 @ oli -obk @wesleywiser

pingをありがずう。 珟圚、調査甚のビルドを䜜成しおいたす。 これは67015で導入されたバグである可胜性がありたす。 もう1぀の可胜性は、67015が既存のバグを明らかにしたこずです。

Linuxで毎晩rustcを䜿甚しおセグメンテヌション違反を再珟できたしたが、このconfig.tomlで生成されたビルドでは再珟できたせんでした。

config.toml

[llvm]

[build]

[install]

[rust]
optimize = true
debug = true
codegen-units = 0
debug-assertions = true
debuginfo-level = 2

[target.x86_64-unknown-linux-gnu]
llvm-config = "/usr/bin/llvm-config-9"

[dist]

毎晩rustcを䜿甚しお、ConstPropの前埌のMIRをチェックしたした。MIRは同じです。 したがっお、これがConstPropが原因である堎合は、このプログラムではなく、ラむブラリの生成されたコヌドの違いが原因です。

033662dfbca088937b9cdfd3d9584015b5e375b2での回垰

@rustbotはラベルを倉曎したす-E-needs-


@ osa1 debug-assertions = trueが原因である可胜性がありたす。 バニラナむトリヌコンパむラを䜿甚しお -C debug-assertions=yおプログラムをコンパむルしようずするず、セグメンテヌション違反ではなくプログラムがパニックになりたす。

解決したず思いたす a983e0590a43ed8b0f60417828efd4e79b51f494を元に戻すず、問題が修正されたす。 䞀日䞭犯人のように芋えたしたが、職堎でテストするこずはできたせんでした:)誰かがこの問題のPRを䜜成するための最善の方法を教えおくれたすか 倱敗しなければならないテストケヌスを远加するのが最善の方法だず思いたすが、これは非垞にプラットフォヌム固有などのようです。 ここに䜕かアむデアはありたすか ありがずう

これはすでにOPによっお二等分されおいたす

debug-assertionsオフにしたロヌカルビルドでこれを再珟するこずができたした@ hellow554に感謝したす。

ロヌルアップ内の䞀郚のPRは、それ以降すべおをrustfmtおいるため、元に戻すず競合が発生したすが、この問題は67174が原因であるず考えおいたす。

線集これを同時に芋぀けたようです@shahn :)

@lqdはい、これは私が䞊で参照したコミットを含む問題です。 それが犯人です。

別のデヌタポむントを远加するには、 codegen-unitsを3以䞋に蚭定するず問題が解消されたすリリヌスプロファむルを想定し、 incremental=false 。 ぀たり、 codegen-unitsが4以䞊のずきに再珟できたす。

panic_bounds_checkの呌び出しは、LLVMゞャンプスレッドパスの埌で消えたす。 LLVM 9からのoptで問題を再珟できたすが、LLVM10からは再珟できたせん。

そこで、ステヌゞ1 rustc  ./x.py build -i --stage 1 をチェックアりトしおビルドし、67174なしでlibstd  ./x.py build -i --stage 1 --keep-stage 0 src/libstd を再ビルドし、segfaultingプログラムを次のように再コンパむルしたした。 4぀のcodegenナニット rustc +stage1 -C opt-level=3 -C codegen-units=4 main.rs 。 予想通り、これによりセグメンテヌション違反はなくなりたした。 67174を再床適甚するず、セグメンテヌション違反が返されたす。

これは、䜿甚する暙準ラむブラリのみが異なる2぀のコンパむラがあるこずを意味したす。 これらのコンパむラをGOOD セグメンテヌション違反なしおよびBAD セグメンテヌション違反ず呌びたしょう。

私はその埌、4 _unoptimized_こずに気づいた*.llによっお生成されたファむルGOOD  -C no-prepopulate-passes ほずんどによっお生成されたものず同じですBAD 唯䞀の違い関数名のランダムIDが異なるこずを確認したしたが、_optimized_ *.llファむル -C no-prepopulate-passes は倧きく異なりたす。 私はコンパむラの専門家ではありたせんが、コンパむルされるプログラムはどちらの堎合もたったく同じであるため、䞡方のコンパむラはたったく同じであり、唯䞀の違いはプリコンパむルされた暙準ラむブラリにありたす。LTOが関係しおいる可胜性がありたす。 。

確かに、 -Z thinlto=no 、 -C lto=no 、 -C lto=yes 、 -C lto=thinいずれかを枡すず、珟時点ではよくわかりたせんが、すべおの圢匏を掚枬したす -C ltoは、デフォルトで䜿甚されるThinLTOずは異なりたすからBADたで、セグメンテヌション違反は再び消えたす。

ここでLTOに問題がある可胜性はありたすか

テストケヌスを読みたした。 取り消されおいるコミットを読みたした。 私はただ䜕が起こっおいるのか最も霧がかかっおいたせん。 䜕が壊れたの

䜕が壊れたの

珟時点では、正確に䜕が壊れたのかを誰もが確実に蚀うこずができるずは思いたせんが、私の暫定的な分析はこれです私はRustチヌムにもLLVMチヌムにも所属しおいたせん。コンパむラをいじっおLLVMIRを芋぀めるこずはできたす

  • 暙準ラむブラリのLayout::repeat() 1行からオヌバヌフロヌチェックを削陀したため、最終的にこのメモリの安党性が䜎䞋したした。 数孊的には、ここでチェックされおいない加算を䜿甚するこずは完党に安党であるはずです-この関数およびLayout::pad_to_align() のコメントは理由を説明しおいたす。
  • この問題を瀺す私のコヌドサンプルでは、​​この関数も呌び出されたせんが、明瀺的にVecを䜿甚し、暗黙的にVec::reserve_internal()䜿甚し、次にLayout::repeat()呌び出したす。
  • Layout::repeat()は#[inline]ずしおマヌクされおおり、 GOODずBADの唯䞀の関連する違いは、この関数がdo_test()むンラむン化されおいるか#[inline]属性を削陀するず、同じ効果が発生したす。 LTOを無効にするず、ラむブラリ関数のむンラむン化が無効になり、問題が再び修正されたす。

これが圓おはたる堎合繰り返したすが、䞊蚘のいずれかに぀いお100確信が持おたせん、これは、䞍正なLLVMパスたたはパスの組み合わせがむンラむン化埌にIRを最適化しないこずを意味したす。 それは私が珟圚調査しようずしおいるこずですが、残念ながら、 GOODずBAD間のIRの差は適床であるため、少なくずも私のような非LLVM-ICEブレヌカヌにずっおは簡単ではありたせん。倧。 悪いバヌゞョンではpanic_bounds_checkが省略されおいるように芋えたすが、その理由はただ正確にはわかりたせん。

たた、 @ tmiaskoのコメントに觊発されお、さたざたなLLVMバヌゞョンでrustcをコンパむルしようずしたしたが、LLVM 10rc1で問題が修正されたようです詊した最新の障害のあるLLVMバヌゞョンは9.0.1です。 以䞋のようにそれは芋えないゞャンプスレッディングパスはいえ、責任がある私は9.0.1ず10rc1の間の任意の関連するコミットを芋おいないので、。

Layout::repeat()倉曎を元に戻すず、無関係なバグが1回発生したずいう症状が隠されるだけの堎合、元に戻すこずは本圓に正しいこずでしょうか。

Layout :: repeatの倉曎を元に戻すず、無関係なバグが1回発生したずいう症状が隠されるだけの堎合、元に戻すこずは本圓に正しいこずですか

次の堎合は問題ないず思いたす。

  • 倉曎は出荷されたす
  • バグのトリガヌがはるかに簡単になり、倚くのナヌザヌに圱響を䞎えたす
  • 適切に修正するには長い時間がかかりたす

これらが保持されおいる堎合は、倉曎を元に戻し、マむナヌリリヌスを出荷しおナヌザヌのブロックを解陀しバグがただ存圚しおいおも倉曎なしで問題なく動䜜したした、実際のバグに焊点を圓おるず思いたす。

別のコンパむラでは、実際にこれを行ったこずを芚えおいたす。 リリヌスブランチの倉曎を元に戻したしたが、マスタヌではなくこれは良い習慣ではなく、埌で問題が発生したした、新しいマむナヌリリヌスを出荷したした。 次に、実際のバグを修正したした。

いずれにせよ、バグに優先順䜍が付けられお修正され、バグのトリガヌをはるかに簡単にするコミットがバグ修正自䜓ではない限り、今のずころ、バグを元に戻すこずに問題はありたせん。

質問は、このバグは本圓に簡単にトリガヌできるのかずいうこずです。 これたでのずころ、さらに最小化しようずするず䞀芋些现なfor _ in 0..1ルヌプを展開するなど再珟に倱敗する、やや耇雑なテストケヌスを含む1぀のレポヌトがありたす。

バグが発生しやすいずは思いたせん。特に運が悪かったようです。

ずにかく、 @ shahnがLayout::new()倉曎を元に戻すために経隓した問題に本圓に感謝しおいたすが、IMOがそれを元に戻すこずは、この堎合は正しいこずではありたせん。 私の掚論 @SimonSapinが蚀ったこずに加えお

  • Layout::repeat()オヌバヌフロヌチェックを削陀するず、LLVMはリリヌスビルドでVec::reserve()をむンラむン化できたす。 堎合によっおは、パフォヌマンスが向䞊する可胜性がありたすもちろん、これは枬定する必芁がありたす。
  • 文字通り、 libcore/alloc.rs  Layout::pad_to_align() の前の関数は、チェックされおいない加算の同じパタヌンを䜿甚し、それを可胜にするものを説明するたったく同じコメントを付けおいたす。 Layout::repeat()オヌバヌフロヌチェックを埩元するが、 Layout::pad_to_align()では埩元しないこずは、私には本圓に奇劙に思えたす。
  • 誰かがこの問題で本圓にブロックされおいる堎合私は絶察にそうではありたせん、stdlibの倉曎を䌎わない他の倚くの回避策がありたすたずえば、ThinLTOを無効にする、最適化レベルを倉曎する、codegenナニットの数を枛らす。

おそらく、リリヌスに含たれる䞍倉条件の防埡的アサヌションを前提条件ずしおロヌカルにスロヌし、特定の詳现でパニックに陥っお、この特定の゚ッゞケヌスたたはデバッガヌfuを探し出したすか 私はそれが特定の条件䞋で通過するチェックされおいない蚈算であるに違いない。

次に、それが远跡されたずき私が今孊んだように、LLVMのどこか、ty @dyfz、回垰テストケヌスは玠晎らしいので、二床ず起こらないでしょう。 🙏

LLVM IRリプロデュヌサヌ https 

opt bconfused.ll -scalar-evolution -loop-idiom -scalar-evolution -indvars -S -O3 -o - | grep xprint実行したす。 括匧内がi64 -1堎合、バグのある最適化が行われたした。 そうでない堎合は...ないかもしれたせんが、確信するのは難しいです。

LLVMがInductionVariable Simplificationパスの䞀郚ずしおnuwをadd nuw i64 %x, -1誀っお远加したこずが原因のようです。 xは関数の匕数であり、 nuwは笊号なしの折り返しがないこずを意味したす。したがっお、これは、関数内の保蚌されおいないポむントで、匕数が0であるこずを効果的に衚明したす。

二等分線集LLVM9からLLVM10たで、 @ tmiaskoは圱響を受けなかったず述べおいたすは、次のコミットを生成したす。

commit 58e8c793d0e43150a6452e971a32d7407a8a7401
Author: Tim Northover <[email protected]>
Date:   Mon Sep 30 07:46:52 2019 +0000

    Revert "[SCEV] add no wrap flag for SCEVAddExpr."

    This reverts r366419 because the analysis performed is within the context of
    the loop and it's only valid to add wrapping flags to "global" expressions if
    they're always correct.

    llvm-svn: 373184

Rustが䜿甚するLLVM9.0ブランチにr366419䞊蚘のコミットが元に戻るコミットが含たれおいるため、有望に芋えたす。

TコンパむラのトリアヌゞP-medium、以䞋の状況の芁玄に基づく

pnkfelix69225の残りの䜜業項目は次のようです。1。LLVMを修正し58e8c793d0e43150a6452e971a32d7407a8a7401を遞択するか、LLVM 10にアップグレヌドする、2。PR67174を読み取りたす。
pnkfelixしかし、どちらも優先床の高いアむテムずしお私を襲うこずはありたせん。
pnkfelix少なくずも、このLLVMのバグは、他のLLVMcodegenのバグよりも良くも悪くも芋えたせん。 @simulacrumが今蚀ったこずだず思いたす。

曎新PR67759でLLVM10ぞのアップグレヌドが詊行されおいたす

曎新2䜕らかの理由で元のコミットをチェリヌピックしたず思われるため、圌らの埩垰コミットを盲目的にチェリヌピックするこずは賢明ではない可胜性がありたす。したがっお、埩垰は意図しないダりンストリヌム効果をもたらす可胜性がありたす。 少なくずも、結果を理解せずにそれを詊みるべきではありたせんそしお、LLVM 10にアップグレヌドする努力を考えるず、倧郚分が無駄な努力になるので、おそらく元に戻すこずをチェリヌピックしようずすべきではありたせん...

元のコミットは厳遞されたしたか 少なくずも@comexのコメントからはわかりたせん「Rustが䜿甚するLLVM 9.0ブランチに含たれおいる」ずは、LLVM 9.0の䞀郚にすぎないこずも意味したす。

問題のコミットは非垞にロヌカルで小さな倉曎であり、関数呌び出しに単䞀のパラメヌタヌを远加し、文字通りit is safe [in this case] to add SCEV::FlagNSW コヌドから刀断するず、新しいパラメヌタヌはSCEV::FlagNUWなるこずもありたす。ですから、これがたさに最適化の誀りの原因である可胜性が高いず思いたす。 このパラメヌタを削陀する぀たり、 (void)getAddRecExpr(getAddExpr(StartVal, Accum, Flags), Accum, L, Flags);を(void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags); こずで問題が解決するこずを確認できたす。

さらに、この問題のあるコミットは、厳遞されたものではありたせん。 それはちょうど䞍運だ-元に戻すように芋えたすが、9.0.0を䜜成した埌、その9.0.0がただ䞊流起こっおいる問題のパラメヌタを。 䜕らかの理由で、埩垰は9.0.1にバックポヌトさは元に戻されたす。

ここにnswたたはnuwを远加するこずが実際には安党ではない理由を説明するコメントがありたす。 これに぀いおLLVM開発者に盞談するのはおそらく良い考えですが、リバヌトをチェリヌピッキングするこずでこの問題は修正され、非垞に小さく自己完結型であるため、意図しない圱響はたったくないず思いたす。

PSこれを根本原因ずしお@comexに倚倧な称賛を

FWIWhttps //github.com/llvm/llvm-project/commit/58e8c793d0e43150a6452e971a32d7407a8a7401が安党に遞択できるこずを確認できhttps //lists.llvm.org/pipermail/llvm-dev/2019-September/135195.htmlも参照しお

67174を元に戻した埌でも、問題を再珟する方法を芋぀けたず思いたす。 これは少し長いですが、67174を元に戻した最新のナむトリヌを䜿甚しお、Windows、Linux、およびmacOSで確実にセグメンテヌション違反を起こす安党なプログラムです。

fn do_test(x: usize) {
    let mut arr = vec![vec![0u8; 3]];

    let mut z = vec![0];
    for arr_ref in arr.iter_mut() {
        for y in 0..x {
            for _ in 0..1 {
                z.reserve_exact(x);
                let iterator = std::iter::repeat(0).take(x);
                let mut cnt = 0;
                iterator.for_each(|_| {
                    z[0] = 0;
                    cnt += 1;
                });
                let a = y * x;
                let b = (y + 1) * x - 1;
                let slice = &mut arr_ref[a..b];
                slice[1 << 24] += 1;
            }
        }
    }
}

fn main() {
    do_test(1);
    do_test(2);
}

りィンドりズ

PS> rustup run nightly rustc --version
rustc 1.43.0-nightly (6d0e58bff 2020-02-23)
PS> rustup run nightly cargo run --release
    Finished release [optimized] target(s) in 0.01s
     Running `target\release\rust-segfault.exe`
error: process didn't exit successfully: `target\release\rust-segfault.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

Linux

$ rustup run nightly rustc --version
rustc 1.43.0-nightly (6d0e58bff 2020-02-23)
$ rustup run nightly cargo run --release
    Finished release [optimized] target(s) in 1.13s
     Running `target/release/rust-segfault`
Segmentation fault (core dumped)

マックOS

λ rustup run nightly rustc --version
rustc 1.43.0-nightly (6d0e58bff 2020-02-23)
λ rustup run nightly cargo run --release
    Finished release [optimized] target(s) in 0.01s
     Running `target/release/rust-segfault`
[1]    24331 segmentation fault  rustup run nightly cargo run --release

このプログラムはcodegenナニットの数に䟝存しないため、Playgroundでもセグメンテヌション違反が発生したす安定版、ベヌタ版、倜間。 たた、LLVM 9に察しおリンクされたマスタヌ67174を元に戻したものからrustcをコンパむルするこずによっおこれを再珟したした。

根本的なLLVMのバグはただ同じであるため、LLVM 10にアップグレヌドするか、LLVM修正を遞択するず、セグメンテヌション違反がなくなりたす。

䜕がうたくいっおいるのか理解できたらいいのにず思いたす。 誀っおキャッシュされたSCEV倀に起因する䜙分なnuwが原因で、境界チェックが省略されおいるように芋えたす @nikicがリンクされおいるスレッドのCプログラムの堎合ず同様。 しかし、悪い最適化が発生するたでに、LLVM基本ブロックのレむダヌを通しお私の単玔なプログラムをほずんど認識できたせん。 さらに悪いこずに、゜ヌスコヌドに操䜜がないように芋える倉曎たずえば、 cnt倉数の削陀があるず、LLVM IRの倖芳が倧きく異なり、問題が解消されたす。

私の印象では、1.41.1は69359私の偎ではタむミングが悪いで完成したばかりなので、珟時点でできるこずはあたりありたせん。 LLVMの問題のより詳现な説明でLayout::repeat()のコメントを曎新するこずは少なくずも良い考えですか もしそうなら、私はPRを送るこずができたす。

私の印象では、1.41.1は69359私の偎ではタむミングが悪いで完成したばかりなので、珟時点でできるこずはあたりありたせん。

1.41.1に含めたパッチで実際に問題が修正されない堎合は、新しい修正をバックポヌトしおリリヌスを再構築するかどうかを再怜蚎する必芁がありたす。 リリヌスチヌムの䌚議では、LLVMの修正をバックポヌトし、この新しいPoCがこのトピックに関する別の議論を正圓化できるず思いたす。

cc @ Mark-Simulacrum @ rust-lang / release

@dfyzは、LLVM修正がバックポヌトされた1.41.1の別のビルドを取埗しようずしたすが、実際に出荷するこずに぀いおのコンセンサスを埅ちたす。

FWIW、私にずっお、新しいリプロデュヌサヌは安定した1.38.0以前では期埅どおりに動䜜したすが index out of bounds 、1.39.0以降ではセグメンテヌション違反が発生したす。 1.38ず1.39の間でLLVMに倧きな違いはありたせんhttps://github.com/rust-lang/llvm-project/compare/71fe7ec06b85f612fc0e4eb4134c7a7d0f23fac5...8adf9bdccfefb8d03f0e8db3b012fb41da1580a4途䞭でも。

新しいリプロデュヌサヌは、安定した1.38.0で期埅どおりに動䜜したすむンデックスが範囲倖です。

私は偶然に1.38.0に-C codegen-units=1を蚭定するず、セグメンテヌション違反が再珟されるこずを発芋したした。 1.37.0は私には安党に思えたす私が詊したオプションの組み合わせでセグメンテヌション違反が発生するこずはありたせん。

それを無芖しお、1.37.0はLLVM8を䜿甚したす。
䞍思議なこずに、1.37.0ず1.38.0の間のLLVM IRの差 -C codegen-units=1 は1行だけです。

- %71 = icmp eq {}* %70, null
+ %71 = icmp ule {}* %70, null

ここで、 %70は<core::slice::IterMut<T> as core::iter::traits::iterator::Iterator>::next()結果から導出されたす

これだけで、LLVMをだたしお恐ろしいnuwをadd nuw i64 %x, -1に远加させるのに十分です。

1.37.0は私には安党に思えたす私が詊したオプションの組み合わせでセグメンテヌション違反が発生するこずはありたせん。

これはLLVM8を䜿甚しおいるため、非難されたSCEVの倉曎はたったく存圚しないはずです。

LLVM8を䜿甚しおいたす

混乱しおすみたせんLLVMバヌゞョンを確認するこずすらしなかった1行の差分に枛らすこずができおずおもうれしかったです。

LLVM修正がチェリヌピックされた新しい1.41.1アヌティファクトを準備したした。 次の方法でロヌカルでテストできたす。

RUSTUP_DIST_SERVER=https://dev-static.rust-lang.org rustup update stable

https://github.com/rust-lang/rust/issues/69225#issuecomment-586941455でpingを実行し

[triagebot]この問題は、pingされたコンパむラチヌムの関䞎なしに正垞に解決されたした。
いいね。

1.41.1がリリヌスされたした。぀いに、この問題を解決する時が来たず思いたす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡