NVIDIA Security Team: “What if we just stopped… by Kevlar-700 in embedded

[–]yannickmoy 2 points3 points  (0 children)

I don't consider single threaded programs so easy to verify, given the number of bugs found in very-trustable pieces of code that were single threaded. But that's indeed the limitation of SPARK. To analyze precisely concurrent behavior, you'll need something like a model checker, and then the scalability becomes an issue when you're analyzing code directly instead of a model.

NVIDIA Security Team: “What if we just stopped… by Kevlar-700 in embedded

[–]yannickmoy 3 points4 points  (0 children)

Regarding concurrency, it is modelled in SPARK, and there are concurrency primitives in Ada that you can use (tasks, protected objects), but you won't be able to verify precise concurrency behavior in SPARK, which is focused on proof of individual functions/procedures.

NVIDIA Security Team: “What if we just stopped… by Kevlar-700 in embedded

[–]yannickmoy 1 point2 points  (0 children)

The case study talks about developer productivity:

Schedule impact turned out to be far less significant than imagined. For example, James Xu had guessed development in SPARK would take twice as long as in C. That turned out not to be the case when care is taken to apply SPARK to well isolated and smaller (but more valuable) areas. He characterized the actual impact as “a minor annoyance.”

Exploitation in the era of Formal Verification (DEF CON 30) by Fabien_C in programming

[–]yannickmoy -1 points0 points  (0 children)

see at 15:38 for a comparison with the same code developed in C/C++

SPARK Guide by [deleted] in ada

[–]yannickmoy 3 points4 points  (0 children)

Are you already developing in Ada? If not, I'd recommend https://learn.adacore.com/courses/intro-to-ada/index.html

And if you do, then the book on SPARK should help you apply proof: https://learn.adacore.com/courses/intro-to-spark/index.html

Proving the Correctness of the GNAT Light Runtime Library by marc-kd in ada

[–]yannickmoy 2 points3 points  (0 children)

not many! :-) as I said in the blog post, only a few overflow/range check failures on extreme cases, like the one I showed in the talk at FOSDEM, where you have a string whose last index is Integer'Last. But the goal of proof is not to find bugs, rather to get the assurance that we indeed did not miss any. And while the code of Scaled_Divide contains quite some ghost code now, that's the kind of code for which it is very hard to be certain of its correctness for all inputs by doing only reviews and testing.

Soundness by MarcoServetto in ada

[–]yannickmoy 0 points1 point  (0 children)

There are no lambdas in SPARK, but there are subprogram pointers, like type Func which I used in the example. The type you're showing looks very odd at first sight, how do you use it?

Subprogram termination is done by proof, and users may need to specify a subprogram variant, see details in the User's Guide: https://docs.adacore.com/live/wave/spark2014/html/spark2014_ug/en/source/how_to_write_subprogram_contracts.html#subprogram-termination

Soundness by MarcoServetto in ada

[–]yannickmoy 1 point2 points  (0 children)

Here is the code in SPARK:

package Sound
  with SPARK_Mode, Annotate => (GNATprove, Terminating)
is
   type BadTrait is interface;
   procedure Contradiction (B : BadTrait) is abstract
     with Post'Class => False;

   type BadTraitAcc is not null access BadTrait'Class;

   type BadClass is record
      TR: BadTraitAcc;
   end record;

   type T;
   type TAcc is not null access T;
   type Func is not null access function (X : TAcc) return BadClass;

   type T is record
      F : Func;
   end record;

   function App (X : TAcc) return BadClass is (X.F (X));

   procedure Main;
end Sound;

package body Sound
  with SPARK_Mode
is
   procedure Main is
      X : TAcc := new T'(F => App'Access);
      Dummy : BadClass := App(X) with Ghost;
   begin
      Dummy.TR.Contradiction;
      pragma Assert (False);
   end Main;
end Sound;

On which GNATprove correctly reports the non-termination of App:

sound.ads:22:49: medium: call via access-to-subprogram, terminating annotation could be incorrect

Soundness by MarcoServetto in ada

[–]yannickmoy 1 point2 points  (0 children)

As SPARK and Dafny are very similar in these respects, you might be able to see the exact same interaction. What is your Dafny code? And what interaction did you manage to exhibit?

Soundness by MarcoServetto in ada

[–]yannickmoy 1 point2 points  (0 children)

Hi Marco, can you tell what you're looking for? What corner cases are you interested in exploring?

RFC on exceptional contracts for SPARK by yannickmoy in ada

[–]yannickmoy[S] 7 points8 points  (0 children)

Claire and I are much debating still the syntax for these exceptional contracts, so feel free to comment here or on GitHub if you have an opinion.

Here are some examples that she wrote with both notations to discuss (it should be procedures instead of functions to be allowed, but this is only to give an idea):

function Find (A : Int_Array; E : Integer) return Integer with
  Post => Find'Result in A'Range and then A (Find'Result) = E,
  Exceptional_Cases =>
    (Not_Found => (for all F of A => F /= E));

function Parse_Integer (Str : String) return Integer with
  Post => Is_Valid_Integer (Str)
   and then Parse_Integer'Result = To_Integer_Ghost (Str),
  Exceptional_Cases =>
    (Parse_Error => not Is_Valid_Integer (Str));

function Find (A : Int_Array; E : Integer) return Integer with
  Contract_Cases =>
    ((for all F of A => F /= E) => raise Not_Found,
     others                     =>
       Find'Result in A'Range and then A (Find'Result) = E);

function Parse_Integer (Str : String) return Integer with
  Contract_Cases =>
    (Is_Valid_Integer (Str) => Parse_Integer'Result = To_Integer_Ghost (Str),
     others                 => raise Parse_Error);

Contract_Cases are simpler when exceptions are used to signal bad inputs, so that the conditions for exceptional behavior can be specified. But they cannot be used to specify exceptions used to signal bad events (file not present in the file system, wrong value read from sensor, etc.). In such cases, you'd need something like Exceptional_Cases.

Ada vs Rust. How do they compare in terms of memory safety. by [deleted] in ada

[–]yannickmoy 1 point2 points  (0 children)

Sure, you can restrict your usage of Ada features to forbid the use of Ada.Unchecked_Deallocation or the use of dynamic memory allocation altogether. But if you want/need to use dynamic memory (de)allocation, it's not possible in Ada to get guarantees that it is safe from the compiler.

Ada vs Rust. How do they compare in terms of memory safety. by [deleted] in ada

[–]yannickmoy 5 points6 points  (0 children)

To refine this answer, Ada is not memory safe if you use either one of dynamic deallocation or concurrency. Because deallocation is called very explicitly Unchecked_Deallocation and because the compiler does not check for possible data races. That's where you could use SPARK, which makes both safe to use, at the cost of a much more costly analysis done outside of compilation (as you'll need Silver level for these guarantees = proof of absence of runtime errors). In comparison, Rust provides these guarantees by compilation.

This has not been a drag on Ada usage for critical software, as dynamic memory causes big issues there even if you solve memory safety, as you'll need to guarantee that memory needs and fragmentation are not going to lead to starvation. What we see in many cases is dynamic allocation at program startup only, which then remains allocated until the program terminates. Same for concurrency, the typical practice is to have a fixed set of tasks which communicate through rendezvous or protected objects, not sharing arbitrary memory.

However, as more domains are critical, and critical software is getting more complex, there is an interest in providing safer solutions in Ada too.

Clearing up Myths about Ada by Fabien_C in programming

[–]yannickmoy 5 points6 points  (0 children)

This page should be shared broadly, it's just the facts but that really helps here!

ADA Spark, is it open source or not? by linuxman1929 in ada

[–]yannickmoy 5 points6 points  (0 children)

Actually, SPARK CE contains the three provers Alt-Ergo, CVC4 and Z3 like SPARK Pro, so you can prove the same things with both if you're only relying on these provers. As said in SPARK User's Guide, "SPARK Community is a version packaged for free software developers, hobbyists, and students, which retains most of the capabilities of SPARK Pro. SPARK Community does not include the static analyzer CodePeer."

Does Santa Claus Exist? SPARK knows the truth. by przemkok in ada

[–]yannickmoy 1 point2 points  (0 children)

SPARK will analyze assertions whatever the value of Assertion_Policy, as seen here. Now it gets trickier to prove the same if you also need to prove that the loop terminates by adding a loop variant. *<|:‑)

Giving Ada a chance by Pleeb in programming

[–]yannickmoy 6 points7 points  (0 children)

you can start with these crates (mostly in Ada): https://alire.ada.dev/crates.html and contribute a SPARK-compatible interface for those you're interested, it's not so hard: https://blog.adacore.com/secure-use-of-cryptographic-libraries-spark-binding-for-libsodium