Miscellaneous-AnsiStringUse

Use wide strings when calling the Microsoft C/C++ standard library

Required inputs: IR

Rationale

For portable applications, the recommendation is to use UTF-8 as string encoding.

However, on Windows, this is problematic because the standard library expects char* strings to use the system ANSI codepage. Moreover, it is impossible to access all files when passing file names as char* to the standard library, because some file names may contain Unicode characters that have no representation in the ANSI codepage.

In order to use UTF-8 internally in the application, all strings must be converted to/from wide-strings when calling Microsoft APIs. Even if UTF-8 is not used internally, the ANSI APIs must be avoided.

You should only enable this rule when analyzing a Windows build of your application. On other platforms, the normal functions taking char* can be used with UTF-8.

Windows API
This rule only verifies calls to functions from the Microsoft C/C++ standard library. It does not verify direct calls to the Windows API. You should #define UNICODE and _UNICODE to use the Windows API with wide strings.
Example
void open_file(const std::string& filename)
{
    std::ifstream f1(filename);  // Not compliant:
    // 'filename' is interpreted using the ANSI codepage

    std::ifstream f2(widen(filename)); // Compliant.
}
    
widen() is a helper function that converts from UTF-8 std::string to std::wstring on Windows. On other platforms, it returns the std::string without any conversion.
See Also
https://utf8everywhere.org/#windows

Possible Messages

Key

Text

Severity

Disabled

ansi_console_call

Use of ANSI string for Windows console API.

None

False

ansi_env_call

Access to environment using ANSI strings.

None

False

ansi_exec_call

Process start using ANSI strings.

None

False

ansi_file_call

Use of ANSI string for file path.

None

False

ansi_time_call

Use of ANSI string for time API.

None

True

Options

stdlib_console_functions

stdlib_console_functions

Type: dict[bauhaus.analysis.config.QualifiedName, int]

Default:

{
   '_cgets_s': 0,
   '_cprintf': 0,
   '_cprintf_l': 0,
   '_cprintf_p': 0,
   '_cprintf_p_l': 0,
   '_cprintf_s': 0,
   '_cprintf_s_l': 0,
   '_cputs': 0,
   '_cscanf': 0,
   '_cscanf_l': 0,
   '_cscanf_s': 0,
   '_cscanf_s_l': 0,
   '_getch': -1,
   '_getch_nolock': -1,
   '_getche': -1,
   '_getche_nolock': -1,
   'cgets': 0,
   'cprintf': 0,
   'cputs': 0,
   'cscanf': 0,
   'getch': -1,
   'getche': -1
}
Mapping from console function names to the index of the string parameter.
 

stdlib_env_functions

stdlib_env_functions

Type: dict[bauhaus.analysis.config.QualifiedName, int]

Default:

{
   '_dupenv_s': 0,
   '_dupenv_s_dbg': 0,
   '_putenv': 0,
   '_putenv_s': 0,
   '_searchenv': 0,
   '_searchenv_s': 0,
   'getenv': -1,
   'getenv_s': 1,
   'putenv': 0
}
Mapping from environment function names to the index of the string parameter.
 

stdlib_exec_functions

stdlib_exec_functions

Type: dict[bauhaus.analysis.config.QualifiedName, int]

Default:

{
   '_execl': 0,
   '_execle': 0,
   '_execlp': 0,
   '_execlpe': 0,
   '_execv': 0,
   '_execve': 0,
   '_execvp': 0,
   '_execvpe': 0,
   '_popen': 0,
   '_spawnl': 1,
   '_spawnle': 1,
   '_spawnlp': 1,
   '_spawnlpe': 1,
   '_spawnv': 1,
   '_spawnve': 1,
   '_spawnvp': 1,
   '_spawnvpe': 1,
   'execl': 0,
   'execle': 0,
   'execlp': 0,
   'execlpe': 0,
   'execv': 0,
   'execve': 0,
   'execvp': 0,
   'execvpe': 0,
   'spawnl': 1,
   'spawnle': 1,
   'spawnlp': 1,
   'spawnlpe': 1,
   'spawnv': 1,
   'spawnve': 1,
   'spawnvp': 1,
   'spawnvpe': 1,
   'system': 0
}
Mapping from execution function names to the index of the string parameter.
 

stdlib_file_functions

stdlib_file_functions

Type: dict[bauhaus.analysis.config.QualifiedName, int]

Default:

{
   '_access': 0,
   '_access_s': 0,
   '_chdir': 0,
   '_chmod': 0,
   '_creat': 0,
   '_findfirst': 0,
   '_findfirst32': 0,
   '_findfirst32i64': 0,
   '_findfirst64': 0,
   '_findfirst64i32': 0,
   '_findfirsti64': 0,
   '_fsopen': 0,
   '_fullpath': 0,
   '_fullpath_dbg': 0,
   '_getcwd': 0,
   '_getcwd_dbg': 0,
   '_getdcwd': 1,
   '_getdcwd_dbg': 1,
   '_getdcwd_nolock': 1,
   '_makepath': 0,
   '_makepath_s': 0,
   '_mkdir': 0,
   '_mktemp': 0,
   '_mktemp_s': 0,
   '_open': 0,
   '_remove': 0,
   '_rename': 0,
   '_rmdir': 0,
   '_sopen': 0,
   '_sopen_s': 1,
   '_splitpath': 0,
   '_splitpath_s': 0,
   '_stat': 0,
   '_stat32': 0,
   '_stat32i64': 0,
   '_stat64': 0,
   '_stat64i32': 0,
   '_stati64': 0,
   '_tempnam': 0,
   '_tempnam_dbg': 0,
   '_unlink': 0,
   '_utime': 0,
   '_utime32': 0,
   '_utime64': 0,
   'access': 0,
   'chdir': 0,
   'chmod': 0,
   'creat': 0,
   'fopen': 0,
   'fopen_s': 1,
   'freopen': 0,
   'freopen_s': 0,
   'getcwd': 0,
   'mkdir': 0,
   'mktemp': 0,
   'open': 0,
   'remove': 0,
   'rename': 0,
   'rmdir': 0,
   'sopen': 0,
   'stat': 0,
   'std::basic_filebuf::basic_filebuf': 1,
   'std::basic_filebuf::open': 1,
   'std::basic_fstream::basic_fstream': 1,
   'std::basic_fstream::open': 1,
   'std::basic_ifstream::basic_ifstream': 1,
   'std::basic_ifstream::open': 1,
   'std::basic_ofstream::basic_ofstream': 1,
   'std::basic_ofstream::open': 1,
   'std::experimental::filesystem::path::append': 1,
   'std::experimental::filesystem::path::assign': 1,
   'std::experimental::filesystem::path::concat': 1,
   'std::experimental::filesystem::path::generic_string': -1,
   'std::experimental::filesystem::path::operator+=': 1,
   'std::experimental::filesystem::path::operator/=': 1,
   'std::experimental::filesystem::path::operator=': 1,
   'std::experimental::filesystem::path::path': 1,
   'std::experimental::filesystem::path::string': -1,
   'std::filesystem::path::append': 1,
   'std::filesystem::path::assign': 1,
   'std::filesystem::path::concat': 1,
   'std::filesystem::path::generic_string': -1,
   'std::filesystem::path::operator+=': 1,
   'std::filesystem::path::operator/=': 1,
   'std::filesystem::path::operator=': 1,
   'std::filesystem::path::path': 1,
   'std::filesystem::path::string': -1,
   'tempnam': 0,
   'tmpnam_s': 0,
   'unlink': 0,
   'utime': 0
}
Mapping from file function names to the index of the string parameter.
 

stdlib_time_functions

stdlib_time_functions

Type: dict[bauhaus.analysis.config.QualifiedName, int]

Default:

{
   '_ctime32': -1,
   '_ctime32_s': 0,
   '_ctime64': -1,
   '_ctime64_s': 0,
   '_strdate': 0,
   '_strdate_s': 0,
   '_strftime_l': 0,
   '_strtime': 0,
   '_strtime_s': 0,
   'ctime': -1,
   'ctime_s': 0,
   'strftime': 0
}
Mapping from time function names to the index of the string parameter.