Skip to content

Commit a3a8ad1

Browse files
Merge pull request #4430 from MicrosoftDocs/main638126875866646577sync_temp
For protected CLA branch, push strategy should use PR and merge to target branch method to work around git push error
2 parents 5c139f2 + 7cdd53f commit a3a8ad1

File tree

7 files changed

+194
-95
lines changed

7 files changed

+194
-95
lines changed

docs/code-quality/c26441.md

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,58 @@
11
---
22
description: "Learn more about: Warning C26441 NO_UNNAMED_GUARDS"
33
title: Warning C26441
4-
ms.date: 11/15/2017
4+
ms.date: 2/7/2023
55
f1_keywords: ["C26441", "NO_UNNAMED_GUARDS"]
66
helpviewer_keywords: ["C26441"]
7-
ms.assetid: f923c422-ed01-4644-b40b-93f15fc5bb93
87
---
98
# Warning C26441
109

1110
> Guard objects must be named (cp.44)
1211
13-
**C++ Core Guidelines**:
14-
[CP.44](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#cp44-remember-to-name-your-lock_guards-and-unique_locks): Remember to name your lock_guards and unique_locks
12+
## C++ Core Guidelines
1513

16-
The standard library provides a few useful classes that help to control concurrent access to resources. Objects of such types lock exclusive access during their lifetime. Lifetime management implies that every lock object must be named. That is, it must have a clearly defined lifetime that spans through the period in which access operations are executed. So, failing to assign a lock object to a variable is a mistake that effectively disables the locking mechanism (because temporary variables are transient). This rule tries to catch simple cases of such unintended behavior.
14+
[CP.44](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cp44-remember-to-name-your-lock_guards-and-unique_locks): Remember to name your `lock_guard`s and `unique_lock`s
1715

1816
## Remarks
1917

20-
- Only standard lock types are tracked: `std::scoped_lock`, `std::unique_lock`, and `std::lock_quard`.
18+
The standard library provides locks to help control concurrent access to resources during their lifetime. When you declare a lock object without a name, the compiler creates a temporary object that's immediately destructed rather than one that lives to the end of the enclosing scope. So, failure to assign a lock object to a variable is a mistake that effectively disables the locking mechanism (because temporary variables are transient). This rule catches simple cases of such unintended behavior.
2119

22-
- Only simple calls to constructors are analyzed. More complex initializer expressions may lead to inaccurate results, but it's an unusual scenario.
20+
This diagnostic only analyzes the standard lock types `std::scoped_lock`, `std::unique_lock`, and `std::lock_guard`. Warning [C26444](c26444.md) covers other unnamed RAII types.
2321

24-
- Locks passed as arguments to function calls or returned as results of function calls are ignored.
25-
26-
- Locks created as temporaries but assigned to named references to extend their lifetime are ignored.
22+
The analyzer only analyzes simple calls to constructors. More complex initializer expressions may lead to inaccurate results in the form of missed warnings. Locks passed as arguments to function calls or returned as results of function calls are ignored because the analysis tool is unable to determine if those locks are deliberately trying to protect that function call or if they should be extended. To provide similar protection for types returned by a function call, annotate them with `[[nodiscard]]`. The analyzer ignores locks created as temporaries but assigned to named references to extend their lifetime.
2723

2824
Code analysis name: `NO_UNNAMED_GUARDS`
2925

3026
## Example
3127

32-
Missing scoped variable:
28+
In this example the name of the scoped lock is missing.
3329

3430
```cpp
35-
void print_diagnostic(gsl::string_span<> text)
31+
void print_diagnostic(std::string_view text)
3632
{
3733
auto stream = get_diagnostic_stream();
3834
if (stream)
3935
{
4036
std::lock_guard<std::mutex>{ diagnostic_mutex_ }; // C26441
4137
write_line(stream, text);
42-
// ...
4338
}
4439
}
4540
```
4641
47-
Missing scoped variable, corrected:
42+
To fix the error, give a name to the lock, which extends its lifetime.
4843
4944
```cpp
50-
void print_diagnostic(gsl::string_span<> text)
45+
void print_diagnostic(std::string_view text)
5146
{
5247
auto stream = get_diagnostic_stream();
5348
if (stream)
5449
{
5550
std::lock_guard<std::mutex> lock{ diagnostic_mutex_ };
5651
write_line(stream, text);
57-
// ...
5852
}
5953
}
6054
```
55+
56+
## See also
57+
58+
[C26444](C26444.md)

docs/code-quality/c28213.md

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,72 @@
11
---
22
description: "Learn more about: Warning C28213"
33
title: Warning C28213
4-
ms.date: 09/08/2022
4+
ms.date: 02/07/2023
55
f1_keywords: ["C28213", "BAD_USEHEADER", "__WARNING_BAD_USEHEADER"]
66
helpviewer_keywords: ["C28213"]
7-
ms.assetid: e141a12a-4c46-47eb-aa9d-a6444472cfaa
87
---
98
# Warning C28213
109

1110
> The `_Use_decl_annotations_` annotation must be used to reference, without modification, a prior declaration.
1211
1312
## Remarks
1413

15-
`_Use_decl_annotations_` tells the compiler to use the annotations from an earlier declaration of the function. If no earlier declaration can be found, or if the current declaration makes changes to the annotations, then this warning is emitted.
14+
`_Use_decl_annotations_` tells the compiler to use the annotations from an earlier declaration of the function. If it can't find an earlier declaration, or if the current declaration makes changes to the annotations, it emits this warning. `_Use_decl_annotations_` also lets you remove all other annotations from the definition, and uses the declaration annotations for analysis of the function.
1615

17-
Code analysis name: BAD_USEHEADER
16+
This diagnostic is frequently a side effect of refactoring or fixing other warnings by adjusting the annotations on a function. To fix the issue, use the same annotations at the other locations. To determine the correct set of annotations, look at the behavior in the function definition. In most cases, this behavior is intentional and the annotations to the function should reflect it. For more information on SAL annotations, see [Using SAL Annotations to reduce code defects](using-sal-annotations-to-reduce-c-cpp-code-defects.md).
1817

19-
## Example
18+
It's important for the annotations to match between the declarations and the definition of a function. When the analysis tools analyze the call site of the function, they use the declaration annotations. If the declaration and definition don't match, the static analysis tools may produce incorrect results. When you fix this warning, it's common for your changes to have cascading effects as the tool reanalyzes the source with updated information.
19+
20+
If this diagnostic occurs because the analyzer couldn't find a previous declaration in the translation unit, the most likely cause is a missing `#include` directive. To resolve this issue when you intentionally don't include the header file, verify that the annotations in the declaration and definition match, and remove the `_Use_decl_annotations_` annotation. Be careful when you don't include a header file, as the two sets of annotations may get out of sync in the future.
21+
22+
Code analysis name: `BAD_USEHEADER`
23+
24+
## Examples
2025

2126
The following code generates C28160. The `buffer` parameter annotation doesn't match between the two files.
2227

2328
*From example.h:*
2429

2530
```cpp
26-
void example_func(_Out_writes_(n) char* buffer, int n);
31+
void addNullTerminate(_Out_writes_(n) char* buffer, int n);
2732
```
2833
2934
*From example.cpp:*
3035
3136
```cpp
3237
_Use_decl_annotations_
33-
void example_func(_Out_writes_z_(n) char* buffer, int n)
38+
void addNullTerminate(_Out_writes_z_(n) char* buffer, int n)
3439
{
3540
buffer[n] = '\0';
3641
}
3742
```
3843

39-
This issue can be fixed by either changing the annotation so they match at all locations, or by removing all annotations except `_Use_decl_annotations_` from the function definition. In this example, `_Out_writes_z_` appears to be correct so we'll move that to the function declaration in the header file. The following code resolves this warning:
44+
Examine the function definition to determine what the correct annotations should be. In this case, `_Out_writes_z_(n)` appears to be correct, so we move that annotation to the function declaration in the header file. This change resolves the issue because the annotations in the declaration and definition now match.
4045

4146
*From example.h:*
4247

4348
```cpp
44-
void example_func(_Out_writes_z_(n) char* buffer, int n);
49+
void addNullTerminate(_Out_writes_z_(n) char* buffer, int n);
4550
```
4651
52+
Now we can remove the buffer annotation on the definition to simplify future maintenance (although this step is optional).
53+
4754
*From example.cpp:*
4855
4956
```cpp
5057
_Use_decl_annotations_
51-
void example_func(_Out_writes_z_(n) char* buffer, int n)
58+
void addNullTerminate(char* buffer, int n)
5259
{
5360
buffer[n] = '\0';
5461
}
5562
```
63+
64+
In real world code, it's not usually as clear which annotation is correct. For more information and guidance, see [using SAL Annotations to reduce code defects](using-sal-annotations-to-reduce-c-cpp-code-defects.md).
65+
66+
## See also
67+
68+
[Rule sets for C++ code](./using-rule-sets-to-specify-the-cpp-rules-to-run.md)\
69+
[Using SAL Annotations to reduce code defects](using-sal-annotations-to-reduce-c-cpp-code-defects.md)\
70+
[C28252](C28252.md)\
71+
[C28253](C28253.md)\
72+
[C28301](C28301.md)

docs/code-quality/c6029.md

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,92 @@
11
---
22
description: "Learn more about: Warning C6029"
33
title: Warning C6029
4-
ms.date: 10/04/2022
4+
ms.date: 2/07/2023
55
f1_keywords: ["C6029", "USING_TAINTED_DATA", "__WARNING_USING_TAINTED_DATA"]
66
helpviewer_keywords: ["C6029"]
7-
ms.assetid: 07f89261-1b77-4597-9f34-12ce5d569b60
87
---
98
# Warning C6029
109

11-
> Possible buffer overrun in call to '*function*': use of unchecked value
10+
> Possible buffer overrun in call to '*function*'
1211
13-
## Remarks
12+
Possible buffer overrun in called function due to an unchecked buffer length/size parameter.
1413

15-
This warning indicates that a function that takes a buffer and a size is being passed an unchecked size. The data read-in from some external source hasn't been verified to see whether it's smaller than the buffer size. An attacker might intentionally specify a much larger than expected value for the size, which will lead to a buffer overrun.
14+
## Remarks
1615

17-
Generally, whenever you read data from an untrusted external source, make sure to verify it for validity. It's appropriate to verify the size to make sure it's in the expected range.
16+
This warning indicates that code passes an unchecked size to a function that takes a buffer and a size. The code doesn't verify that the data read from some external source is smaller than the buffer size. An attacker might intentionally specify a larger than expected value for the size, which can lead to a buffer overrun. Generally, whenever you read data from an untrusted external source, make sure to verify it for validity. It's appropriate to verify the size to make sure it's in the expected range.
1817

1918
Code analysis name: `USING_TAINTED_DATA`
2019

2120
## Example
2221

23-
The following code generates this warning by calling the annotated function [`ReadFile`](/windows/desktop/api/fileapi/nf-fileapi-readfile) two times. After the first call, the Post attribute property marks the second parameter value untrusted. Therefore, passing an untrusted value in the second call to `ReadFile` generates this warning as shown in the following code:
22+
The following code generates this warning when it calls the annotated function `std::fread` two times. The code uses the first call to determine the length of the data to read in later calls. After the first call, analysis marks `dataSize` as coming from an untrusted source. Therefore, when the code passes the untrusted value to the second `std::fread` call, the analyzer generates this warning. A malicious actor could modify the file and cause the call to `std::fread` to overflow the `buffer` array. In real world code, you should also handle error recovery based on the return value of `std::fread`. For simplicity, these examples intentionally leave out error recovery code.
2423

2524
```cpp
26-
#include "windows.h"
25+
void processData(FILE* file)
26+
{
27+
const size_t MAX_BUFFER_SIZE = 100;
28+
uint32_t buffer[MAX_BUFFER_SIZE]{};
29+
uint8_t dataSize = 0;
30+
31+
// Read length data from the beginning of the file
32+
fread(&dataSize, sizeof(uint8_t), 1, file);
33+
// Read the rest of the data based on the dataSize
34+
fread(buffer, sizeof(uint32_t), dataSize, file);
35+
}
36+
```
2737
28-
bool f(HANDLE hFile)
38+
The fix for the issue depends on the nature of the data and the behavior of the annotated function that triggers the diagnostic. For more information, see the documentation for that function. A straightforward fix is to check the size before the second call to `std:fread`. In the next example, we throw an exception to terminate the function. Most real-world code would instead have an error recovery strategy that's specific to the scenario.
39+
40+
```cpp
41+
void processData(FILE* file)
2942
{
30-
char buff[MAX_PATH];
43+
const size_t MAX_BUFFER_SIZE = 100;
44+
uint32_t buffer[MAX_BUFFER_SIZE]{};
45+
uint8_t dataSize = 0;
3146
32-
DWORD cbLen;
33-
DWORD cbRead;
47+
fread(&dataSize, sizeof(uint32_t), 1, file);
3448
35-
// Read the number of byte to read (cbLen).
36-
if (!ReadFile (hFile, &cbLen, sizeof (cbLen), &cbRead, NULL))
37-
{
38-
return false;
39-
}
40-
// Read the bytes
41-
if (!ReadFile (hFile, buff, cbLen, &cbRead, NULL)) // warning C6029
49+
if (dataSize > MAX_BUFFER_SIZE)
4250
{
43-
return false;
51+
throw std::runtime_error("file data unexpected size");
4452
}
4553
46-
return true;
54+
fread(buffer, sizeof(uint32_t), dataSize, file);
4755
}
4856
```
4957

50-
To correct this warning, check the buffer size as shown in the following code:
58+
In `std:fread` and similar functions, the code may need to read large amounts of data. To handle large data, you can allocate the size of the buffer dynamically after the size becomes known. Or, you can call `std:fread` multiple times as needed to read in the rest of the data. If you allocate the buffer dynamically, we recommend you put a limit on the size to avoid introducing an out-of-memory exploit for large values. We don't use this approach in our example because it's already bounded by the size of `uint8_t`.
5159

5260
```cpp
53-
bool f(HANDLE hFile)
61+
void processDataDynamic(FILE* file)
5462
{
55-
char buff[MAX_PATH];
63+
uint8_t dataSize = 0;
64+
fread(&dataSize, sizeof(uint8_t), 1, file);
65+
66+
// Vector with `dataSize` default initialized objects
67+
std::vector<uint32_t> vecBuffer(dataSize);
5668

57-
DWORD cbLen;
58-
DWORD cbRead;
69+
fread(&vecBuffer[0], sizeof(uint32_t), dataSize, file);
70+
}
71+
void processDataMultiple(FILE* file)
72+
{
73+
const size_t MAX_BUFFER_SIZE = 100;
74+
uint32_t buffer[MAX_BUFFER_SIZE]{};
75+
uint8_t dataSize = 0;
5976

60-
// Read the number of byte to read (cbLen).
61-
if (!ReadFile (hFile, &cbLen, sizeof (cbLen), &cbRead, NULL))
62-
{
63-
return false;
64-
}
65-
// Ensure that there's enough space in the buffer to read that many bytes.
66-
if (cbLen > sizeof(buff))
67-
{
68-
return false;
69-
}
70-
// Read the bytes
71-
if (!ReadFile (hFile, buff, cbLen, &cbRead, NULL)) // warning C6029
77+
fread(&dataSize, sizeof(uint32_t), 1, file);
78+
79+
while( dataSize > 0 )
7280
{
73-
return false;
81+
size_t readSize = dataSize > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : dataSize;
82+
readSize = fread(buffer, sizeof(uint32_t), readSize, file);
83+
dataSize = dataSize - readSize;
84+
// Process the data in `buffer`...
7485
}
75-
76-
return true;
7786
}
7887
```
7988
8089
## See also
8190
82-
- [Using SAL Annotations to reduce code defects](using-sal-annotations-to-reduce-c-cpp-code-defects.md)
91+
[Rule sets for C++ code](./using-rule-sets-to-specify-the-cpp-rules-to-run.md)\
92+
[Using SAL Annotations to reduce code defects](using-sal-annotations-to-reduce-c-cpp-code-defects.md)

docs/code-quality/c6064.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
---
22
description: "Learn more about: Warning C6064"
33
title: Warning C6064
4-
ms.date: 10/03/2022
4+
ms.date: 2/07/2023
55
f1_keywords: ["C6064", "MISSING_INTEGER_ARGUMENT_TO_FORMAT_FUNCTION", "__WARNING_MISSING_INTEGER_ARGUMENT_TO_FORMAT_FUNCTION"]
66
helpviewer_keywords: ["C6064"]
7-
ms.assetid: d8f126aa-b093-440e-820f-65b8e6cffaba
87
---
98
# Warning C6064
109

1110
> Missing integer argument to '*function-name*' corresponding to conversion specifier '*number*'
1211
13-
This warning indicates that not enough arguments are provided to match a format string and one of the missing arguments is an integer.
12+
This warning indicates that the code doesn't provide enough arguments to match a format string and one of the missing arguments is an integer.
1413

1514
## Remarks
1615

@@ -20,13 +19,13 @@ Code analysis name: `MISSING_INTEGER_ARGUMENT_TO_FORMAT_FUNCTION`
2019

2120
## Example
2221

23-
The following code generates this warning because an incorrect number of arguments were used in the call to `sprintf_s` and the missing argument was an integer. If the unsafe function `sprintf` was used instead of the safer variant `sprintf_s`, this code would likely cause a stack overflow instead of just an unexpected output:
22+
The following code generates this warning because it uses an incorrect number of arguments in the call to `sprintf_s` and the missing argument is an integer. If the unsafe function `sprintf` was used instead of the safer variant `sprintf_s`, this code would likely cause a stack overflow instead of just an unexpected output:
2423

2524
```cpp
2625
void f()
2726
{
2827
char buff[8];
29-
char *string="Hello";
28+
const char *string="Hello";
3029
sprintf_s(buff, sizeof(buff), "%s %d", string); // Attempts to print "Hello "
3130
// followed by a number up to eleven characters long, depending on the garbage
3231
// found on the stack. Any number other than a single non-negative digit can't
@@ -35,17 +34,18 @@ void f()
3534
}
3635
```
3736

38-
To correct this warning, specify missing arguments as shown in the following code:
37+
To correct this warning, specify missing arguments or adjust the format string. In this example, we add the missing integer value.
3938

4039
```cpp
4140
void f()
4241
{
4342
char buff[8];
44-
char *string = "Hello";
43+
const char *string = "Hello";
4544
sprintf_s(buff, sizeof(buff), "%s %d", string, strlen(string));
4645
}
4746
```
4847

4948
## See also
5049

51-
[`sprintf_s`, `_sprintf_s_l`, `swprintf_s`, `_swprintf_s_l`](../c-runtime-library/reference/sprintf-s-sprintf-s-l-swprintf-s-swprintf-s-l.md)
50+
[`sprintf_s`, `_sprintf_s_l`, `swprintf_s`, `_swprintf_s_l`](../c-runtime-library/reference/sprintf-s-sprintf-s-l-swprintf-s-swprintf-s-l.md)\
51+
[C4473](../error-messages/compiler-warnings/c4473.md)

0 commit comments

Comments
 (0)