CWE Rule 547
Description
Rule Description
The program uses hard-coded constants instead of symbolic names for security-critical values, which increases the likelihood of mistakes during code maintenance or security policy change.
Polyspace Implementation
The rule checker checks for these issues:
Hard-coded buffer size
Hard-coded loop boundary
Hard-coded object size used to manipulate memory
Hard-coded sensitive data
Examples
Hard-coded buffer size
This issue occurs when you use a numerical value instead of a symbolic constant when declaring a memory buffer such as an array.
Hard-coded buffer size causes the following issues:
Hard-coded buffer size increases the likelihood of mistakes and therefore maintenance costs. If a policy change requires developers to change the buffer size, they must change every occurrence of the buffer size in the code.
Hard-constant constants can be exposed to attack if the code is disclosed.
Use a symbolic name instead of a hard-coded constant for buffer
size. Symbolic names include const
-qualified variables, enum
constants,
or macros.
enum
constants are recommended.
Macros are replaced by their constant values after preprocessing. Therefore, they can expose the loop boundary.
enum
constants are known at compilation time. Therefore, compilers can optimize the loops more efficiently.const
-qualified variables are usually known at run time.
int table[100]; //Noncompliant void read(int); void func(void) { for (int i=0; i<100; i++) //Noncompliant read(table[i]); }
In this example, the size of the array table
is hard-coded. There is a second violation of the rule in this example, because the loop boundary of the for
loop is also hard-coded.
One possible correction is to replace the hard-coded size with a symbolic name.
const int MAX_1 = 100; #define MAX_2 100 enum { MAX_3 = 100 }; int table_1[MAX_1]; int table_2[MAX_2]; int table_3[MAX_3]; void read(int); void func(void) { for (int i=0; i < MAX_1; i++) read(table_1[i]); for (int i=0; i < MAX_2; i++) read(table_2[i]); for (int i=0; i < MAX_3; i++) read(table_3[i]); }
Hard-coded loop boundary
This issue occurs
when you use a numerical value instead of symbolic constant for the
boundary of a for
, while
or do-while
loop.
Hard-coded loop boundary causes the following issues:
Hard-coded loop boundary makes the code vulnerable to denial of service attacks when the loop involves time-consuming computation or resource allocation.
Hard-coded loop boundary increases the likelihood of mistakes and maintenance costs. If a policy change requires developers to change the loop boundary, they must change every occurrence of the boundary in the code.
For instance, the loop boundary is 10000 and represents the maximum number of client connections supported in a network server application. If the server supports more clients, you must change all instances of the loop boundary in your code. Even if the loop boundary occurs once, you have to search for a numerical value of
10000
in your code. The numerical value can occur in places other than the loop boundary. You must browse through those places before you find the loop boundary.
Use a symbolic name instead of a hard-coded constant for loop
boundary. Symbolic names include const
-qualified
variables, enum
constants or macros.enum
constants
are recommended because:
Macros are replaced by their constant values after preprocessing. Therefore, they can expose the buffer size.
enum
constants are known at compilation time. Therefore, compilers can allocate storage for them more efficiently.const
-qualified variables are usually known at run time.
void performOperation(int); void func(void) { for (int i=0; i<100; i++) //Noncompliant performOperation(i); }
In this example, the boundary of the for
loop
is hard-coded.
One possible correction is to replace the hard-coded loop boundary with a symbolic name.
const int MAX_1 = 100; #define MAX_2 100 enum { MAX_3 = 100 }; void performOperation_1(int); void performOperation_2(int); void performOperation_3(int); void func(void) { for (int i=0; i<MAX_1; i++) performOperation_1(i); for (int i=0; i<MAX_2; i++) performOperation_2(i); for (int i=0; i<MAX_3; i++) performOperation_3(i); }
Hard-coded object size used to manipulate memory
This issue occurs when you use hard-coded constants as memory size arguments for these memory functions:
Dynamic memory allocation function such as
malloc
orcalloc
.Memory manipulation functions such as
memcpy
,memmove
,memcmp
, ormemset
.
When performing memory operations with a string literal, Polyspace® does not report a defect if you hard code the memory size.
If you hard code object size, your code is not portable to architectures with different type sizes. If the constant value is not the same as the object size, the buffer might or might not overflow.
For the size argument of memory functions, use sizeof(
.object
)
#include <stddef.h> #include <stdlib.h> enum { SIZE3 = 3, SIZE20 = 20 }; extern void fill_ints(int **matrix, size_t nb, size_t s); void bug_hardcodedmemsize() { size_t i, s; s = 4; int **matrix = (int **)calloc(SIZE20, s); //Noncompliant if (matrix == NULL) { return; /* Indicate calloc() failure */ } fill_ints(matrix, SIZE20, s); free(matrix); }
In this example, the memory allocation function calloc
is
called with a memory size of 4. The memory is allocated for an integer
pointer, which can be a more or less than 4 bytes depending on your
target. If the integer pointer is not 4 bytes, your program can fail.
sizeof(int *)
When calling calloc
, replace the hard-coded
size with a call to sizeof
. This change makes your
code more portable.
#include <stddef.h> #include <stdlib.h> enum { SIZE3 = 3, SIZE20 = 20 }; extern void fill_ints(int **matrix, size_t nb, size_t s); void corrected_hardcodedmemsize() { size_t i, s; s = sizeof(int *); int **matrix = (int **)calloc(SIZE20, s); if (matrix == NULL) { return; /* Indicate calloc() failure */ } fill_ints(matrix, SIZE20, s); free(matrix); }
Hard-coded sensitive data
This issue occurs when data that is potentially sensitive is directly exposed in the code, for instance, as string literals. The checker identifies certain data as sensitive from their use in certain functions such as password encryption functions.
Following data can be potentially sensitive.
Type of Data | Functions That Indicate Sensitive Nature of Information |
---|---|
Host name |
|
Password |
|
Database |
|
User name |
|
Salt | crypt , crypt_r (2nd argument) |
Cryptography keys and initialization vectors | OpenSSL:
|
Seed |
|
Information that is hardcoded can be queried from binaries generated from the code.
Avoid hard coding sensitive information.
// Typically, you include the header "mysql.h" with function and type declarations. // In this example, only the required lines from the header are quoted. typedef struct _MYSQL MYSQL; MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag); typedef void * DbHandle; extern MYSQL *sql; // File that uses functions from "mysql.h" const char *host = "localhost"; char *user = "guest"; char *passwd; DbHandle connect_to_database_server(const char *db) { passwd = (char*)"guest"; return (DbHandle) mysql_real_connect (sql, host, user, passwd, db, 0, 0x0, 0); //Noncompliant }
In this example, the arguments host
(host name), user
(user name), and passwd
(password) are string literals and directly exposed in the code.
Querying the generated binary for ASCII strings can reveal this information.
One possible correction is to read the data from a configuration file. In the following corrected example, the call to function connect_to_database_server_init
presumably reads the host name, user name, and password into its arguments from a secured configuration file.
// Typically, you include the header "mysql.h" with function and type declarations. // In this example, only the required lines from the header are quoted. typedef struct _MYSQL MYSQL; MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag); typedef void * DbHandle; extern MYSQL *sql; // File that uses functions from "mysql.h" int connect_to_database_server_init(const char **host, const char **user, const char **passwd, const char **db); DbHandle connect_to_database_server(const char *db) { const char *host_from_cfg; const char *user_from_cfg; const char *passwd_from_cfg; const char *db_from_cfg; if (connect_to_database_server_init(&host_from_cfg, &user_from_cfg, &passwd_from_cfg, &db_from_cfg)) { return (DbHandle) mysql_real_connect (sql, host_from_cfg, user_from_cfg, passwd_from_cfg, db_from_cfg, 0, 0x0, 0); } else return (DbHandle)0x0; }
Check Information
Category: Bad Coding Practices |
Version History
Introduced in R2023a
See Also
External Websites
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)