Skip to content

Commit ff25070

Browse files
Merge pull request #4858 from TylerMSFT/github4487
fix SAL annotation
2 parents 998ef65 + 5db5c1e commit ff25070

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

docs/code-quality/best-practices-and-examples-sal.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
description: "Learn more about: Best practices and examples (SAL)"
33
title: Best practices and examples (SAL)
4-
ms.date: 01/27/2022
4+
ms.date: 03/30/2023
55
ms.topic: "conceptual"
66
---
77
# Best practices and examples (SAL)
@@ -10,7 +10,7 @@ Here are some ways to get the most out of the Source Code Annotation Language (S
1010

1111
## `_In_`
1212

13-
If the function is supposed to write to the element, use `_Inout_` instead of `_In_`. This is particularly relevant in cases of automated conversion from older macros to SAL. Prior to SAL, many programmers used macros as comments—macros that were named `IN`, `OUT`, `IN_OUT`, or variants of these names. Although we recommend that you convert these macros to SAL, we also urge you to be careful when you convert them because the code might have changed since the original prototype was written and the old macro might no longer reflect what the code does. Be especially careful about the `OPTIONAL` comment macro because it's frequently placed incorrectly—for example, on the wrong side of a comma.
13+
If the function is supposed to write to the element, use `_Inout_` instead of `_In_`. This is relevant in cases of automated conversion from older macros to SAL. Prior to SAL, many programmers used macros as comments—macros that were named `IN`, `OUT`, `IN_OUT`, or variants of these names. Although we recommend that you convert these macros to SAL, we also urge you to be careful when you convert them because the code might have changed since the original prototype was written and the old macro might no longer reflect what the code does. Be especially careful about the `OPTIONAL` comment macro because it's frequently placed incorrectly—for example, on the wrong side of a comma.
1414

1515
```cpp
1616
#include <sal.h>
@@ -25,7 +25,10 @@ void Func1(_In_ int *p1)
2525
}
2626

2727
// Correct
28-
void Func2(_Inout_ PCHAR p1)
28+
// _Out_opt_ because the function tolerates NULL as a valid argument, i.e.
29+
// no error is returned. If the function didn't check p1 for NULL, then
30+
// _Out_ would be the better choice
31+
void Func2(_Out_opt_ PCHAR p1)
2932
{
3033
if (p1 == NULL)
3134
return;
@@ -36,7 +39,7 @@ void Func2(_Inout_ PCHAR p1)
3639
3740
## `_opt_`
3841
39-
If the caller isn't allowed to pass in a null pointer, use `_In_` or `_Out_` instead of `_In_opt_` or `_Out_opt_`. This applies even to a function that checks its parameters and returns an error if it is `NULL` when it shouldn't be. Although having a function check its parameter for unexpected `NULL` and return gracefully is a good defensive coding practice, it doesn't mean that the parameter annotation can be of an optional type (`_*Xxx*_opt_`).
42+
If the caller isn't allowed to pass in a null pointer, use `_In_` or `_Out_` instead of `_In_opt_` or `_Out_opt_`. This applies even to a function that checks its parameters and returns an error if it's `NULL` when it shouldn't be. Although having a function check its parameter for unexpected `NULL` and return gracefully is a good defensive coding practice, it doesn't mean that the parameter annotation can be of an optional type (`_*Xxx*_opt_`).
4043
4144
```cpp
4245
#include <sal.h>
@@ -56,7 +59,7 @@ void Func2(_Out_ int *p1)
5659

5760
## `_Pre_defensive_` and `_Post_defensive_`
5861

59-
If a function appears at a trust boundary, we recommend that you use the `_Pre_defensive_` annotation. The "defensive" modifier modifies certain annotations to indicate that, at the point of call, the interface should be checked strictly, but in the implementation body it should assume that incorrect parameters might be passed. In that case, `_In_ _Pre_defensive_` is preferred at a trust boundary to indicate that although a caller will get an error if it attempts to pass `NULL`, the function body will be analyzed as if the parameter might be `NULL`, and any attempts to de-reference the pointer without first checking it for `NULL` will be flagged. A `_Post_defensive_` annotation is also available, for use in callbacks where the trusted party is assumed to be the caller and the untrusted code is the called code.
62+
If a function appears at a trust boundary, we recommend that you use the `_Pre_defensive_` annotation. The "defensive" modifier modifies certain annotations to indicate that, at the point of call, the interface should be checked strictly, but in the implementation body it should assume that incorrect parameters might be passed. In that case, `_In_ _Pre_defensive_` is preferred at a trust boundary to indicate that although a caller gets an error if it attempts to pass `NULL`, the function body is analyzed as if the parameter might be `NULL`, and any attempts to dereference the pointer without first checking it for `NULL` are flagged. A `_Post_defensive_` annotation is also available, for use in callbacks where the trusted party is assumed to be the caller and the untrusted code is the called code.
6063

6164
## `_Out_writes_`
6265

@@ -71,7 +74,7 @@ void Func1(_Out_writes_(size) CHAR *pb,
7174
);
7275
```
7376

74-
The annotation `_Out_writes_` signifies that you have a buffer. It has `cb` bytes allocated, with the first byte initialized on exit. This annotation isn't strictly wrong and it's helpful to express the allocated size. However, it doesn't tell how many elements are initialized by the function.
77+
The annotation `_Out_writes_` signifies that you have a buffer. It has `cb` bytes allocated, with the first byte initialized on exit. This annotation isn't strictly wrong and it's helpful to express the allocated size. However, it doesn't tell how many elements the function initializes.
7578

7679
The next example shows three correct ways to fully specify the exact size of the initialized portion of the buffer.
7780

@@ -204,7 +207,7 @@ BOOL WINAPI TryEnterCriticalSection(
204207

205208
## Reference variable
206209

207-
For a reference variable, the previous version of SAL used the implied pointer as the annotation target and required the addition of a `__deref` to annotations that attached to a reference variable. This version uses the object itself and doesn't require the additional `_Deref_`.
210+
For a reference variable, the previous version of SAL used the implied pointer as the annotation target and required the addition of a `__deref` to annotations that attached to a reference variable. This version uses the object itself and doesn't require `_Deref_`.
208211

209212
```cpp
210213
#include <sal.h>

0 commit comments

Comments
 (0)