As asked in the title:
What is the purpose of SAL (Source Annotation Language) and what is the difference between SAL 1 and SAL 2?
I understand the basics of the usage, and that is serves to highlight the purpose of each of the variables passed to functions along with various other things for static code analysis, but how much difference does it actually make (ignoring increasing clarity of parameter requirements for other programmers on the project)?
If I was to have the following prototype:
_Success_(return == 1)
int TestFunction( _In_ int* pTest, _Inopt_ char* pOptional );
This is supposed to "tell" the static analyser that the function will return 1 upon it's successful operation, that pTest
is a pointer which must not be nullptr
and that pOptional
is a pointer which may or may not be nullptr
. However, can't the static analyser get this information from the function definition itself? Moreover, what does it do with the information it gets such as the success criteria?
Furthermore, why is there a difference between SAL 1 and SAL 2, why did microsoft decide to change the way they named their macros (i.e. from __out
to _Out_
and __success
to _Success_
?)
I'm sorry if this is described somewhere in detail on the MSDN but I was unable to find it or any other question on StackOverflow with a detailed answer so I thought I'd ask in the hopes of having my curiosity satisfied.
Thanks in advance for your time!
I read multiple questions in your question, hopefully I got them all:
Why use SAL and not just deduce from source?
There are multiple answers as to the point of explicitly telling the analyzer details about parameter behavior, etc., with SAL.
Although an analyzer can deduce parameter behavior from the implementation, it often can't tell the difference between intent and accidents of implementation. As a developer, if you explicitly state the intended purpose of different parameters, the analyzer can both validate that you wrote an implementation that fulfilled your intent and also that callers are using it correctly.
This gives static analyzers information about function behavior when the source code isn't available to analyze, for instance the functions declared in various header files shipped as part of Visual Studio, driver kits, etc.
SAL allows expression of concepts that are difficult to impossible to deduce from source code only, such as lock usage and IRQL requirements in drivers.
This also assists in consistency with callback functions. Some frameworks described by the Windows headers may declare a set of callback functions, so the Windows framework will call those callback functions defined elsewhere (applications, drivers, etc.). So Windows never sees the source for the called functions, and the callback function definitions never see the callers.
What information does the analyzer get from Success?
This is not really relevant in the case you wrote. However in cases where there are output parameters (e.g. Out and family), it means that if the function does not succeed, the caller cannot rely on the output annotations. So for instance:
_Success_(return) bool GetASmallInt(_Out_range_(0, 10) int& an_int);
If GetASmallInt returns true, an_int will be between 0 and 10, inclusive. If it returns false, no such guarantee exists, and the variable may not even have been initialized by the function.
What is the difference between SAL 1 and SAL 2 and why were the annotations renamed from __in
to _In_
?
Some corner cases in the original definition of SAL (e.g. __in) didn't mesh with C++ well. The new syntax started off with some newer implementation that made sure it would be consistent with the requirements of both the C and C++ grammars.
The main difference between SAL 1 and SAL 2 has to do with SAL 2 being able to express a lot of concepts that SAL 1 cannot, and SAL 2 is better defined, especially with respect to C++, as noted above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With