Skip to content

Commit

Permalink
CA1311 and CA1421 (#32634)
Browse files Browse the repository at this point in the history
  • Loading branch information
gewarren authored Jan 9, 2023
1 parent a3e1476 commit 09edd79
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ Often, strings are converted to a standard case to enable easier lookup later. W

If a security decision is based on a case change operation, the operation should be culture-insensitive to ensure that the result is not affected by the value of `CultureInfo.CurrentCulture`. See the "String Comparisons that Use the Current Culture" section of the [Best Practices for Using Strings](../../standard/base-types/best-practices-strings.md) article for an example that demonstrates how culture-sensitive string operations can produce inconsistent results.

## Using the String.ToUpper and String.ToLower Methods
## String.ToUpper and String.ToLower

For code clarity, it is recommended that you always use overloads of the `String.ToUpper` and `String.ToLower` methods that allow you to specify a `culture` parameter explicitly. For example, the following code performs an identifier lookup. The `key.ToLower` operation is culture-sensitive by default, but this behavior is not clear from reading the code.
For code clarity, it's recommended that you always use overloads of the `String.ToUpper` and `String.ToLower` methods that let you specify a culture explicitly. For example, the following code performs an identifier lookup. The `key.ToLower` operation is culture-sensitive by default, but this behavior is not clear from reading the code.

### Example

Expand All @@ -44,7 +44,7 @@ static object LookupKey(string key)
}
```

If you want the `key.ToLower` operation to be culture-insensitive, you should change the preceding example as follows to explicitly use the `CultureInfo.InvariantCulture` when changing the case.
If you want the `key.ToLower` operation to be culture-insensitive, change the preceding example as follows to explicitly use `CultureInfo.InvariantCulture` when changing the case.

```vb
Shared Function LookupKey(key As String) As Object
Expand All @@ -59,15 +59,16 @@ static object LookupKey(string key)
}
```

## Using the Char.ToUpper and Char.ToLower Methods
## Char.ToUpper and Char.ToLower

Although the `Char.ToUpper` and `Char.ToLower` methods have the same characteristics as the `String.ToUpper` and `String.ToLower` methods, the only cultures that are affected are Turkish (Turkey) and Azerbaijani (Latin, Azerbaijan). These are the only two cultures with single-character casing differences. For more details about this unique case mapping, see the "Casing" section in the <xref:System.String> class topic. For code clarity and to ensure consistent results, it is recommended that you always use the overloads of these methods that allow you to explicitly specify a `culture` parameter.
Although the `Char.ToUpper` and `Char.ToLower` methods have the same characteristics as the `String.ToUpper` and `String.ToLower` methods, the only cultures that are affected are Turkish (Turkey) and Azerbaijani (Latin, Azerbaijan). These are the only two cultures with single-character casing differences. For more details about this unique case mapping, see the "Casing" section in the <xref:System.String> class documentation. For code clarity and to ensure consistent results, it's recommended that you always use the overloads of these methods that accept a <xref:System.Globalization.CultureInfo> parameter.

## See also

- <xref:System.String.ToUpper%2A?displayProperty=nameWithType>
- <xref:System.String.ToLower%2A?displayProperty=nameWithType>
- <xref:System.Char.ToUpper%2A?displayProperty=nameWithType>
- <xref:System.Char.ToLower%2A?displayProperty=nameWithType>
- [CA1311: Specify a culture or use an invariant version](../../fundamentals/code-analysis/quality-rules/ca1311.md)
- [Change case in .NET](../../standard/base-types/changing-case.md)
- [Perform culture-insensitive string operations](performing-culture-insensitive-string-operations.md)
93 changes: 93 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca1311.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: "CA1311: Specify a culture or use an invariant version (code analysis)"
description: "Learn about code analysis rule CA1311: Specify a culture or use an invariant version"
ms.date: 11/16/2022
ms.topic: reference
f1_keywords:
- CA1311
- SpecifyCultureForToLowerAndToUpper
helpviewer_keywords:
- CA1311
dev_langs:
- CSharp
- VB
---
# CA1311: Specify a culture or use an invariant version

| | Value |
| ----------------------------------- | ------------------------------------------ |
| **Rule ID** | CA1311 |
| **Category** | [Globalization](globalization-warnings.md) |
| **Fix is breaking or non-breaking** | Non-breaking |

## Cause

A call is made to <xref:System.String.ToUpper?displayProperty=nameWithType> or <xref:System.String.ToLower?displayProperty=nameWithType> without specifying a culture.

## Rule description

Specify a culture or use an invariant culture to avoid implicit dependency on the current culture when calling `ToUpper` or `ToLower`. Using an invariant culture yields consistent results regardless of the culture of an application.

## How to fix violations

Instead of calling the parameterless <xref:System.String.ToUpper?displayProperty=nameWithType> or <xref:System.String.ToLower?displayProperty=nameWithType> methods, call <xref:System.String.ToUpper(System.Globalization.CultureInfo)> or <xref:System.String.ToUpperInvariant>, or <xref:System.String.ToLower(System.Globalization.CultureInfo)> or <xref:System.String.ToLowerInvariant>.

## Example

The following code snippet shows a violation of rule CA1311:

```csharp
string s = "hello";
s = s.ToLower();
```

```vb
Dim s As String = "hello"
s.ToLower()
```

The following code snippet fixes the violation:

```csharp
string s = "hello";
s = s.ToLowerInvariant();
```

```vb
Dim s As String = "hello"
s.ToLowerInvariant()
```

## When to suppress warnings

It's safe to suppress a warning from this rule if you're certain that <xref:System.Threading.Thread.CurrentCulture%2A?displayProperty=nameWithType> will never change.

## Suppress a warning

If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

```csharp
#pragma warning disable CA1311
// The code that's violating the rule is on this line.
#pragma warning restore CA1311
```

To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md).

```ini
[*.{cs,vb}]
dotnet_diagnostic.CA1311.severity = none
```

To disable this entire category of rules, set the severity for the category to `none` in the [configuration file](../configuration-files.md).

```ini
[*.{cs,vb}]
dotnet_analyzer_diagnostic.category-Globalization.severity = none
```

For more information, see [How to suppress code analysis warnings](../suppress-warnings.md).

## See also

- [Perform culture-insensitive case changes](../../../core/extensions/performing-culture-insensitive-case-changes.md)
46 changes: 46 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca1421.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: "CA1421: Method uses runtime marshalling when 'DisableRuntimeMarshallingAttribute' is applied"
description: "Learn about code analysis rule CA1421: Method uses runtime marshalling when 'DisableRuntimeMarshallingAttribute' is applied"
ms.date: 11/16/2022
ms.topic: reference
f1_keywords:
- CA1421
- MethodUsesRuntimeMarshallingEvenWhenMarshallingDisabled
helpviewer_keywords:
- CA1421
dev_langs:
- CSharp
- VB
---
# CA1421: Method uses runtime marshalling when DisableRuntimeMarshallingAttribute is applied

| | Value |
| ----------------------------------- | ------------------------------------------------ |
| **Rule ID** | CA1421 |
| **Category** | [Interoperability](interoperability-warnings.md) |
| **Fix is breaking or non-breaking** | Non-breaking |

## Cause

A method uses runtime marshalling, and runtime marshalling is explicitly disabled.

## Rule description

If a method uses runtime marshalling when runtime marshalling is disabled, it can cause unexpected behavior differences at run time due to different expectations of a type's native layout.

## How to fix violations

Enable runtime marshalling or use features like `sizeof` and pointers to ensure accurate results.

## When to suppress warnings

Don't suppress a warning from this rule.

## Example

The following code snippet shows a violation of CA1421:

:::code language="csharp" source="snippets/csharp/extra-rules/ca1421.cs":::
:::code language="vb" source="snippets/vb/extra-rules/ca1421.vb":::

To fix the violation, remove the <xref:System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute> attribute on the assembly.
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ Globalization rules support world-ready libraries and applications.
|[CA1308: Normalize strings to uppercase](ca1308.md)|Strings should be normalized to uppercase. A small group of characters cannot make a round trip when they are converted to lowercase.|
|[CA1309: Use ordinal StringComparison](ca1309.md)|A string comparison operation that is nonlinguistic does not set the StringComparison parameter to either Ordinal or OrdinalIgnoreCase. By explicitly setting the parameter to either StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase, your code often gains speed, becomes more correct, and becomes more reliable.|
|[CA1310: Specify StringComparison for correctness](ca1310.md)|A string comparison operation uses a method overload that does not set a StringComparison parameter and uses culture-specific string comparison by default.|
|[CA1311: Specify a culture or use an invariant version](ca1311.md)|Specify a culture or use an invariant culture to avoid implicit dependency on the current culture when calling `ToUpper` or `ToLower`.|
|[CA2101: Specify marshalling for P/Invoke string arguments](ca2101.md)|A platform invoke member allows for partially trusted callers, has a string parameter, and does not explicitly marshal the string. This can cause a potential security vulnerability.|
2 changes: 2 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@ The following table lists code quality analysis rules.
> | [CA1308: Normalize strings to uppercase](ca1308.md) | Strings should be normalized to uppercase. A small group of characters cannot make a round trip when they are converted to lowercase. |
> | [CA1309: Use ordinal StringComparison](ca1309.md) | A string comparison operation that is nonlinguistic does not set the StringComparison parameter to either Ordinal or OrdinalIgnoreCase. By explicitly setting the parameter to either StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase, your code often gains speed, becomes more correct, and becomes more reliable. |
> | [CA1310: Specify StringComparison for correctness](ca1310.md) | A string comparison operation uses a method overload that does not set a StringComparison parameter and uses culture-specific string comparison by default. |
> | [CA1311: Specify a culture or use an invariant version](ca1311.md) | Specify a culture or use an invariant culture to avoid implicit dependency on the current culture when calling `ToUpper` or `ToLower`. |
> | [CA1401: P/Invokes should not be visible](ca1401.md) | A public or protected method in a public type has the System.Runtime.InteropServices.DllImportAttribute attribute (also implemented by the Declare keyword in Visual Basic). Such methods should not be exposed. |
> | [CA1416: Validate platform compatibility](ca1416.md) | Using platform-dependent APIs on a component makes the code no longer work across all platforms. |
> | [CA1417: Do not use `OutAttribute` on string parameters for P/Invokes](ca1417.md) | String parameters passed by value with the `OutAttribute` can destabilize the runtime if the string is an interned string. |
> | [CA1418: Use valid platform string](ca1418.md) | Platform compatibility analyzer requires a valid platform name and version. |
> | [CA1419: Provide a parameterless constructor that is as visible as the containing type for concrete types derived from 'System.Runtime.InteropServices.SafeHandle'](ca1419.md) | Providing a parameterless constructor that is as visible as the containing type for a type derived from `System.Runtime.InteropServices.SafeHandle` enables better performance and usage with source-generated interop solutions. |
> | [CA1420: Property, type, or attribute requires runtime marshalling](ca1420.md) | Using features that require runtime marshalling when runtime marshalling is disabled will result in run-time exceptions. |
> | [CA1421: Method uses runtime marshalling when DisableRuntimeMarshallingAttribute is applied](ca1421.md) | A method uses runtime marshalling, and runtime marshalling is explicitly disabled. |
> | [CA1422: Validate platform compatibility](ca1422.md) | Calling an API that's obsolete in a given OS (version) from a call site that's reachable from that OS (version) is not recommended. |
> | [CA1501: Avoid excessive inheritance](ca1501.md) | A type is more than four levels deep in its inheritance hierarchy. Deeply nested type hierarchies can be difficult to follow, understand, and maintain. |
> | [CA1502: Avoid excessive complexity](ca1502.md) | This rule measures the number of linearly independent paths through the method, which is determined by the number and complexity of conditional branches. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ Portability rules support portability across different platforms. Interoperabili
| [CA1418: Use valid platform string](ca1418.md) | Platform compatibility analyzer requires a valid platform name and version. |
| [CA1419: Provide a parameterless constructor that is as visible as the containing type for concrete types derived from 'System.Runtime.InteropServices.SafeHandle'](ca1419.md) | Providing a parameterless constructor that is as visible as the containing type for a type derived from `System.Runtime.InteropServices.SafeHandle` enables better performance and usage with source-generated interop solutions. |
| [CA1420: Property, type, or attribute requires runtime marshalling](ca1420.md) | Using features that require runtime marshalling when runtime marshalling is disabled will result in run-time exceptions. |
| [CA1421: Method uses runtime marshalling when DisableRuntimeMarshallingAttribute is applied](ca1421.md) | A method uses runtime marshalling, and runtime marshalling is explicitly disabled. |
| [CA1422: Validate platform compatibility](ca1422.md) | Calling an API that's obsolete in a given OS (version) from a call site that's reachable from that OS (version) is not recommended. |
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: DisableRuntimeMarshalling]

class C
{
public void Test()
{
nint offset = Marshal.OffsetOf(typeof(ValueType), "field");
}
}

struct ValueType
{
int field;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>extra_rules</RootNamespace>
</PropertyGroup>

</Project>

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices

<Assembly: DisableRuntimeMarshalling>

Class C
Shared Sub S1()
Dim offset As IntPtr = Marshal.OffsetOf(GetType(ValueType), "field")
End Sub
End Class

Structure ValueType
Dim field As Integer
End Structure
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>extra_rules</RootNamespace>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>

</Project>

4 changes: 4 additions & 0 deletions docs/fundamentals/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,8 @@ items:
href: code-analysis/quality-rules/ca1309.md
- name: CA1310
href: code-analysis/quality-rules/ca1310.md
- name: CA1311
href: code-analysis/quality-rules/ca1311.md
- name: CA2101
href: code-analysis/quality-rules/ca2101.md
- name: Portability and interoperability rules
Expand All @@ -1024,6 +1026,8 @@ items:
href: code-analysis/quality-rules/ca1419.md
- name: CA1420
href: code-analysis/quality-rules/ca1420.md
- name: CA1421
href: code-analysis/quality-rules/ca1421.md
- name: CA1422
href: code-analysis/quality-rules/ca1422.md
- name: Maintainability rules
Expand Down

0 comments on commit 09edd79

Please sign in to comment.