CWE Rule 129
Description
Rule Description
The product uses untrusted input when calculating or using an array index, but the product does not validate or incorrectly validates the index to ensure the index references a valid position within the array.
Polyspace Implementation
The rule checker checks for these issues:
Array access with tainted index
Invalid use of standard library string routine
Pointer dereference with tainted offset
Tainted division operand
Tainted modulo operand
Examples
Array access with tainted index
This issue occurs when you access an array by using an index that is obtained from unsecure sources and which has not been validated.
The index might be outside the valid array range. If the tainted index is outside the array range, it can cause:
Buffer underflow/underwrite — writing to memory before the beginning of the buffer.
Buffer overflow — writing to memory after the end of a buffer.
Over-reading a buffer — accessing memory after the end of the targeted buffer.
Under-reading a buffer, or accessing memory before the beginning of the targeted buffer.
An attacker can use an invalid read or write operation create to problems in your program.
Before using the index to access the array, validate the index value to make sure that it is inside the array range.
By default, Polyspace® assumes that data from external sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider
any data that does not originate in the current scope of Polyspace analysis as
tainted, use the command line option -consider-analysis-perimeter-as-trust-boundary
.
#include <stdlib.h> #include <stdio.h> #define SIZE100 100 extern int tab[SIZE100]; static int tainted_int_source(void) { return strtol(getenv("INDEX"),NULL,10); } int taintedarrayindex(void) { int num = tainted_int_source(); return tab[num];//Noncompliant }
In this example, the index num
accesses the array tab
. The index num
is obtained from
an unsecure source and the function taintedarrayindex
does not check to
see if num
is inside the range of tab
.
One possible correction is to check that num
is
in range before using it.
#include <stdlib.h> #include <stdio.h> #define SIZE100 100 extern int tab[SIZE100]; static int tainted_int_source(void) { return strtol(getenv("INDEX"),NULL,10); } int taintedarrayindex(void) { int num = tainted_int_source(); if (num >= 0 && num < SIZE100) { return tab[num]; } else { return -1; } }
Invalid use of standard library string routine
This issue occurs when a string library function is called with invalid arguments.
The risk depends on the type of invalid arguments. For instance, using the
strcpy
function with a source argument larger than the
destination argument can result in buffer overflows.
The fix depends on the standard library function involved in the defect. In some cases, you can constrain the function arguments before the function call. For instance, if the strcpy
function:
char * strcpy(char * destination, const char* source)
strcpy
. In some cases, you can use an alternative function to avoid the error. For instance, instead of strcpy
, you can use strncpy
to control the number of bytes copied.See examples of fixes below.
If you do not want to fix the issue, add comments to your result or code to avoid another review. See:
Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface.
Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser.
Annotate Code and Hide Known or Acceptable Results if you review results in an IDE.
#include <string.h> #include <stdio.h> char* Copy_String(void) { char *res; char gbuffer[5],text[20]="ABCDEFGHIJKL"; res=strcpy(gbuffer,text); //Noncompliant /* Error: Size of text is less than gbuffer */ return(res); }
The string text
is larger
in size than gbuffer
. Therefore, the function strcpy
cannot
copy text
into gbuffer
.
One possible correction is to declare the destination
string gbuffer
with equal or larger size than the
source string text
.
#include <string.h> #include <stdio.h> char* Copy_String(void) { char *res; /*Fix: gbuffer has equal or larger size than text */ char gbuffer[20],text[20]="ABCDEFGHIJKL"; res=strcpy(gbuffer,text); return(res); }
Pointer dereference with tainted offset
This issue occurs when a pointer dereference uses an offset variable from an unknown or unsecure source.
This check focuses on dynamically allocated buffers. For static
buffer offsets, see Array access with tainted index
.
The index might be outside the valid array range. If the tainted index is outside the array range, it can cause:
Buffer underflow/underwrite, or writing to memory before the beginning of the buffer.
Buffer overflow, or writing to memory after the end of a buffer.
Over reading a buffer, or accessing memory after the end of the targeted buffer.
Under-reading a buffer, or accessing memory before the beginning of the targeted buffer.
An attacker can use an invalid read or write to compromise your program.
Validate the index before you use the variable to access the pointer. Check to make sure that the variable is inside the valid range and does not overflow.
By default, Polyspace assumes that data from external sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider
any data that does not originate in the current scope of Polyspace analysis as
tainted, use the command line option -consider-analysis-perimeter-as-trust-boundary
.
#include <stdio.h> #include <stdlib.h> enum { SIZE10 = 10, SIZE100 = 100, SIZE128 = 128 }; extern void read_pint(int*); int taintedptroffset(void) { int offset; scanf("%d",&offset); int* pint = (int*)calloc(SIZE10, sizeof(int)); int c = 0; if(pint) { /* Filling array */ read_pint(pint); c = pint[offset];//Noncompliant free(pint); } return c; }
In this example, the function initializes an integer
pointer pint
. The pointer is dereferenced using the input index
offset
. The value of offset
could be outside the
pointer range, causing an out-of-range error.
One possible correction is to validate the value of offset
. Continue with
the pointer dereferencing only if offset
is inside the valid range.
#include <stdlib.h> #include <stdio.h> enum { SIZE10 = 10, SIZE100 = 100, SIZE128 = 128 }; extern void read_pint(int*); int taintedptroffset(void) { int offset; scanf("%d",&offset); int* pint = (int*)calloc(SIZE10, sizeof(int)); int c = 0; if (pint) { /* Filling array */ read_pint(pint); if (offset>0 && offset<SIZE10) { c = pint[offset]; } free(pint); } return c; }
Tainted division operand
This issue occurs when one or both integer operands in a division operation comes from unsecure sources.
If the numerator is the minimum possible value and the denominator is
-1
, your division operation overflows because the result cannot be represented by the current variable size.If the denominator is zero, your division operation fails possibly causing your program to crash.
These risks can be used to execute arbitrary code. This code is usually outside the scope of a program's implicit security policy.
Before performing the division, validate the values of the operands.
Check for denominators of 0
or -1
,
and numerators of the minimum integer value.
By default, Polyspace assumes that data from external
sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider any data that does not originate in
the current scope of Polyspace analysis as tainted,
use the command line option -consider-analysis-perimeter-as-trust-boundary
.
#include <limits.h> #include <stdio.h> extern void print_int(int); int taintedintdivision(void) { long num, denum; scanf("%lf %lf", &num, &denum); int r = num/denum; //Noncompliant print_int(r); return r; }
This example function divides two argument variables, then prints and returns the result. The argument values are unknown and can cause division by zero or integer overflow.
One possible correction is to check the values of the numerator and denominator before performing the division.
#include <limits.h> #include <stdio.h> extern void print_long(long); int taintedintdivision(void) { long num, denum; scanf("%lf %lf", &num, &denum); long res= 0; if (denum!=0 && !(num==INT_MIN && denum==-1)) { res = num/denum; } print_long(res); return res; }
Tainted modulo operand
This issue occurs when one or both integer operands in a remainder
operation (%
) comes from unsecure
sources.
If the second remainder operand is zero, your remainder operation fails, causing your program to crash.
If the second remainder operand is
-1
, your remainder operation can overflow if the remainder operation is implemented based on the division operation that can overflow.If one of the operands is negative, the operation result is uncertain. For C89, the modulo operation is not standardized, so the result from negative operands is implementation-defined.
These risks can be exploited by attackers to gain access to your program or the target in general.
Before performing the modulo operation, validate the values
of the operands. Check the second operand for values of 0
and -1
.
Check both operands for negative values.
By default, Polyspace assumes that data from external
sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider any data that does not originate in
the current scope of Polyspace analysis as tainted,
use the command line option -consider-analysis-perimeter-as-trust-boundary
.
#include <stdio.h> extern void print_int(int); int taintedintmod(void) { int userden; scanf("%d", &userden); int rem = 128%userden; //Noncompliant print_int(rem); return rem; }
In this example, the function performs a modulo operation by using a user input. The input is not checked before calculating the remainder for values that can crash the program, such as 0 and -1.
One possible correction is to check the values of the operands before performing the modulo operation. In this corrected example, the modulo operation continues only if the second operand is greater than zero.
#include<stdio.h> extern void print_int(int); int taintedintmod(void) { int userden; scanf("%d", &userden); int rem = 0; if (userden > 0 ) { rem = 128 % userden; } print_int(rem); return rem; }
Check Information
Category: Data Validation 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 (한국어)