Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Modular Termination Verification on VeriFast

eldesh
January 25, 2018

Modular Termination Verification on VeriFast

[静的コード解析の会#6](https://metasepi.connpass.com/event/67805/) で発表した資料です。

前回の発表(https://speakerdeck.com/eldesh/verifast-termination-checking-introduction-a) に続いて、
VeriFastによるC(およびJava)言語の停止性検査について説明しています。

停止性検査を行う背景、基本となる数学的な方針、VeriFastによる検査のアイディア、パターン毎の証明テクニックについて解説しています。
各分類パターンについては具体的なコード(片)に沿って解説しています。

参照:
Modular termination verification
Bart Jacobs, Dragan Bosnacki, and Ruurd Kuiper. At ECOOP 2015.

eldesh

January 25, 2018
Tweet

More Decks by eldesh

Other Decks in Programming

Transcript

  1. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Modular Termination Verification on VeriFast @eldesh https://twitter.com/eldesh http://d.hatena.ne.jp/eldesh ੩తίʔυղੳͷձ ୈ 6 ճ 2018/01/20 2018/01/20 VeriFast Termination Checking 1 / 74
  2. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ໨࣍ 1 VeriFast ֓ཁ 2 ఀࢭੑݕࠪͱ͸Կ͔ 3 VeriFast ʹΑΔఀࢭੑݕࠪ 4 fixpoint ͷఀࢭੑ 5 C ݴޠؔ਺ͷఀࢭੑݕࠪ ଟॏू߹ͱ DW-Ordering 6 ύλʔϯผఀࢭੑݕূ Upcalls Only ύλʔϯ Static Recursion ύλʔϯ Dynamic Binding ύλʔϯ 7 ࢀর 2018/01/20 VeriFast Termination Checking 2 / 74
  3. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ What is this slide? ͜ͷεϥΠυͰ͸ VeriFast ʹΑΔ C ݴޠ͓Αͼ Java ϓϩάϥϜͷఀࢭੑݕ ূͷجૅͱͳΔ֓೦ɺ͓ΑͼͦΕΛ༻͍ͨݕূํ਑ɺ࣮ࡍͷॲཧܥͰͷѻ ͍ʹ͍ͭͯઆ໌͠·͢ɻ جૅͱͳΔ֓೦ ఀࢭੑূ໌ͷํ਑ ࣮ࡍͷॲཧܥ্Ͱͷѻ͍ 2018/01/20 VeriFast Termination Checking 3 / 74
  4. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ૝ఆ/ର৅ௌऺ ඞਢ C ݴޠ͕෼͔Δ ๬·͍͠ ࣄલ/ࣄޙ৚݅ͷݕ͕ࠪͲΜͳ΋ͷͳͷ͔෼͔Δ 2018/01/20 VeriFast Termination Checking 4 / 74
  5. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ VeriFast ͷೖ໳తΛઆ໌͢Δ 2018/01/20 VeriFast Termination Checking 5 / 74
  6. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ఀࢭੑݕࠪͱ͸ ϓϩάϥϜ͕ (༗ݶ࣌ؒ಺ʹ) ఀࢭ͢Δ͜ͱΛݕࠪ͢Δ͜ͱɻ 2018/01/20 VeriFast Termination Checking 6 / 74
  7. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ VeriFast ͕ݕࠪ͢Δ͜ͱ ͱ͜ΖͰɺVeriFast ͸ϓϩάϥϜ (ؔ਺) ͱɺͦͷࣄલ৚݅/ࣄޙ৚݅ͱͷҰ ؏ੑΛݕࠪ͢Δɻ 2018/01/20 VeriFast Termination Checking 7 / 74
  8. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ VeriFast ͕ݕࠪ͢Δ͜ͱ ͱ͜ΖͰɺVeriFast ͸ϓϩάϥϜ (ؔ਺) ͱɺͦͷࣄલ৚݅/ࣄޙ৚݅ͱͷҰ ؏ੑΛݕࠪ͢Δɻ ⇒ ͜Ε͸Կ͕ݕূग़དྷ͍ͯΔͷ͔ɻ 2018/01/20 VeriFast Termination Checking 7 / 74
  9. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ VeriFast Ͱݕࠪͨؔ͠਺ ΤϯΩϡʔͷ࢓༷ͷྫ void enqueue(struct queue *q, int x) //@ requires queue(q, ?vs); //@ ensures queue(q, iappend(vs , icons(x, inil ))); { ... } 2018/01/20 VeriFast Termination Checking 8 / 74
  10. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Hoare triple ؔ਺ͱɺͦͷࣄલ৚݅/ࣄޙ৚݅ 3 ͭΛ߹Θͤͯ Hoare triple ͱݺͿɻ ͜ΕΛܗࣜతʹѻ͏ࡍʹ͸ҎԼͷΑ͏ʹදه͢Δɻ Hoare triple ⊢ {P} c {Q} 2018/01/20 VeriFast Termination Checking 9 / 74
  11. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Hoare triple ͷҙຯ ؔ਺ͱɺͦͷࣄલ৚݅/ࣄޙ৚݅ 3 ͭΛ߹Θͤͯ Hoare triple ͱݺͿɻ Hoare triple ͷҙຯ ⊢ {P} c {Q} ⇔ ∀h, γ.Ifix , h |= P ∧ (h, c) ⇓ γ ⇒ γ |= Q γ |= Q ͷҙຯ Divergence |= Q Ifix , h |= Q[v/res] (n, v, h) |= Q Divergence ͸ൃࢄͨ͠ঢ়ଶ (ແݶϧʔϓ) Λද͢ɻ 2018/01/20 VeriFast Termination Checking 10 / 74
  12. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Hoare triple ͷҙຯ Divergence |= Q ͱ͍͏͜ͱ͸ɺແݶϧʔϓʹͳͬͨ৔߹͸ৗʹ Q ࣄޙ৚ ͕݅੒Γཱͭͱݴ͍ͬͯΔɻ 2018/01/20 VeriFast Termination Checking 11 / 74
  13. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Hoare triple ͷҙຯ Divergence |= Q ͱ͍͏͜ͱ͸ɺແݶϧʔϓʹͳͬͨ৔߹͸ৗʹ Q ࣄޙ৚ ͕݅੒Γཱͭͱݴ͍ͬͯΔɻ ⇒VerifFast ͸ແݶϧʔϓʹͳΔ͔Ͳ͏͔͸ݕূ͠ͳ͍ 2018/01/20 VeriFast Termination Checking 11 / 74
  14. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Hoare triple ͷҙຯ VeriFast ͸෦෼ਖ਼౰ੑ (partial correctness) Λ࣋ͭɻ ෦෼ਖ਼౰ੑ ϓϩάϥϜͷ࣮ߦ݁Ռ͕ग़ͨ (=ਖ਼͘͠ऴྃͨ͠) ৔߹ʹ ͦͷਖ਼͠͞Λอূ͢Δ ⇕ Partial Correctness ͜Εʹରͯ͠ɺৗʹϓϩάϥϜ͕ਖ਼͍݁͠ՌΛग़ྗ͢Δ৔߹ɺ͜ΕΛ׬શ ਖ਼౰ੑ (Total Correctness) Λ࣋ͭ ͱ͍͏ɻ 2018/01/20 VeriFast Termination Checking 12 / 74
  15. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ఀࢭੑݕࠪͱ͸ (࠶) ࠶ ϓϩάϥϜ͕ (༗ݶ࣌ؒ಺ʹ) ఀࢭ͢Δ͜ͱΛݕࠪ͢Δ͜ͱɻ ͱ͍͏͜ͱ͸. . . (෦෼ਖ਼౰ੑʹՃ͑ͯ) ఀࢭੑΛݕূ͢Δ ⇕ VeriFast ʹ׬શਖ਼౰ੑΛ༩͑Δ ⇕ ϓϩάϥϜ͕ৗʹਖ਼͍͠౴͑Λฦ͢͜ͱΛอূͰ͖Δ 2018/01/20 VeriFast Termination Checking 13 / 74
  16. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ఀࢭੑݕࠪͷࢦఆ ؔ਺ͷఀࢭੑΛݕࠪ͢Δʹ͸௨ৗͷࣄલ, ࣄޙ৚݅ͷଞʹ terminates Λࢦ ఆ͢Δ. Կ΋͠ͳ͍ؔ਺ͷݕূ void empty_cmd (void) //@ requires emp; //@ ensures emp; //@ terminates; { } 2018/01/20 VeriFast Termination Checking 14 / 74
  17. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ࣗ໌ʹఀࢭ͢Δྫ 1 ϓϦϛςΟϒͳԋࢉ͸ࣗ໌ʹఀࢭ͢Δɻ less than ͷ࢓༷ bool compare (int x, int y) //@ requires emp; //@ ensures result == (x < y); //@ terminates; { return x < y; // ฦΓ஋͸େখൺֱͷ݁ՌʹҰக͢Δ } 2018/01/20 VeriFast Termination Checking 15 / 74
  18. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ࣗ໌ʹఀࢭ͢Δྫ 2 if จ͸ɺͦΕͧΕͷઅ͕ఀࢭ͢ΔͳΒࣗ໌ʹఀࢭ͢Δɻ if statement int max_int (int x, int y) //@ requires emp; //@ ensures result == (x > y ? x : y); //@ terminates; { if (x > y) { return x; } else { return y; } } 2018/01/20 VeriFast Termination Checking 16 / 74
  19. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ࣗ໌ʹఀࢭ͢Δྫ 3 ఀࢭ͢Δؔ਺ΛݺͿؔ਺͕ɺͦͷؔ਺ΑΓϑΝΠϧதͰԼͰఆٛ͞Ε͍ͯ Δ৔߹΋ఀࢭ͢Δ͜ͱ͕ࣗಈͰݕࠪͰ͖Δɻ call function int callee (int x) //@ requires emp; //@ ensures emp; //@ terminates; { return 0; } void caller (void) //@ requires emp; //@ ensures emp; //@ terminates; { callee (3); } 2018/01/20 VeriFast Termination Checking 17 / 74
  20. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ϧʔϓ ݕূʹৗʹඞཁͱͳΔϧʔϓΠϯόϦΞϯτʹՃ͑ͯɺdecreases ໋ྩͰݮ গ͢ΔύϥϝʔλΛࢦఆ͢Δ͜ͱͰఀࢭੑΛݕࠪ͢Δ͜ͱ͕Ͱ͖Δɻ while loop void loop (int x) //@ requires 0 < x; //@ ensures emp; //@ terminates; { int i = 0; while (i < x) //@ invariant i <= x; //@ decreases x - i; { ++i; } } 2018/01/20 VeriFast Termination Checking 18 / 74
  21. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ࣗ໌Ͱ͸ͳ͍ఀࢭ͢Δྫ ΞοΧʔϚϯؔ਺ int ackermann(int m, int n) { if (m == 0) { return n + 1; } else { if (n == 0) { int r = ackermann(m - 1, 1); return r; } else { return ackermann(m - 1, ackermann(m, n - 1)); } } } ఀࢭੑΛݕূͨ͠ίʔυ͸ examples/termination/ackermann.c Λࢀরɻ72 ߦ͋Δɻ 2018/01/20 VeriFast Termination Checking 19 / 74
  22. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ جຊతͳൃ૝ શͯͷݺͼग़͠γʔέϯε͕༗ݶεςοϓ௕͔͠ͳ͍͜ͱΛࣔͤ͹ྑ͍ɻ ⇒ Ͳ͏͢Δ͔ 2018/01/20 VeriFast Termination Checking 20 / 74
  23. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ fixpoint ͱ͜ΖͰ VeriFast ͸໋୊தͷؔ਺Λ fixpoint ͱ͍͏ΩʔϫʔυͰهड़͢Δ ͜ͱ͕ग़དྷΔɻ fixpoint ؔ਺ͷྫ fixpoint int length <t>(list <t> xs) { switch (xs) { case nil: return 0; case cons(x, xs0): return 1 + length(xs0); } } 2018/01/20 VeriFast Termination Checking 21 / 74
  24. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ fixpoint fixpoint ͸ඞͣఀࢭ͢Δɻ fixpoint ؔ਺ͷྫ fixpoint int length <t>(list <t> xs) { switch (xs) { case nil: return 0; case cons(x, xs0): return 1 + length(xs0); } } 2018/01/20 VeriFast Termination Checking 21 / 74
  25. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ fixpoint fixpoint ͸ͳͥඞͣఀࢭ͢Δͷ͔ fixpoint ؔ਺ͷྫ fixpoint int length <t>(list <t> xs) { switch (xs) { case nil: return 0; case cons(x, xs0): return 1 + length(xs0); } } 2018/01/20 VeriFast Termination Checking 21 / 74
  26. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ fixpoint ͷ੍ݶ fixpoint ʹΑΔؔ਺ͷఆٛʹ͸ɺ೚ҙͷؔ਺͕هड़Ͱ͖ΔΘ͚Ͱ͸ͳ͘ز ੍͔ͭ໿͕൐͏ 1ɻ fixpoint ͷ੍ݶ ୯ಠͷ return ·ͨ͸ switch จͰ͋Δ͜ͱ switch ʹ౉ͤΔͷ͸ inductive σʔλͷΈ શͯͷίϯετϥΫλʹ͍ͭͯఆٛ͞Ε͍ͯΔ͜ͱ ࠶ؼ͢Δ৔߹͸ύλʔϯϚονͰऔΓग़ͨ͠σʔλʹ͍ͭͯࣗ਎Λݺ ΜͰ͍Δ͜ͱ Ҏ্ͷΑ͏ͳ੍ݶΛकΔ͜ͱͰɺ஋ʹґͬͯ͸ະఆٛ͋Δ͍͸ݕ͕ࠪࢭ· Βͳ͘ͳΔΑ͏ͳ (͓͔͠ͳ) ࢓༷Λආ͚Δ͜ͱ͕Ͱ͖Δɻ 1ͦΕͧΕ VeriFast ͕ݕࠪ͢Δ 2018/01/20 VeriFast Termination Checking 22 / 74
  27. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ fixpoint ͷ੍ݶ fixpoint ʹΑΔؔ਺ͷఆٛʹ͸ɺ೚ҙͷؔ਺͕هड़Ͱ͖ΔΘ͚Ͱ͸ͳ͘ز ੍͔ͭ໿͕൐͏ 1ɻ fixpoint ͷ੍ݶ ୯ಠͷ return ·ͨ͸ switch จͰ͋Δ͜ͱ switch ʹ౉ͤΔͷ͸ inductive σʔλͷΈ શͯͷίϯετϥΫλʹ͍ͭͯఆٛ͞Ε͍ͯΔ͜ͱ ࠶ؼ͢Δ৔߹͸ύλʔϯϚονͰऔΓग़ͨ͠σʔλʹ͍ͭͯࣗ਎Λݺ ΜͰ͍Δ͜ͱ Ҏ্ͷΑ͏ͳ੍ݶΛकΔ͜ͱͰɺ஋ʹґͬͯ͸ະఆٛ͋Δ͍͸ݕ͕ࠪࢭ· Βͳ͘ͳΔΑ͏ͳ (͓͔͠ͳ) ࢓༷Λආ͚Δ͜ͱ͕Ͱ͖Δɻ ⇒fixpoint ؔ਺͸ඞͣఀࢭ͢Δ 1ͦΕͧΕ VeriFast ͕ݕࠪ͢Δ 2018/01/20 VeriFast Termination Checking 22 / 74
  28. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ fixpoint Ͱ͏·͍͘͘ཧ༝ fixpoint ͕ఀࢭ͢Δॏཁͳཧ༝͸ɺ inductive σʔλ্ͷ࠶ؼͰ͋Δ ࠶ؼݺͼग़͠ຖʹίϯετϥΫλ͕Ұͭͣͭണ͕Ε͍ͯ͘ 2 2Inductive σʔλͱ͍͏ͷ͸ɺجఈͷσʔλʹίϯετϥΫλΛ༗ݶճద༻ͯ͠ಘΒΕΔ σʔλͷ͜ͱ 2018/01/20 VeriFast Termination Checking 23 / 74
  29. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ inductive ΑΓෳࡶͳ΋ͷ fixpoint ͸ inductive σʔλ্ͷؔ਺ͩͬͨɻͰ͸ C ݴޠͰѻ͏σʔλߏ ଄Ͱ͸Ͳ͏ͩΖ͏ʁ 2018/01/20 VeriFast Termination Checking 24 / 74
  30. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ inductive ΑΓෳࡶͳ΋ͷ ॥؀͢Δσʔλߏ଄ typedef struct C { int x; struct C * t; } C; void consumer (C * c) { ... consumer(c->t); } void producer (void) { C * ones = malloc(sizeof(C)); ones ->x = 1; ones ->t = ones; consumer(ones ); } 2018/01/20 VeriFast Termination Checking 25 / 74
  31. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ inductive ΑΓෳࡶͳ΋ͷ ྫ͑͹॥؀͢Δσʔλߏ଄্ͷؔ਺ͷ৔߹ɺ༩͑ΒΕͨσʔλͷҰ෦ʹͭ ͍ͯ࠶ؼݺͼग़͠ 3 ͍ͯͯ͠΋ؔ਺͕ఀࢭ͢Δͱ͸ݴ͑ͳ͍ɻ ॥؀͢Δσʔλߏ଄ void consumer (C * c) { ... consumer(c->t); } void producer (void) { C * ones = malloc(sizeof(C)); ones ->x = 1; ones ->t = ones; consumer(ones ); } 3fixpoint Ͱݕࠪ͢Δ಺༰ʹ૬౰͢Δ৚݅ 2018/01/20 VeriFast Termination Checking 26 / 74
  32. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ C ݴޠͰ͏·͍͔͘ͳ͍ཧ༝ C ݴޠͰ͸ఀࢭੑݕূ͸؆୯Ͱ͸ͳ͍ɻ C ݴޠͰѻ͏σʔλ͸ inductive ͱ͸ݶΒͳ͍ ෼͔Γ΍͘͢σʔλߏ଄͕খ͘͞ͳΒͳ͍ ॥؀σʔλߏ଄ ڞ༗͞ΕͨมߋՄೳͳߏ଄ 2018/01/20 VeriFast Termination Checking 27 / 74
  33. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ C ݴޠͰ͏·͍͔͘ͳ͍ཧ༝ C ݴޠͰ͸ఀࢭੑݕূ͸؆୯Ͱ͸ͳ͍ɻ C ݴޠͰѻ͏σʔλ͸ inductive ͱ͸ݶΒͳ͍ ෼͔Γ΍͘͢σʔλߏ଄͕খ͘͞ͳΒͳ͍ ॥؀σʔλߏ଄ ڞ༗͞ΕͨมߋՄೳͳߏ଄ inductive ͳσʔλΑΓҰൠతͳσʔλΛѻ͍͍ͨ 2018/01/20 VeriFast Termination Checking 27 / 74
  34. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ੔ૅؔ܎ inductive σʔλ (ͷίϯετϥΫλ਺ͷେখؔ܎) ͷҰൠԽͱͯ͠੔ૅؔ ܎Λߟ͑Δɻ ͋Δू߹্ͷೋ߲ؔ܎ R ͕੔ૅؔ܎ Well-Founded Relation Ͱ͋Δͱ͸ ੔ૅؔ܎ ∀S ⊆ X, S ̸= ∅ → ∃m ∈ S, ∀s ∈ S, (s, m) / ∈ R ੔ૅؔ܎ ू߹ X ্ͷೋ߲ؔ܎ R ͕ɺۭͰͳ͍ू߹ S ⊂ X ͕ R ʹؔͯ͠ۃখݩΛ ࣋ͭ 2018/01/20 VeriFast Termination Checking 28 / 74
  35. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ inductive σʔλ্ͷ੔ૅؔ܎ fixpoint ؔ਺ͷఀࢭੑ͸ɺҾ਺ͷίϯετϥΫλͷ਺͕ؔ਺ݺͼग़͠ͷ౓ ʹݮ͍ͬͯ͘͜ͱʹґ͍ͬͯͨɻ fixpoint ͷఀࢭੑ ࣗવ਺ (ίϯετϥΫλͷ਺) ্ͷେখؔ܎͕੔ૅؔ܎Ͱ͋Δ͜ͱʹґͬͯ ͍Δɻ ੔ૅؔ܎ͷఆٛʹ౰ͯ͸Ίͯ֬ೝ͢Δɿ ੔ૅؔ܎ ∀S ⊆ X, S ̸= ∅ → ∃m ∈ S, ∀s ∈ S, (s, m) / ∈ R ࣗવ਺্ͷେখؔ܎ ∀S ⊆ N, S ̸= ∅ → ∃m ∈ S, ∀s ∈ S, (s, m) / ∈ (<) 2018/01/20 VeriFast Termination Checking 29 / 74
  36. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ੔ૅؔ܎ͷ௚؍ ΑΓ௚ײతʹ͸ɺ੔ૅؔ܎ͱ͸ɺू߹্ͷೋ߲ؔ܎ R ͕ແݶ߱Լྻ 4 Λ࣋ ͨͳ͍͜ͱΛݴ͏ɻ ͜Ε͸ܭࢉ͕ਐΉʹ࿈ΕͯԿ͔͕੔ૅؔ܎Ͱ͋Δେখؔ܎ʹԊͬͯݮগ͠ ͍ͯ͘ͳΒ͹ɺͦͷܭࢉ͕༗ݶ࣌ؒͰఀࢭ͢Δ͜ͱʹରԠ͢Δɻ(ؾ͕͢Δ) 4ৗʹΑΓখ͍͞ݩ͕ଘࡏ͢Δ͜ͱ 2018/01/20 VeriFast Termination Checking 30 / 74
  37. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ݮগ͢ΔϞϊ ੔ૅؔ܎Λಋೖͯ͠ inductive σʔλ (্ͷେখؔ܎) ΑΓॊೈͳೋ߲ؔ܎ ͕ѻ͑ΔΑ͏ʹͳͬͨɻͰ͸ C ݴޠͰ͸Կ͕ݮ͍ͬͯΔͱߟ͑Ε͹͍͍ͩ Ζ͏ʁ 2018/01/20 VeriFast Termination Checking 31 / 74
  38. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ݮগ͢ΔϞϊ ੔ૅؔ܎Λಋೖͯ͠ inductive σʔλ (্ͷେখؔ܎) ΑΓॊೈͳೋ߲ؔ܎ ͕ѻ͑ΔΑ͏ʹͳͬͨɻͰ͸ C ݴޠͰ͸Կ͕ݮ͍ͬͯΔͱߟ͑Ε͹͍͍ͩ Ζ͏ʁ ఏҊɿcall permission (ؔ਺ΛݺͿݖར)a aʮpermissionʯͳͷͰʮڐ୚ʯͷํ͕ద੾͔΋ 2018/01/20 VeriFast Termination Checking 31 / 74
  39. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call permission ͷಋೖ ؔ਺ݺͼग़͠ʹ͸ඞͣ call permission ͱ͍͏ݖར͕ඞཁͱ͍͏͜ͱʹ ͢Δɻ ؔ਺ f ΛݺͿͨΊʹ call_perm(f) ͕ (Ұͭ) ඞཁ ؔ਺ f ΛݺͿ౓ʹ call_perm(f) ͕ (Ұͭ) ݮগ 2018/01/20 VeriFast Termination Checking 32 / 74
  40. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call permission ͷಋೖ ؔ਺ݺͼग़͠ʹ͸ඞͣ call permission ͱ͍͏ݖར͕ඞཁͱ͍͏͜ͱʹ ͢Δɻ ؔ਺ f ΛݺͿͨΊʹ call_perm(f) ͕ (Ұͭ) ඞཁ ؔ਺ f ΛݺͿ౓ʹ call_perm(f) ͕ (Ұͭ) ݮগ ࠷ॳʹؔ਺ͦΕͧΕͷ༗ݶݸͷ call_perm ͷετοΫΛ༩͑Δ ؔ਺͔Βݺͼग़͢શͯͷؔ਺ͷ call_perm Λࣄલ৚݅ʹཁٻ͢Δ ݕূΛύεग़དྷΕ͹༗ݶճ͔ؔ͠਺ݺͼग़͠͸ແ͍ (ఀࢭ͢Δ) ͸ͣͰ ͋Δ 2018/01/20 VeriFast Termination Checking 32 / 74
  41. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call permission ͷ࣮૷ call permission ͷ௥੻͸طଘͷ predicate ͱಉ༷ͷ࢓૊ΈͰՄೳɻ ඪ४ϥΠϒϥϦͰ೚ҙͷؔ਺ϙΠϯλ্ͷ૊ΈࠐΈͷ predicate ͱͯ͠ఏ ڙ͞Εɺ࣮ମ͸Ϣʔβଆʹެ։͞Ε͍ͯͳ͍ɻ call permission ͷ࣮૷ // prelude.h predicate call_perm_(void *f;); ;(ηϛίϩϯ) ͕෇͍͍ͯΔͷͰɺಉ͡ϙΠϯλʹ͍ͭͯͷ call_perm_͸Ұ ҙʹఆ·Δɻ 2018/01/20 VeriFast Termination Checking 33 / 74
  42. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_perm_ͷ࢖༻ ؔ਺ f ΛݺͿͨΊʹ͸ call_perm_(f) ͕ඞཁͱ͞ΕΔ call_perm_ͷ࢖༻ (pseudo) void call (void) //@ requires call_perm_(f); //@ ensures emp; //@ terminates; { f(); } 2018/01/20 VeriFast Termination Checking 34 / 74
  43. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_perm_ͷ࢖༻ ؔ਺ f Λ 2 ճݺͿ͜ͱ͸Ͱ͖ͳ͍ɻ call_perm_ͷ࢖༻ (pseudo) void call (void) //@ requires call_perm_(f); //@ ensures emp; //@ terminates; { f(); f(); // ~should_fail } 2018/01/20 VeriFast Termination Checking 35 / 74
  44. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_perm_ͷ࢖༻ ؔ਺ f Λ 2 ճݺͿͨΊʹ͸ call_perm_(f) ͕ 2 ͭඞཁ call_perm_ͷ࢖༻ void call (void) //@ requires [2] call_perm_(f); //@ ensures emp; //@ terminates; { f(); f(); } 2018/01/20 VeriFast Termination Checking 35 / 74
  45. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_perm_ͷߏ੒ ؔ਺ΛݺͿͨΊʹ͸ call_perm_͕ඞཁ͕ͩɺcall_perm_ͱ͍͏໋୊ͷΠϯ ελϯε͸௚઀ߏ੒Ͱ͖ͣɺ·ͣ call_below_perm_ͱ͍͏໋୊Λܦ༝͢Δ ඞཁ͕͋Δɻ call_below_perm // prelude.h predicate call_below_perm_ (void *f;); 2018/01/20 VeriFast Termination Checking 36 / 74
  46. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_below_perm_ͷಋग़ call_below_perm_ΛಘΔʹ͸ɺproduce_call_below_perm_ͱ͍͏૊ΈࠐΈ໋ ྩ 5 Λ࢖͏ɻ produce_call_below_perm void func (void) //@ requires emp; //@ ensures call_below_perm_ (func ); { //@ produce_call_below_perm_ (); //@ assert( call_below_perm_ (func )); } ͋Δؔ਺ func ͔Β produce_call_below_perm_ΛݺͿͱɺ call_below_perm_(func) ͕ (Ұͭ) खʹೖΔɻ 5ΰʔετίϚϯυ (ghost command) ͱݺ͹ΕΔ 2018/01/20 VeriFast Termination Checking 37 / 74
  47. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_perm_Λಋग़͢Δ call_below_perm_(f) ͔Β͸ඪ४ϥΠϒϥϦͷఏڙ͞ΕΔิ୊ʹΑͬͯ call_perm_(g)(ͨͩ͠ g < f ) ͕ಋग़Ͱ͖Δɻ call_below_perm_͔Β call_perm_Λಋग़͢Δ void g (void ); //@ terminates; void f (void) //@ requires emp; //@ ensures emp; //@ terminates; { //@ produce_call_below_perm_ (); //@ call_below_perm__elim (f); //@ consume_call_perm_for (g); g(); } 2018/01/20 VeriFast Termination Checking 38 / 74
  48. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_below_perm_ call_below_perm_͸ఀࢭੑݕࠪͷϞδϡϥϦςΟΛߴΊΔͨΊʹಋೖ͞Ε ໋ͨ୊ 6 Ͱɺcall_perm_ͱͷؒʹҎԼͷΑ͏ͳؔ਺ͷେখؔ܎ 7 ʹجͮ͘େ খؔ܎͕ఆٛ͞Ε͍ͯΔɻ call_perm_ͱ call_below_perm_ͷେখؔ܎ ∀f g, g < f → call_perm_(g) < call_below_perm_(f ) < call_perm_(f ) 6චऀͷ༧૝ 7ؔ਺ͷେখؔ܎͸ޙड़ 2018/01/20 VeriFast Termination Checking 39 / 74
  49. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ call_below_perm_ call_below_perm_͸ఀࢭੑݕࠪͷϞδϡϥϦςΟΛߴΊΔͨΊʹಋೖ͞Ε ໋ͨ୊ 6 Ͱɺcall_perm_ͱͷؒʹҎԼͷΑ͏ͳؔ਺ͷେখؔ܎ 7 ʹجͮ͘େ খؔ܎͕ఆٛ͞Ε͍ͯΔɻ call_perm_ͱ call_below_perm_ͷେখؔ܎ ؔ਺ f ͷఆٛதͰߏ੒Ͱ͖Δ call_below_perm_(f) ͸ɺcall_perm_(f) ະຬ Ͱ࠷େͷ call permssionɻ 6චऀͷ༧૝ 7ؔ਺ͷେখؔ܎͸ޙड़ 2018/01/20 VeriFast Termination Checking 39 / 74
  50. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering call_perm ΛͲ͏΍ͬͯ༩͑Δ͔ call_perm_ͱ call_below_perm_Λ࢖͑͹ɺݕূ͢Δର৅ؔ਺ΑΓখ͍ؔ͞ ਺Λܾ·ͬͨճ਺ݺͼग़͢έʔεʹ͍ͭͯ͸ݕূͰ͖ͦ͏ͩͬͨɻ 2018/01/20 VeriFast Termination Checking 40 / 74
  51. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering call_perm ΛͲ͏΍ͬͯ༩͑Δ͔ ؔ਺ͷఀࢭੑΛݕূ͢Δʹ͸ҎԼͷखॱ͕ඞཁͩͬͨɻ ࠷ॳʹؔ਺ͦΕͧΕͷ༗ݶݸͷ call_perm ͷετοΫΛ༩͑Δ ͱ͜Ζ͕Ұൠʹɺݕূ͠Α͏ͱ͍ͯ͠Δؔ਺͕Ͳͷؔ਺ΛԿ౓ݺͿ͔ͳΜ ͯ෼͔Βͳ͍. . . 2018/01/20 VeriFast Termination Checking 41 / 74
  52. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering call_perm ΛͲ͏΍ͬͯ༩͑Δ͔ ؔ਺ͷఀࢭੑΛݕূ͢Δʹ͸ҎԼͷखॱ͕ඞཁͩͬͨɻ ࠷ॳʹؔ਺ͦΕͧΕͷ༗ݶݸͷ call_perm ͷετοΫΛ༩͑Δ ͱ͜Ζ͕Ұൠʹɺݕূ͠Α͏ͱ͍ͯ͠Δؔ਺͕Ͳͷؔ਺ΛԿ౓ݺͿ͔ͳΜ ͯ෼͔Βͳ͍. . . ⇒ ଟॏू߹ (multiset,bag) ͱ DW-Ordering Λ࢖͏ 2018/01/20 VeriFast Termination Checking 41 / 74
  53. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering ଟॏू߹ ଟॏू߹ (multi set) ͸ɺཁૉͷॏෳΛڐ͢ू߹ɻ ଟॏू߹ͷྫ {[]} {[1, 2, 3]} {[1, 3, 3, 5, 5, 5, 6]} ͦΕͧΕͷཁૉ਺Λଟॏ౓ͱݺͼɺҎԼͷΑ͏ʹදه͢Δɻ ଟॏ౓ M = {[1, 3, 3, 5, 5, 5, 6]} ͷ࣌ɺ M(0) = 0 M(3) = 2 M(5) = 3 2018/01/20 VeriFast Termination Checking 42 / 74
  54. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering ଟॏू߹ ࠓճͷٞ࿦Ͱ͸݁߹ (join) ͱݺ͹ΕΔૢ࡞͕ඞཁʹͳΔ 8ɻ ଟॏू߹ͷ݁߹ (join) {[1, 2, 3]} ⊎ {[2, 3, 4]} = {[1, 2, 2, 3, 3, 4]} 8࣮૷͸୯ͳΔϦετͷ࿈݁ 2018/01/20 VeriFast Termination Checking 43 / 74
  55. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering ଟॏू߹্ͷॱংؔ܎ ൒ॱংؔ܎ͷ͋Δཁૉ͔ΒͳΔଟॏू߹ʹҎԼͷΑ͏ͳॱংؔ܎Λ༩͑ Δ 9ɻ Dershowitz–Manna ordering ଟॏू߹ M,N ʹ͍ͭͯɺେখؔ܎ (<) ΛҎԼͷΑ͏ʹఆٛ͢Δɻ M < N ≡ M ̸= N ∧ ∀y ∈ S, M(y) > N(y) → ∃x ∈ S, y < x ∧ M(x) < N(x) ͜ͷنଇʹै͑͹ྫ͑͹ {[0, 0, 1, 2, 2, 2]} < {[0, 0, 0, 3]} ͕੒Γཱͭɻ 9࿦จதͰཅʹݴٴ͕ແ͍͕ Dershowitz-Manna Ordering ͩͱࢥΘΕΔ 2018/01/20 VeriFast Termination Checking 44 / 74
  56. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering ଟॏू߹্ͷॱংؔ܎ ൒ॱংؔ܎ͷ͋Δཁૉ͔ΒͳΔଟॏू߹ʹҎԼͷΑ͏ͳॱংؔ܎Λ༩͑ Δ 9ɻ Dershowitz–Manna ordering[1] In order to descend down the multiset order starting from a multiset M, one can replace any element of M with any number of lesser elements of X, any number of times. (খ͍͞ཁૉ͸زͭ͋ͬͯ΋ΑΓେ͖͍ཁૉ 1 ͭΑΓখ͍͞) ͜ͷنଇʹै͑͹ྫ͑͹ {[0, 0, 1, 2, 2, 2]} < {[0, 0, 0, 3]} ͕੒Γཱͭɻ 9࿦จதͰཅʹݴٴ͕ແ͍͕ Dershowitz-Manna Ordering ͩͱࢥΘΕΔ 2018/01/20 VeriFast Termination Checking 44 / 74
  57. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering func_lt ͱ͜Ζ͕ VeriFast ʹ͸೚ҙͷؔ਺ϙΠϯλΛେখൺֱͰ͖Δؔ਺͕͋Δɻ ؔ਺ͷେখؔ܎ // prelude.h fixpoint bool func_lt(void *f, void *g); 2018/01/20 VeriFast Termination Checking 45 / 74
  58. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering func_lt ͱ͜Ζ͕ VeriFast ʹ͸೚ҙͷؔ਺ϙΠϯλΛେখൺֱͰ͖Δؔ਺͕͋Δɻ ؔ਺ͷେখؔ܎ // prelude.h fixpoint bool func_lt(void *f, void *g); ⇒ ͲͷΑ͏ʹେখؔ܎Λఆٛ͢Δͷ͔ʁ 2018/01/20 VeriFast Termination Checking 45 / 74
  59. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering func_lt ιʔείʔυ্ͷ্Լؔ܎Λͦͷ··࢖͏ʂ ؔ਺ͷେখؔ܎ void foo (void) //@ terminates; { } void bar (void) //@ terminates; { } void cmp (void) //@ terminates; { //@ assert func_lt(foo , bar) == true; //@ assert func_lt(bar , foo) == false; } ͜ͷେখؔ܎͸ VeriFast ͕ࣗಈͰಋग़ͯ͘͠ΕΔɻ 2018/01/20 VeriFast Termination Checking 46 / 74
  60. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering DW-Ordering Λಋग़ͨ͠खॱ ͜Ε·ͰͰҎԼͷखॱͰଟॏू߹্ͷ੔ૅؔ܎͕खʹೖͬͨɻ ؔ਺ʹେখؔ܎͕ಋೖ͞Εͨ (func_lt ͕࢖͑Δ) call_perm_্ʹ΋ͦͷେখؔ܎Λͦͷ··࢖͏ call_perm_্ͷେখؔ܎͔Β Dershowitz-Manna ordering Ͱ੔ૅؔ܎Λ ఆٛ͢Δ 2018/01/20 VeriFast Termination Checking 47 / 74
  61. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering DW-Ordering Λಋग़ͨ͠खॱ ͜Ε·ͰͰҎԼͷखॱͰଟॏू߹্ͷ੔ૅؔ܎͕खʹೖͬͨɻ ͜ͷؔ܎Λ࢖͏ͱɺΑΓখ͍͞ call_perm_Λ೚ҙݸಋग़͢Δ͜ͱ͕ग़དྷΔɻ derive permissions void g (void) //@ requires call_perm ({h}); { func_t * ff = f; //@ call_perm_below (2); //@ assert [2] call_perm_(f); //@ consume_call_perm_for (f); //@ consume_call_perm_for (f); ff(); ff(); } void f (void) //@ : func_t { } void h (void) { } 2018/01/20 VeriFast Termination Checking 47 / 74
  62. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering C ݴޠؔ਺ͷఀࢭੑݕࠪ·ͱΊ call permission ͱ͍͏֓೦Λಋೖ call_perm_ͷଟॏू߹্Ͱ੔ૅؔ܎Λఆٛ͢Δ ఆٛͨ͠੔ૅؔ܎ʹΑͬͯɺΑΓখ͍͞ call_perm_͸೚ҙͷ਺͚ͩಋ ग़Ͱ͖Δ 2018/01/20 VeriFast Termination Checking 48 / 74
  63. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ଟॏू߹ͱ DW-Ordering C ݴޠؔ਺ͷఀࢭੑݕࠪ·ͱΊ call permission ͱ͍͏֓೦Λಋೖ call_perm_ͷଟॏू߹্Ͱ੔ૅؔ܎Λఆٛ͢Δ ఆٛͨ͠੔ૅؔ܎ʹΑͬͯɺΑΓখ͍͞ call_perm_͸೚ҙͷ਺͚ͩಋ ग़Ͱ͖Δ ݕࠪର৅ʹؚ·ΕΔؔ਺ͷதͰɺ࠷େͷؔ਺ΛݺͿ͜ͱ͕ग़དྷΔ call_perm_Λ༩͑Ε͹ɺଞ͸ͦͷ call_perm_͔Βಋग़͢Ε͹Α͍ ϓϩάϥϜશମΛݕূ͍ͨ͠৔߹͸ main ؔ਺ΛϑΝΠϧ຤ඌʹఆٛ ͠ɺcall_below_perm_(main) Λ࢖͏ 2018/01/20 VeriFast Termination Checking 48 / 74
  64. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ύλʔϯผݕࠪํ๏ ͜͜·ͰͰ VeriFast ʹΑΔఀࢭੑݕࠪͷ͓͓Αͦͷํ਑ͱཧ࿦తͳഎܠΛ આ໌͖ͯͨ͠ɻ͜ΕҎ߱Ͱ͸ݕূ͢Δର৅ίʔυͷύλʔϯຖʹɺ஫ऍΛ ෇͚͍ͯ͘ํ๏ͱ࣮ࡍͷίʔυΛղઆ͢Δɻ 2018/01/20 VeriFast Termination Checking 49 / 74
  65. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ ύλʔϯͷ෼ྨ ղઆ͢Δύλʔϯͷ෼ྨ͸ҎԼͷΑ͏ʹ໊લ͕෇͍͍ͯΔ 10 Upcalls Only ύλʔϯ Static Recursion ύλʔϯ Dynamic Binding ύλʔϯ 10Jacobs(2015)[1] ͰఏҊ͞Ε͍ͯΔ΋ͷͱಉҰɻ 2018/01/20 VeriFast Termination Checking 50 / 74
  66. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Upcalls Only ύλʔϯ Upcalls Only ݺͼग़͞ΕΔؔ਺͕ɺશͯͦͷ࣌఺Ͱఆٛ͞Ε͓ͯΓɺ͔ͭ࠶ؼ͍ͯ͠ͳ ͍ύλʔϯɻ ͜ͷ৔߹ؔ਺ݺͼग़͕͠ৗʹࣗ෼ΑΓখ͍ؔ͞਺ͷݺͼग़͠ʹͳΔͨΊɺ ࣗ໌ʹఀࢭ͢Δͱݴ͑Δɻ 2018/01/20 VeriFast Termination Checking 51 / 74
  67. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Upcalls Only ύλʔϯ Upcalls Only ͜ͷ৔߹͸ࣗಈͰݕࠪͰ͖Δɻ upcalls_only void foo(void) //@ requires emp; //@ ensures emp; //@ terminates; {} void bar(void) //@ requires emp; //@ ensures emp; //@ terminates; { foo (); } void bazz(void) //@ requires emp; //@ ensures emp; //@ terminates; { bar (); } ͜ͷ৔߹ɺcall_perm_͸ূ໌ίϯςΩετதʹ໌ࣔతʹ͸ݱΕͳ͍ɻ 2018/01/20 VeriFast Termination Checking 52 / 74
  68. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ Static Recursion ୯ҰϨΠϠ 11 ಺Ͱ૬ޓ࠶ؼ͍ͯ͠Δ৔߹ɺ͜ΕΛ static recursion ύλʔϯ ͱݺͿɻ௚઀࠶ؼ͍ͯ͠Δύλʔϯ΋͜Εʹؚ·ΕΔɻ 11ಉҰϑΝΠϧ 2018/01/20 VeriFast Termination Checking 53 / 74
  69. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ Static Recursion యܕతͳྫͱͯ͠૬ޓ࠶ؼͨ͠ۮد൑ఆͷؔ਺Λѻ͏ɻ bool isOdd (int x) //@ requires 0 <= x; //@ ensures emp; //@ terminates; { if (x == 0) return false; return isEven(x -1); } bool isEven(int x) //@ requires 0 <= x; //@ ensures emp; //@ terminates; { if (x == 0) return true; return isOdd(x -1); } 2018/01/20 VeriFast Termination Checking 54 / 74
  70. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ Static Recursion ࠶ؼؔ਺Ͱ͸ɺfunc_lt ʹґΔେখؔ܎͕ٯస͢Δؔ਺ݺͼग़͠ 12 Λඞͣ ؚΉͨΊɺ୯ʹؔ਺ͷେখΛൺֱ͢Δ͚ͩͰ͸ݕࠪͰ͖ͳ͍ɻ bool isOdd (int x) //@ requires 0 <= x; //@ ensures emp; //@ terminates; { if (x == 0) return false; return isEven(x -1); } bool isEven(int x) //@ requires 0 <= x; //@ ensures emp; //@ terminates; { if (x == 0) return true; return isOdd(x -1); } 12ؔ਺ͷݺग़ଆ͕ݺ͹ΕΔଆͷؔ਺ΑΓখ͍͞ 2018/01/20 VeriFast Termination Checking 54 / 74
  71. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven/isOdd ͷݕূํ਑ isEven, isOdd ͷఀࢭੑΛݕূ͢Δʹ͸ɺͦΕͧΕͷҾ਺͕খ͘͞ͳ͍ͬͯ ͘ (༗ݶճͷݺͼग़͠Ͱ 0 ʹͳΔ) ͱ͍͏৘ใΛ࢖͍͍ͨɻ͜ͷͨΊʹ͸ predicate call_perm_level Λ࢖͏ɻ 2018/01/20 VeriFast Termination Checking 55 / 74
  72. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ call_perm_level call_perm_level ͸ call_perm_ͱɺ੔ૅؔ܎Λ࣋ͭ೚ҙͷܕ͔Βಋग़͞Ε Δɺมܗͨ͠λϓϧɻ13 call_perms.gh predicate call_perm_level <t>( // t ্ͷେখؔ܎ͱ t ܕͷ஋ pair <fixpoint(t, t, bool), t> level , // ؔ਺ϙΠϯλͷଟॏू߹ list <void *> fs; ); 13ؔ਺ؒͷେখؔ܎͸ॲཧܥఆٛͳͷͰෆཁ 2018/01/20 VeriFast Termination Checking 56 / 74
  73. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ call_perm_level σεΫτϥΫτ͢Ε͹ call_perm_͕ಘΒΕΔɻ call_perms.gh lemma void consume_call_perm_level_for <t>( void *f); requires call_perm_level <t>(? level , ?fs) &*& mem(f, fs) == true; ensures call_perm_(f); 2018/01/20 VeriFast Termination Checking 56 / 74
  74. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ call_perm_level DW-Ordering ʹΑΓɺλϓϧͷୈ 1 ཁૉ͕੔ૅؔ܎ͰΑΓখ͍͞஋ΛऔΔ Α͏ͳ೚ҙݸͷ call_perm_level ʹஔ͖׵͑ͯΑ͍ɻσεΫτϥΫτͷ໋ ୊ͱ߹ΘͤΔͱɺcall_perm_Λ૿΍͍ͤͯΔ͜ͱʹ஫ҙɻ call_perms.gh lemma void call_perm_level_weaken <t>( real frac0 , fixpoint(t, t, bool) lt , t level0 , list <void *> fs0 , real frac1 , t level1 ); requires [_]is_wf(lt) &*& lt(level1 , level0) == true &*& 1 <= frac0 &*& 1 <= frac1 &*& [frac0]call_perm_level <t>( pair(lt , level0), fs0); ensures [frac1]call_perm_level <t>( pair(lt , level1), fs0); 2018/01/20 VeriFast Termination Checking 56 / 74
  75. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven/isOdd ͷݕূํ਑ ࠓճͷྫͷݕূͰ͸ isOdd(খ͍ؔ͞਺) ͔Β isEven(େ͖͍ؔ਺) ΛݺͿ͜ ͱ͕ग़དྷͳ͍ͷ͕໰୊ͩͬͨɻ͜Ε͸ઌʹڍ͛ͨ call_perm_level Λ࢖͏ ͱҎԼͷΑ͏ʹճආग़དྷΔɻ call_perm_level(pair(lt,x),{isEven}) ͔Β call_perm_level(pair(lt,x-1),{isEven}) Λಋग़͢Δ 2 ͭ͋Δ call_perm_level ಺ͷҰ͔ͭΒ call_perm_(isEven) Λಋग़͢ Δ (ͱ isEven ΛݺͿ͜ͱ͕ग़དྷΔ) isOdd ͷࣄલ৚݅Ͱ call_perm_level(pair(lt,x),{isEven}) Λཁٻ ͢Δ 2018/01/20 VeriFast Termination Checking 57 / 74
  76. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven/isOdd ͷݕূํ਑ ࠓճͷྫͷݕূͰ͸ isOdd(খ͍ؔ͞਺) ͔Β isEven(େ͖͍ؔ਺) ΛݺͿ͜ ͱ͕ग़དྷͳ͍ͷ͕໰୊ͩͬͨɻ͜Ε͸ઌʹڍ͛ͨ call_perm_level Λ࢖͏ ͱҎԼͷΑ͏ʹճආग़དྷΔɻ isOdd(஫ऍத) bool isOdd (int x) /*@ requires 0 <= x &*& call_perm_level (pair(lt , x), {isEven }); @*/ { if (0 == x) { return false; } else { //@ is_wf_lt (); //@ call_perm_level_weaken (1, lt , x, {isEven}, 2, x -1); //@ consume_call_perm_level_for (isEven ); return isEven(x -1); } } ͜ΕͰओཁͳ໰୊͕ย෇͍ͨɻ͋ͱ͸ isOdd ͷࣄલ৚͕݅ຬͨͤΕ͹Α͍ɻ 2018/01/20 VeriFast Termination Checking 57 / 74
  77. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven ͷࣄલ৚݅ isOdd ͷࣄલ৚݅Ͱ call_perm_level(pair(lt,x),{isEven}) ͕ཁٻ͞Εͯ ͍Δ͕ɺ͜Ε͸ isEven ͷ࣮૷தʹಋग़͢Δ͜ͱ͸ग़དྷͳ͍ 13ɻ 13ؔ਺ f தͰ͸ɺΑΓখ͍͞ call_below_perm_(f) ͔͠ಋग़ग़དྷͳ͍ 2018/01/20 VeriFast Termination Checking 58 / 74
  78. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven ͷࣄલ৚݅ isOdd ͷࣄલ৚݅Ͱ call_perm_level(pair(lt,x),{isEven}) ͕ཁٻ͞Εͯ ͍Δ͕ɺ͜Ε͸ isEven ͷ࣮૷தʹಋग़͢Δ͜ͱ͸ग़དྷͳ͍ 13ɻ ͳͷͰɺ isEven Ͱ΋ࣄલ৚݅ʹಉ͡΋ͷΛཁٻ͢Δɻ 13ؔ਺ f தͰ͸ɺΑΓখ͍͞ call_below_perm_(f) ͔͠ಋग़ग़དྷͳ͍ 2018/01/20 VeriFast Termination Checking 58 / 74
  79. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven ͷࣄલ৚݅ isOdd ͷࣄલ৚݅Ͱ call_perm_level(pair(lt,x),{isEven}) ͕ཁٻ͞Εͯ ͍Δ͕ɺ͜Ε͸ isEven ͷ࣮૷தʹಋग़͢Δ͜ͱ͸ग़དྷͳ͍ 13ɻ isEven(஫ऍத) bool isEven(int x) /*@ requires 0 <= x &*& call_perm_level (pair(lt , x), {isEven }); @*/ { if (0 == x) { return true; } else { //@ is_wf_lt (); //@ call_perm_level_weaken (1, lt , x, {isEven}, 1, x - 1); return isOdd(x -1); } } isOdd ͱҟͳΓΑΓখ͍ؔ͞਺Λݺͼग़ͨ͢Ίɺcall_perm_level Λ૿΍͢ ඞཁ͸ͳ͍ɻ 13ؔ਺ f தͰ͸ɺΑΓখ͍͞ call_below_perm_(f) ͔͠ಋग़ग़དྷͳ͍ 2018/01/20 VeriFast Termination Checking 58 / 74
  80. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven/isOdd ͷϥούʔ ͜ΕͰ isEven ͱ isOdd ͷఀࢭੑ͕ݕࠪͰ͖͕ͨɺͦΕͧΕͷࣄલ৚݅ʹ͜ Ε·Ͱ͸ඞཁͳ͔ͬͨ call_perm_level Λཁٻ͢ΔΑ͏ͳͬͯ͠·ͬͨɻ ͜Ε͸ isEven ΑΓେ͖͍ؔ਺ͱͯ͠ϥούʔΛఆٛ͢Ε͹؆୯ʹղܾ ͢Δɻ 2018/01/20 VeriFast Termination Checking 59 / 74
  81. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven/isOdd ͷϥούʔ bool isOdd (int x) /*@ requires 0 <= x &*& call_perm_level (pair(lt , x), {isEven }); @*/ { ... } bool isEven(int x) { ... } bool isOddWrapper (int x) //@ requires 0 <= x; { //@ produce_call_below_perm_ (); //@ call_below_perm__elim (isOddWrapper ); //@ call_perm_level (1, pair(lt , x), {isEven }); return isOdd(x); } bool isEvenWrapper (int x) { ... ͱಉ༷isOddWrapper } 2018/01/20 VeriFast Termination Checking 59 / 74
  82. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ isEven/isOdd ͷϥούʔ ϥούʔͷࣄલ৚݅ͱͯ͠ call_perm_level ͕ݱΕ͍ͯͳ͍͜ͱʹ΋஫໨ɻ ϥούʔΛϔομ͔Βެ։͢Ε͹ɺϢʔβʹͱͬͯ͸ఀࢭੑݕࠪͷͨΊʹ ࣄલ৚͕݅ෳࡶʹ੒ΒͣʹࡁΉɻ bool isOddWrapper (int x) //@ requires 0 <= x; { //@ produce_call_below_perm_ (); //@ call_below_perm__elim (isOddWrapper ); //@ call_perm_level (1, pair(lt , x), {isEven }); return isOdd(x); } bool isEvenWrapper (int x) { ... ͱಉ༷isOddWrapper } 2018/01/20 VeriFast Termination Checking 59 / 74
  83. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ VeriFast ͷ੍ݶ ݱঢ়ͷ VeriFast Ͱ͸࣮૷ͷ੍ݶͰ isOdd ͔Β௚઀ isEven ͷݺग़͠͸ग़དྷͳ ͍ɻ͜Ε͸ؔ਺ϙΠϯλΛܦ༝ͨ͠ݺͼग़͠ʹ͢Ε͹ճආग़དྷΔɻ typedef bool is_even_fn(int x); /*@ requires 0 <= x &*& call_perm_level (pair(lt , x), {isEven }); @*/ bool isOdd (int x) /*@ requires 0 <= x &*& call_perm_level (pair(lt , x), {isEven }); @*/ { if (0 == x) { return false; } else { is_even_fn * evenp = isEven; //@ is_wf_lt (); //@ call_perm_level_weaken (1, lt , x, {isEven}, 2, x -1); //@ consume_call_perm_level_for (isEven ); return evenp(x -1); } } 2018/01/20 VeriFast Termination Checking 60 / 74
  84. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Static Recursion ύλʔϯ Static Recursion ͷݕূखॱ ͜Ε·ͰͷखॱΛ·ͱΊΔɻ ࣗ਎Ҏ্ͷؔ਺ͷݺͼग़͠Λؔ਺ϙΠϯλܦ༝ʹ͢Δ (ͨͩ͜͠Ε͸࣮ ૷ͷ౎߹) ࠶ؼݺͼग़͠ͷ౓ʹݮগ͢Δύϥϝʔλͱ call_perm_ͷλϓϧ (call_perm_level) Λ measure ͱ͢Δ ࠶ؼΛߏ੒͢Δશͯͷؔ਺ 14 ͷࣄલ৚݅ʹɺ࠶ؼΛߏ੒͢Δશͯͷؔ ਺ͷதͰ࠷େͷؔ਺ͷ call_perm_level Λ௥Ճ͢Δ ࠶ؼΛߏ੒͢Δؔ਺ΛϔομϑΝΠϧ͔Βެ։͢Δ৔߹͸ɺ͜ΕΛ௚ ઀ެ։ͤͣϥούʔΛఏڙ͠ɺ͜ΕΛެ։͢ΔΑ͏ʹ͢Δ (͜ΕʹΑͬ ͯࣄલ৚͕݅ෳࡶԽͤͣʹࡁΉ) 14͜͜Ͱ͸ isEven ͱ isOdd 2018/01/20 VeriFast Termination Checking 61 / 74
  85. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ Dynamic Binding ಈతʹଋറ͞Εͨؔ਺ݺͼग़͕͠ (Ұൠʹ͸) ૬ޓ࠶ؼ͢Δύλʔϯɻ ؔ਺ϙΠϯλΛड͚औΓɺ͜ΕΛݺͼग़͢৔߹ɻؔ਺͕౉͞ΕΔͷ͔͸ಈ తʹܾ·ΔͷͰ࢖༻ଆ (ϙΠϯλΛड͚औΔଆ) ʹ͸໌Β͔Ͱͳ͍ɻ Java ͷ৔߹͸ந৅Խ͞ΕͨΠϯλʔϑΣʔεΦϒδΣΫτΛड͚औΓɺͦ ͷެ։͢ΔϝιουΛ࢖༻͢Δ৔߹ʹ૬౰͢Δɻ 2018/01/20 VeriFast Termination Checking 62 / 74
  86. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ Dynamic Binding ͷྫ ྫͱͯ͠ࢀর࿦จதͷɺΦϒδΣΫτͷදࣜ͢ͷඍ෼Λܭࢉ͢ΔྫͷҰ෦ Λ࢖༻͢Δɻ (pseudo) interface RealFunc { float apply(float x); } class Math { static float derivative(RealFunc f, float x) { f.apply(x+1) - f.apply(x) } } class Identity implements RealFunc { float apply(float x) { x } } 2018/01/20 VeriFast Termination Checking 63 / 74
  87. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ ΠϯλʔϑΣʔεఆٛ ҎԼ͸ΠϯλʔϑΣʔεΛද͢ܕͷఆٛΛ͍ࣔͯ͠Δɻ struct realfunc_obj { real_func * invoke; // object method //@ predicate(realfunc_obj *) RealFunc; }; /*@ predicate realfunc_obj(realfunc_obj * object , void * invoke , predicate(realfunc_obj *) p) = object ->invoke |-> invoke &*& object ->RealFunc |-> p &*& [_] is_real_func(invoke , p) &*& p(object ); @*/ 2018/01/20 VeriFast Termination Checking 64 / 74
  88. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ ΠϯλʔϑΣʔεఆٛ ҎԼ͸ΠϯλʔϑΣʔεΛද͢ܕͷఆٛΛ͍ࣔͯ͠Δɻ real_func ͸ύϥ ϝʔλ෇͖ͷؔ਺ܕɻ ΦϒδΣΫτϝιουͷγάωνϟ typedef double real_func /*@(predicate(realfunc_obj *) RealFunc)@*/ (realfunc_obj * object , double x); //@ requires realfunc_obj(object , this , RealFunc ); //@ ensures realfunc_obj(object , this , RealFunc ); 2018/01/20 VeriFast Termination Checking 64 / 74
  89. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ Identity ΦϒδΣΫτͷߏங realfunc_obj * create_identity (void) //@ requires emp; //@ ensures realfunc_obj(result , identity , @identity ); { realfunc_obj * obj = malloc(sizeof(realfunc_obj )); if (!obj) abort (); obj ->invoke = identity; //@ obj ->RealFunc = @identity; /*@ produce_function_pointer_chunk real_func (identity )( @identity )(object , x) { call (); } @*/ //@ close identity(obj); return obj; //@ close realfunc_obj(obj , identity , @identity ); } 2018/01/20 VeriFast Termination Checking 65 / 74
  90. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ apply ϝιουͷ࣮૷ apply ͷ࣮૷ double realfunc_object_apply (realfunc_obj * obj , double x) //@ requires realfunc_obj(obj , _, _); //@ ensures realfunc_obj(obj , _, _); { //@ open realfunc_obj(obj , _, _); real_func * invoke = obj ->invoke; //@ close realfunc_obj(obj , invoke , _); return invoke(obj , x); } 2018/01/20 VeriFast Termination Checking 66 / 74
  91. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ Start Termchecking ͜͜·Ͱ͖ࣔͯͨ͠ΦϒδΣΫτΛ࢖༻͢Δؔ਺ͷఀࢭੑΛݕূ͢Δɻ 2018/01/20 VeriFast Termination Checking 67 / 74
  92. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ ΠϯόϦΞϯτΛ֦ு ಉҰΠϯλʔϑΣʔεΛ͍࣋ͬͯͯ΋ΦϒδΣΫτຖʹ࣮૷͕ҟͳΓ͏Δ ͨΊɺͦͷ call_perm_΋ͦΕͧΕҟͳΔɻ͜ΕΛอ࣋͢ΔͨΊɺΦϒδΣ ΫτͷΠϯόϦΞϯτΛ֦ு͢Δɻ struct realfunc_obj { real_func * invoke; // object method //@ predicate(realfunc_obj*, list <void*>) RealFunc; }; /*@ predicate realfunc_obj(realfunc_obj * object , void * invoke , predicate(realfunc_obj*, list <void*>) p , list <void*> d) = object ->invoke |-> invoke &*& object ->RealFunc |-> p &*& [_] is_real_func(invoke , p) &*& p(object , ?d_) &*& bag_le(func_lt , cons(invoke , d_), d) == true; @*/ 2018/01/20 VeriFast Termination Checking 68 / 74
  93. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ ΠϯόϦΞϯτΛ֦ு ݺͿؔ਺Λྻڍग़དྷΔΑ͏ʹ list<void*>Λࢦఆɻ͜ͷ૿΍ͨ͠ύϥϝʔλ ͷ͜ͱΛ dynamic depth ͱݺͿɻ typedef double real_func /*@(predicate(realfunc_obj*, list <void*>) p)@*/ (realfunc_obj * object , double x); /*@ requires [?f]realfunc_obj(object , this , p, ?d) &*& call_perm(d); @*/ //@ ensures [f] realfunc_obj(object , this , p, d); //@ terminates; 2018/01/20 VeriFast Termination Checking 68 / 74
  94. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ call permission ͷ্ք ֦ுͨ͠ΠϯόϦΞϯτʹ͸ɺग़དྷΔ͚ͩେ͖͍ call permission ͕࢖͑ ΔΑ͏ʹ͍ͨ͠ɻ ίϯετϥΫλͷؔ਺ (ͷ call_perm) Λ্ݶͱ͢Δ ݺͼ͍ͨؔ਺Λશͯ௥Ճ͢Δ 2018/01/20 VeriFast Termination Checking 69 / 74
  95. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ ίϯετϥΫλͷ permission Identity ΦϒδΣΫτͷίϯετϥΫλΛҎԼͷΑ͏ʹ֦ு͢Δɻ realfunc_obj * create_identity (void) /*@ requires call_perm_below (?d) &*& func_bag_lt ({ create_identity }, d) == true; @*/ /*@ ensures realfunc_obj(result , identity , @identity , { create_identity }); @*/ //@ terminates; { //... } 2018/01/20 VeriFast Termination Checking 70 / 74
  96. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ Dynamic Binding ͷݕূखॱ Dynamic Binding ύλʔϯͷݕূखॱΛ·ͱΊΔɻ ΦϒδΣΫτͷΠϯόϦΞϯτΛ֦ு͠ɺdynamic depth ͱݺ͹ΕΔؔ ਺ϙΠϯλϦετΛ௥Ճ͢Δ ग़དྷΔ͚ͩେ͖͍ call_perm Λࢦఆ͢ΔͨΊɺίϯετϥΫτͨؔ͠ ਺ࣗ਎ͷ call_perm_Λ্ݶͱͯ͠࢖͏ ΦϒδΣΫτͷؔ਺಺ͰݺͿؔ਺ͷ call_perm_͸શͯ dynamic depth ʹ join ͢Δ 2018/01/20 VeriFast Termination Checking 71 / 74
  97. ໨࣍ VeriFast ֓ཁ ఀࢭੑݕࠪͱ͸Կ͔ VeriFast ʹΑΔఀࢭੑݕࠪ fixpoint ͷఀࢭੑ C ݴޠؔ਺ͷఀࢭੑݕࠪ

    ύλʔϯผఀࢭੑݕূ Dynamic Binding ύλʔϯ ·ͱΊ ͜ͷষͰ͸ҎԼͷ 3 ͭͷύλʔϯʹ͍ͭͯఀࢭੑΛݕࠪ͢Δํ਑ͱ۩ମྫ Λ͖ࣔͯͨ͠ɻ Upcalls Only ύλʔϯ Static Recursion ύλʔϯ Dynamic Binding ύλʔϯ ͲͷύλʔϯͰ΋ call_perm ͷେখؔ܎Ͱઆ໌ͱݕূ͕ग़དྷͨɻ 2018/01/20 VeriFast Termination Checking 72 / 74
  98. ࢀߟࢿྉ Bart Jacobs, Dragan Bosnacki, Ruurd Kuiper. Modular Termination Verification

    ECOOP 2015 http://www.cs.kuleuven.be/~bartj/ecoop2015.pdf VeriFast official web site https://people.cs.kuleuven.be/~bart.jacobs/verifast/ VeriFast Tutorial(೔ຊޠ൛) https://github.com/jverifast-ug/translate/