CWE Rule 188
Description
Rule Description
The software makes invalid assumptions about how protocol data or memory is organized at a lower level, resulting in unintended program behavior.
Polyspace Implementation
The rule checker checks for these issues:
Invalid assumptions about memory organization
Memory comparison of padding data
Missing byte reordering when transferring data
Examples
Invalid assumptions about memory organization
This issue occurs when you compute the address of a variable in the stack by adding or subtracting from the address of another non-array variable.
When you compute the address of a variable in the stack by adding or subtracting from the address of another variable, you assume a certain memory organization. If your assumption is incorrect, accessing the computed address can be invalid.
Do not perform an access that relies on assumptions about memory organization.
void func(void) { int var1 = 0x00000011, var2; *(&var1 + 1) = 0; //Noncompliant }
In this example, the programmer relies on the assumption that &var1
+ 1
provides the address of var2
. Therefore,
an Invalid assumptions about memory organization appears
on the +
operation. In addition, a Pointer
access out of bounds error also appears on the dereference.
One possible correction is not perform direct computation on addresses to access separately declared variables.
Memory comparison of padding data
This issue occurs
when you use the memcmp
function to compare two
structures as a whole. In the process, you compare meaningless data
stored in the structure padding.
For instance:
struct structType { char member1; int member2; . . }; structType var1; structType var2; . . if(memcmp(&var1,&var2,sizeof(var1))) {...}
If members of a structure have different data types,
your compiler introduces additional padding for data alignment in memory. For an
example of padding, see Higher Estimate of Size of Local
Variables
(Polyspace Code Prover).
The content of these extra padding bytes is meaningless. The
C Standard allows the content of these bytes to be indeterminate,
giving different compilers latitude to implement their own padding.
If you perform a byte-by-byte comparison of structures with memcmp
,
you compare even the meaningless data stored in the padding. You might
reach the false conclusion that two data structures are not equal,
even if their corresponding members have the same value.
Instead of comparing two structures in one attempt, compare the structures member by member.
For efficient code, write a function that does the comparison member by member. Use this function for comparing two structures.
You can use memcmp
for byte-by-byte comparison
of structures only if you know that the structures do not contain
padding. Typically, to prevent padding, you use specific attributes
or pragmas such as #pragma pack
. However, these
attributes or pragmas are not supported by all
compilers and make your code implementation-dependent. If your structures
contain bit-fields, using these attributes or pragmas cannot prevent
padding.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define fatal_error() abort() typedef struct s_padding { char c; int i; unsigned int bf1:1; unsigned int bf2:2; unsigned char buffer[20]; } S_Padding ; /* Function that guarantees safe access to the input memory */ extern int trusted_memory_zone(void *ptr, size_t sz); int func(const S_Padding *left, const S_Padding *right) { if (!trusted_memory_zone((void *)left, sizeof(S_Padding)) || !trusted_memory_zone((void *)right, sizeof(S_Padding))) { fatal_error(); } if (0 == memcmp(left, right, sizeof(S_Padding))) //Noncompliant { return 1; } else return 0; }
In this example, memcmp
compares byte-by-byte
the two structures that left
and right
point
to. Even if the values stored in the structure members are the same,
the comparison can show an inequality if the meaningless values in
the padding bytes are not the same.
One possible correction is to compare individual structure members.
Note
You can compare entire arrays by using memcmp
.
All members of an array have the
same data type. Padding bytes are not required to store arrays.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define fatal_error() abort() typedef struct s_padding { char c; int i; unsigned int bf1:1; unsigned int bf2:2; unsigned char buffer[20]; } S_Padding ; /* Function that guarantees safe access to the input memory */ extern int trusted_memory_zone(void *ptr, size_t sz); int func(const S_Padding *left, const S_Padding *right) { if (!trusted_memory_zone((void *)left, sizeof(S_Padding)) || !trusted_memory_zone((void *)right, sizeof(S_Padding))) { fatal_error(); } return ((left->c == right->c) && (left->i == right->i) && (left->bf1 == right->bf1) && (left->bf2 == right->bf2) && (memcmp(left->buffer, right->buffer, 20) == 0)); }
Missing byte reordering when transferring data
This issue occurs when you do not use a byte ordering function:
Before sending data to a network socket.
After receiving data from a network socket.
Some system architectures implement little endian byte ordering (least significant byte first), and other systems implement big endian (most significant byte first). If the endianness of the sent data does not match the endianness of the receiving system, the value returned when reading the data is incorrect.
After receiving data from a socket, use a byte
ordering function such as ntohl()
. Before sending data to a
socket, use a byte ordering function such as htonl()
.
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <byteswap.h> #include <unistd.h> #include <string.h> unsigned int func(int sock, int server) { unsigned int num; /* assume int is 32-bits */ if (server) { /* Server side */ num = 0x17; /* Endianness of server host may not match endianness of network. */ if (send(sock, (void *)&num, sizeof(num), 0) < (int)sizeof(num)) //Noncompliant { /* Handle error */ } return 0; } else { /* Endianness of client host may not match endianness of network. */ if (recv (sock, (void *)&num, sizeof(num), 0) < (int) sizeof(num)) { /* Handle error */ } /* Comparison may be inaccurate */ if (num> 255) //Noncompliant { return 255; } else { return num; } } }
In this example, variable num
is assigned hexadecimal value
0x17
and is sent over a network to the client from the server. If the
server host is little endian and the network is big endian, num
is
transferred as 0x17000000
. The client then reads an incorrect value for
num
and compares it to a local numeric value.
Before sending num
from the server host, use
htonl()
to convert from host to network byte ordering. Similarly,
before reading num
on the client host, use ntohl()
to convert from network to host byte ordering.
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <byteswap.h> #include <unistd.h> #include <string.h> unsigned int func(int sock, int server) { unsigned int num; /* assume int is 32-bits */ if (server) { /* Server side */ num = 0x17; /* Convert to network byte order. */ num = htonl(num); if (send(sock, (void *)&num, sizeof(num), 0) < (int)sizeof(num)) { /* Handle error */ } return 0; } else { if (recv (sock, (void *)&num, sizeof(num), 0) < (int) sizeof(num)) { /* Handle error */ } /* Convert to host byte order. */ num = ntohl(num); if (num > 255) { return 255; } else { return num; } } }
Check Information
Category: Data Neutralization Issues |
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 (한국어)