Unicorn with delicious cookie
Nous utilisons des cookies pour améliorer votre expérience de navigation. En savoir plus
Accepter
to the top
>
>
>
V5629. Code contains invisible characte…
menu mobile close menu
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Micro-Optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C++)
OWASP errors (C#)
OWASP errors (Java)
Problems related to code analyzer
Additional information
toggle menu Contents

V5629. Code contains invisible characters that may alter its logic. Consider enabling the display of invisible characters in the code editor.

20 Mar 2025

The analyzer has detected characters in code that may confuse a developer. These characters can be invisible and change the way the code is displayed in IDEs. Combinations of such characters can cause a human and a compiler to interpret the code differently.

This can be done on purpose. This type of attack is called Trojan Source. Follow the links to learn more:

Character

Code

Definition

Description

LRE

U+202A

LEFT-TO-RIGHT EMBEDDING

The text after the LRE character is interpreted as embedded and displayed left-to-right. The LRE action is interrupted by the PDF character or a line break.

RLE

U+202B

RIGHT-TO-LEFT EMBEDDING

The text after the RLE character is interpreted as embedded and displayed right-to-left. The RLE action is interrupted by the PDF character or a line break.

LRO

U+202D

LEFT-TO-RIGHT OVERRIDE

The text after the LRO character is forcibly displayed left-to-right. The LRO action is interrupted by the PDF character or a line break.

RLO

U+202E

RIGHT-TO-LEFT OVERRIDE

The text after the LRO character is forcibly displayed right-to-left. The LRO action is interrupted by the PDF character or a line break.

PDF

U+202C

POP DIRECTIONAL FORMATTING

The PDF character interrupts one of the LRE, RLE, LRO, or RLO characters encountered earlier. It interrupts exactly one last encountered character.

LRI

U+2066

LEFT‑TO‑RIGHT ISOLATE

The text after the LRI character is displayed left-to-right and interpreted as isolated. This means that other control characters do not affect the display of this text fragment. The LRI action is interrupted by the PDI character or a line break.

RLI

U+2067

RIGHT‑TO‑LEFT ISOLATE

The text after the RLI character is displayed right-to-left and is interpreted as isolated. This means that other control characters do not affect the display of this text fragment. The RLI action is interrupted by the PDI character or a line break.

FSI

U+2068

FIRST STRONG ISOLATE

The direction of the text after the FSI character is set by the first control character not included in this text fragment. Other control characters do not affect the display of this text. The FSI action is interrupted by the PDI character or a line break.

PDI

U+2069

POP DIRECTIONAL ISOLATE

The PDI action interrupts one of the LRI, RLI, or FSI characters encountered earlier. It interrupts exactly one last encountered character.

LRM

U+200E

LEFT-TO-RIGHT MARK

The text after the LRM character is displayed left-to-right. The LRM action is interrupted by a line break.

RLM

U+200F

RIGHT-TO-LEFT MARK

The text after the RLM character is displayed right-to-left. The RLM action is interrupted by a line break.

ALM

U+061C

ARABIC LETTER MARK

The text after the ALM character is displayed right-to-left. The ALM action is interrupted by a line break.

ZWSP

U+200B

ZERO WIDTH SPACE

An invisible space character. Using the ZWSP character causes different strings to be displayed the same way. For example, str[ZWSP]ing is displayed as string.

Take a look at the following code snippet:

bool isAdmin = false;
/*[RLO] } [LRI] if (isAdmin)[PDI] [LRI] begin admins only */ // (1)
  Console.WriteLine("You are an admin.");
/* end admins only [RLO]{ [LRI]*/                            // (2)

Now let's take a closer look at line (1).

[LRI] if (isAdmin)[PDI]

The [LRI] character here is valid up to the [PDI] character. The if (isAdmin) string is displayed left-to-right and is isolated. We get if (isAdmin).

[LRI] begin admins only */

The [LRI] character here is valid to the end of the string. We get an isolated string: begin admins only */

[RLO] {space1}, '}', {space2}, 'if (isAdmin)', 'begin admins only */'

The [RLO] character here is valid to the end of the string and displays the text right-to-left. Each of the isolated strings obtained in the previous paragraphs is treated as a separate, indivisible character. We get the following sequence:

'begin admins only */', 'if (isAdmin)', {space2}, '{', {space1}

Note that the closing brace character is now displayed as { instead of }.

The final view of the (1) line that can be displayed in the editor:

/* begin admins only */ if (isAdmin) {

Similar transformations affect the (2) line, which is displayed like this:

/* end admins only */ }

The code fragment that can be displayed in the editor:

bool isAdmin = false;
/* begin admins only */ if (isAdmin) { 
  Console.WriteLine("You are an admin.");
/* end admins only */ }

A reviewer may think that some check is done in the code before displaying the message. They will ignore the comments and think that this is how the code should run:

bool isAdmin = false;
if (isAdmin) { 
  Console.WriteLine("You are an admin.");
}

However, there is no any check. This is how the discussed code looks for the compiler:

bool isAdmin = false;
Console.WriteLine("You are an admin.");

Now, let's look at a simple yet dangerous example of using invisible characters:

enum BlockSipherType { DES, TripleDES, AES };

BlockSipherType StringToBlockSypherType(string str)
{
    if (str == "AES[ZWSP]")
        return BlockSipherType.AES;
    else if (str == "TripleDES[ZWSP]")
        return BlockSipherType.TripleDES;
    else return BlockSipherType.DES;
}

The StringToBlockCipherType method converts the string to one of the BlockCipherType enumeration values. Looking at the code, one might conclude that the function returns three different values, but this is not the case. Due to the addition of an invisible [ZWSP] space character at the end of each string literal, equality checks with the AES and TripleDES strings will be false. As a result, the function will return only BlockCipherType::DES out of three expected values. At the same time, the code in the editor may look like this:

enum BlockSipherType { DES, TripleDES, AES };

BlockSipherType StringToBlockSypherType(string str)
{
    if (str == "AES")
        return BlockSipherType.AES;
    else if (str == "TripleDES")
        return BlockSipherType.TripleDES;
    else return BlockSipherType.DES;
}

If the analyzer issued a warning about invisible characters in the code, enable the display of invisible characters in your editor and make sure that they do not change the execution logic of the program.

This diagnostic is classified as:

close form

Remplissez le formulaire ci‑dessous en 2 étapes simples :

Vos coordonnées :

Étape 1
Félicitations ! Voici votre code promo !

Type de licence souhaité :

Étape 2
Team license
Enterprise licence
** En cliquant sur ce bouton, vous déclarez accepter notre politique de confidentialité
close form
Demandez des tarifs
Nouvelle licence
Renouvellement de licence
--Sélectionnez la devise--
USD
EUR
* En cliquant sur ce bouton, vous déclarez accepter notre politique de confidentialité

close form
La licence PVS‑Studio gratuit pour les spécialistes Microsoft MVP
close form
Pour obtenir la licence de votre projet open source, s’il vous plait rempliez ce formulaire
* En cliquant sur ce bouton, vous déclarez accepter notre politique de confidentialité

close form
I want to join the test
* En cliquant sur ce bouton, vous déclarez accepter notre politique de confidentialité

close form
check circle
Votre message a été envoyé.

Nous vous répondrons à


Si l'e-mail n'apparaît pas dans votre boîte de réception, recherchez-le dans l'un des dossiers suivants:

  • Promotion
  • Notifications
  • Spam