engineering better software at microsoft
play

Engineering Better Software at Microsoft Jason Yang - PowerPoint PPT Presentation

Engineering Better Software at Microsoft Jason Yang jasony@microsoft.com Principal Development Lead Windows Engineering Desktop Microsoft Corporation Who we are Windows Engineering Desktop Analysis Technologies Team Develops and supports


  1. Engineering Better Software at Microsoft Jason Yang jasony@microsoft.com Principal Development Lead Windows Engineering Desktop Microsoft Corporation

  2. Who we are Windows Engineering Desktop – Analysis Technologies Team Develops and supports some of the most critical compile-time program analysis tools and infrastructures used at Microsoft. Source-level global analyzer  PREfix local analyzer  PREfast/Esp  SAL source code annotation Binary-level binary instrumentation  Vulcan  Magellan code coverage CMU, 11/30/2010 Jason Yang, Microsoft 2

  3. A primer on SAL An introduction to program analysis A glimpse at the engineering process in Windows CMU, 11/30/2010 Jason Yang, Microsoft 3

  4. good APIs + annotations + analysis tools significantly fewer code defects CMU, 11/30/2010 Jason Yang, Microsoft 4

  5. 3,631,361 * * number of annotations in Windows alone more secure and reliable products CMU, 11/30/2010 Jason Yang, Microsoft 5

  6. Why SAL? Manual Review too many code paths to think about Massive Testing inefficient detection of simple programming errors Global Analysis long turn-around time Local Analysis lack of calling context limits accuracy SAL light-weight specifications make implicit intent explicit CMU, 11/30/2010 Jason Yang, Microsoft 6

  7. Evolution of Source Code Annotation Language (SAL) EspX SAL 2.0 2004 2010 Buffer overrun Improves checker coverage and deployed for usability SAL 1.0 EspC 2002 2007 Windows Vista Focuses on Concurrency buffer overrun checker deployed for Windows 7 PFD PREfast & PREfast for PREfix 2007 Drivers shipped VS 2005 Starts to 2003 with DDK SAL aware support 2005 compiler shipped annotations with Visual Studio CMU, 11/30/2010 Jason Yang, Microsoft 7

  8. SAL C0 Contracts For industrial strength C/C++ For a subset of C Current enforcement entirely based Tailored for compile-time analysis vs. on runtime analysis May handle full functional Target critical problem areas specification void * foo(int *p) _Post_ _Notnull_ void * //@requires p != NULL; foo(_Pre_ _Notnull_ int *p) //@ensures \result != NULL; { … } { … } _Pre_satisfies_(p>q)   //@requires p>q; _Post_satisfies_(p>q)   //@ensures p>q; CMU, 11/30/2010 Jason Yang, Microsoft 8

  9. What do these functions do? void * memcpy( void *dest, const void *src, size_t count ); wchar_t *wmemcpy( wchar_t *dest, const wchar_t *src, size_t count ); CMU, 11/30/2010 Jason Yang, Microsoft 9

  10. CMU, 11/30/2010 Jason Yang, Microsoft 10

  11. CMU, 11/30/2010 Jason Yang, Microsoft 11

  12. For every buffer API there’s usually a wide version. Many errors are confusing “byte” vs. “element” counts. CMU, 11/30/2010 Jason Yang, Microsoft 12

  13. For every buffer API there’s usually a wide version. Many errors are confusing “byte” vs. “element” counts. Vital property for avoiding buffer overrun. CMU, 11/30/2010 Jason Yang, Microsoft 13

  14. SAL speak void * memcpy( _Out_writes_bytes_all_(count) void *dest, _In_reads_bytes_(count) const void *src, size_t count ); wchar_t *wmemcpy( _Out_writes_all_(count) wchar_t *dest, _In_reads_(count) const wchar_t *src, size_t count );  Captures programmer intent.  Improves defect detection via tools.  Extends language types to encode program logic properties. CMU, 11/30/2010 Jason Yang, Microsoft 14

  15. Precondition : function can assume p to be non-null when called. _Post_ _Notnull_ void * foo(_Pre_ _Notnull_ int *p); Postcondition : function must ensure the return value to be non-null. struct buf { int n; _Field_size_(n) int *data; }; Invariant : property that should be maintained. CMU, 11/30/2010 Jason Yang, Microsoft 15

  16. What : annotation specifies program property. Where : _At_ specifies annotation target. _At_(ptr, _When_(flag != 0, _Pre _Notnull_)) void Foo( int *ptr, int flag); When : _When_ specifies condition. CMU, 11/30/2010 Jason Yang, Microsoft 16

  17. Type Program Logic Types are used to describe Program logic describes the representation of a value transitions between program in a given program state. states. Enforced by compiler via type Programming errors can be vs. checking. detected by static analysis. Each execution step in a type- Types are often not descriptive safe imperative language enough to avoid errors preserves types, so types by because knowledge about themselves are sufficient to program logic is often implicit. establish a wide class of properties without the need for program logic. CMU, 11/30/2010 Jason Yang, Microsoft 17

  18. Memory cell semantics Memory allocated and can be written to but nothing is known about its contents, for unknown ? example the result of malloc() (that does not zero init the returned buffer) Object has a “well-formed” value: valid initialized + type specific invariants (if any) Memory is read-only read-only Buffer is null-terminated null-terminated ‘\0’ CMU, 11/30/2010 Jason Yang, Microsoft 18

  19. Legend Memory Cells Pointers null unknown state ? non-null maybe null valid p p p read-only x x null-terminated ‘\0’ (b) (c) (a) Diagram (a) abbreviates (b) or (c) CMU, 11/30/2010 Jason Yang, Microsoft 19

  20. Program state ‘a’ x 1 y 1 p CMU, 11/30/2010 Jason Yang, Microsoft 20

  21. Well-typed program state ‘a’ char x 1 int y 1 int *p CMU, 11/30/2010 Jason Yang, Microsoft 21

  22. Well-typed program state ‘a’ char x 1 int y int *p CMU, 11/30/2010 Jason Yang, Microsoft 22

  23. Well-typed program state ‘a’ char x 1 int y 1 int *p C type is not descriptive enough to avoid errors. CMU, 11/30/2010 Jason Yang, Microsoft 23

  24. Program state with qualified type ‘a’ char x 1 int y 1 _Notnull_ int *p Use SAL as a qualifier to be more precise! CMU, 11/30/2010 Jason Yang, Microsoft 24

  25. Qualified type is not always sufficient void foo(_Notnull_ _Writable_elements_(1) int *p) { *p = 1; } void foo(_Notnull_ _Valid_ void *p) { *p = 1; } Which one is right? Problem: types don’t capture state transitions! CMU, 11/30/2010 Jason Yang, Microsoft 25

  26. Pre/post conditions make up a contract _Notnull_ _Writable_elements_(1) int *p ? Precondition foo(&a); Postcondition _Notnull_ _Valid_ int *p 1 CMU, 11/30/2010 Jason Yang, Microsoft 26

  27. Contract for program logic void foo( _Pre_ _Notnull_ _Pre_ _Writable_elements_(1) _Post_ _Notnull_ _Post_ _Valid_ int *p) { *p = 1; } _Post_ _Notnull_ can be removed because C is call by value. CMU, 11/30/2010 Jason Yang, Microsoft 27

  28. Simplified, but still cumbersome to use! void foo( _Pre_ _Notnull_ _Pre_ _Writable_elements_(1) _Post_ _Valid_ int *p) { *p = 1; } CMU, 11/30/2010 Jason Yang, Microsoft 28

  29. C preprocessor macros to the rescue #define _Out_ \ _Pre_ _Notnull_ _Pre_ _Writable_elements_(1) \ _Post_ _Valid_ void foo(_Out_ int *p) { *p = 1; } See how simple the user-visible syntax is! CMU, 11/30/2010 Jason Yang, Microsoft 29

  30. Under the hood—two implementations #define _Out_ \ [SA_Pre(Null=SA_No, WritableElementsConst=1)] \ attributes [SA_Post(Valid=SA_Yes)] #define _Out_ \ __declspec("SAL_pre") __declspec("SAL_notnull") \ __declspec("SAL_pre") \ declspecs __declspec("SAL_writableTo(elementCount(1))") \ __declspec("SAL_post") __declspec("SAL_valid") Historically, there are some key differences between the two mechanisms. With the Visual Studio 2010 compiler, the gap is (almost) eliminated. A consistent user-visible language makes the choice transparent. CMU, 11/30/2010 Jason Yang, Microsoft 30

  31. validity Basic Properties const-ness _Valid_ _Const_ _Notvalid_ string termination buffer size null-ness _Null_terminated_ _Readable_elements_ _Null_ _NullNull_terminated_ _Writable_elements_ _Notnull_ _Readable_bytes_ _Maybenull_ _Writable_bytes_ Examples “Pointer ptr may not be null.” “String str is null terminated.” “Length of string str is stored in count. ” “Object obj is guarded by lock cs. ” CMU, 11/30/2010 Jason Yang, Microsoft 31

  32. Popular annotations in Windows SAL Count _In_ 1961906 _Out_ 381083 _In_opt_ 253496 _Inout_ 185008 _Outptr_ 99447 _In_reads_(size) 71217 _Out_opt_ 63749 _Out_writes_(size) 56330 _In_reads_bytes_(size) 43448 _Out_writes_bytes_(size) 19888 _Inout_opt_ 18845 _In_z_ 17932 _Inout_updates_(size) 14566 _Out_writes_opt_(size) 12701 _In_reads_opt_(size) 12247 _Outptr_result_maybenull_(size) 12054 _Outptr_result_buffer_(size) 9597 _In_reads_bytes_opt_(size) 9138 _Outptr_result_bytebuffer_(size) 7693 _Out_writes_bytes_opt_(size) 7667 _Outptr_opt_ 6231 _Out_writes_to_(size, count) 5498 CMU, 11/30/2010 Jason Yang, Microsoft 32

  33. Single element pointers _Inout_ T* p _In_ T* p _Out_ T* p p p p … … … … x ? … … x Pre Pre Pre Post Post Post p p p … … … … x x … … x’ CMU, 11/30/2010 Jason Yang, Microsoft 33

  34. Single element pointers that might be null _In_opt_ T* p _Out_opt_ T* p _Inout_opt_ T* p p p p … … … … … … x ? x Pre Pre Pre Post Post Post p p p … … … … … … x x x’ CMU, 11/30/2010 Jason Yang, Microsoft 34

Recommend


More recommend