CWE Rule 682
Description
Rule Description
The product performs a calculation that generates incorrect or unintended results that are later used in security-critical decisions or resource management.
Polyspace Implementation
The rule checker checks for these issues:
Absorption of float operand
Bitwise operation on negative value
Float overflow
Invalid use of standard library floating point routine
Invalid use of standard library integer routine
Tainted modulo operand
Use of plain char type for numeric value
Examples
Absorption of float operand
This issue occurs when one operand of an addition or subtraction operation is always negligibly small compared to the other operand. Therefore, the result of the operation is always equal to the value of the larger operand, making the operation redundant.
Redundant operations waste execution cycles of your processor.
The absorption of a float operand can indicate design issues elsewhere in the code. It is possible that the developer expected a different range for one of the operands and did not expect the redundancy of the operation. However, the operand range is different from what the developer expects because of issues elsewhere in the code.
See if the operand ranges are what you expect. To see the ranges, place your cursor on the operation.
If the ranges are what you expect, justify why you have the redundant operation in place. For instance, the code is only partially written and you anticipate other values for one or both of the operands from future unwritten code.
If you cannot justify the redundant operation, remove it.
If the ranges are not what you expect, in your code, trace back to see where the ranges come from. To begin your traceback, search for instances of the operand in your code. Browse through previous instances of the operand and determine where the unexpected range originates.
To determine when one operand is negligible compared to the other operand, the defect uses
rules based on IEEE® 754 standards. To fix the defect, instead of using the actual rules,
you can use this heuristic: the ratio of the larger to the smaller operand must be
less than 2p-1
at least for some
values. Here, p
is equal to 24 for 32-bit precision and 53 for
64-bit precision. To determine the precision, the defect uses your specification for
Target processor type (-target)
.
This defect appears only if one operand is always negligibly smaller than the other operand. To see instances of subnormal operands or results, use the check Subnormal Float in Polyspace® Code Prover™.
#include <stdlib.h> float get_signal(void); void do_operation(float); float input_signal1(void) { float temp = get_signal(); if(temp > 0. && temp < 1e-30) return temp; else { /* Reject value */ exit(EXIT_FAILURE); } } float input_signal2(void) { float temp = get_signal(); if(temp > 1.) return temp; else { /* Reject value */ exit(EXIT_FAILURE); } } void main() { float signal1 = input_signal1(); float signal2 = input_signal2(); float super_signal = signal1 + signal2; //Noncompliant do_operation(super_signal); }
In this example, the defect appears on the addition because
the operand signal1
is in the range (0,1e-30)
but signal2
is
greater than 1
.
One possible correction is to remove the redundant addition
operation. In the following corrected code, the operand signal2
and
its associated code is also removed from consideration.
#include <stdlib.h> float get_signal(void); void do_operation(float); float input_signal1(void) { float temp = get_signal(); if(temp > 0. && temp < 1e-30) return temp; else { /* Reject value */ exit(EXIT_FAILURE); } } void main() { float signal1 = input_signal1(); do_operation(signal1); }
Another possible correction is to see if the operand ranges
are what you expect. For instance, if one of the operand range is
not supposed to be negligibly small, fix the issue causing the small
range. In the following corrected code, the range (0,1e-2)
is
imposed on signal2
so that it is not always negligibly
small as compared to signal1
.
#include <stdlib.h> float get_signal(void); void do_operation(float); float input_signal1(void) { float temp = get_signal(); if(temp > 0. && temp < 1e-2) return temp; else { /* Reject value */ exit(EXIT_FAILURE); } } float input_signal2(void) { float temp = get_signal(); if(temp > 1.) return temp; else { /* Reject value */ exit(EXIT_FAILURE); } } void main() { float signal1 = input_signal1(); float signal2 = input_signal2(); float super_signal = signal1 + signal2; do_operation(super_signal); }
Bitwise operation on negative value
This issue occurs when bitwise operators (>>
, ^
,
|
, ~
, but
,
not
, &
) are used on signed integer
variables with negative values.
If the value of the signed integer is negative, bitwise operation results can be unexpected because:
Bitwise operations on negative values can produce compiler-specific results.
Unexpected calculations can lead to additional vulnerabilities, such as buffer overflow.
When performing bitwise operations, use unsigned
integers
to avoid unexpected results.
A default Bug Finder analysis might not raise this defect when the input values are unknown and only a subset of inputs cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
#include <stdio.h> #include <stdarg.h> static void demo_sprintf(const char *format, ...) { int rc; va_list ap; char buf[sizeof("256")]; va_start(ap, format); rc = vsprintf(buf, format, ap); if (rc == -1 || rc >= sizeof(buf)) { /* Handle error */ } va_end(ap); } void bug_bitwiseneg() { int stringify = 0x80000000; demo_sprintf("%u", stringify >> 24); //Noncompliant }
In this example, the statement demo_sprintf("%u", stringify
>> 24)
stops the program unexpectedly. You expect
the result of stringify >> 24
to be 0x80
.
However, the actual result is 0xffffff80
because stringify
is
signed and negative. The sign bit is also shifted.
unsigned
KeywordBy adding the unsigned
keyword, stringify
is
not negative and the right-shift operation gives the expected result
of 0x80
.
#include <stdio.h> #include <stdarg.h> static void demo_sprintf(const char *format, ...) { int rc; va_list ap; char buf[sizeof("256")]; va_start(ap, format); rc = vsprintf(buf, format, ap); if (rc == -1 || rc >= sizeof(buf)) { /* Handle error */ } va_end(ap); } void corrected_bitwiseneg() { unsigned int stringify = 0x80000000; demo_sprintf("%u", stringify >> 24); }
Float overflow
This issue occurs when an operation on floating point variables results in values that cannot be represented by the data type that the operation uses. This data type depends on the operand types and determines the number of bytes allocated for storing the result, thus constraining the range of allowed values.
Note that:
The data type used to determine an overflow is based on the operand data types. If you then assign the result of an operation to another variable, a different checker,
Float conversion overflow
, determines if the value assigned also overflows the variable assigned to. For instance, in an operation such as:This checker checks for an overflow based on the types ofres = x + y;
x
andy
, and not on the type ofres
. The checker for float conversion overflows then checks for an overflow based on the type ofres
.The two operands in a binary operation might undergo promotion before the operation occurs. See also Code Prover Assumptions About Implicit Data Type Conversions (Polyspace Code Prover).
The exact storage allocation for different types depends on your processor. See Target processor type (-target)
.
Overflows can result in unpredictable values from computations. The result can be infinity or the maximum finite value depending on the rounding mode used in the implementation. If you use the result of an overflowing computation in subsequent computations and do not account for the overflow, you can see unexpected results.
The fix depends on the root cause of the defect. Often the result details (or source code tooltips in Polyspace as You Code) show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show this event history, you can search for previous references of variables relevant to the defect using right-click options in the source code and find related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface or Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access).
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.
By default, a Bug Finder analysis does not recognize infinities and
NaNs
. Operations that results in infinities and
NaNs
might be flagged as defects. To handle infinities and
NaN
values in your code, use the option Consider non finite floats
(-allow-non-finite-floats).
.
A default Bug Finder analysis might not raise this defect when the input values are unknown and only a subset of inputs cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
#include <float.h> float square(void) { float val = FLT_MAX; return val * val; //Noncompliant }
In the return statement, the variable val
is
multiplied by itself. The square of the maximum float value cannot
be represented by a float (the return type for this function) because
the value of val
is the maximum float value.
One possible correction is to store the result
of the operation in a larger data type. In this example, by returning
a double
instead of a float
,
the overflow defect is fixed.
#include <float.h> double square(void) { float val = FLT_MAX; return (double)val * (double)val; }
Invalid use of standard library floating point routine
This issue occurs when you use invalid arguments with a floating point function from the standard library and the standard name space. This defect picks up:
Rounding and absolute value functions (
ceil()
,fabs()
,floor()
,fmod()
, and so on)Fractions and division functions (
fmod()
,modf()
Exponents and log functions (
frexp()
,ldexp()
,sqrt()
,pow()
,exp()
,log()
,log10()
, and so on)Trigonometry functions (
cos()
,sin()
,tan()
,acos()
,asin()
,atan()
,atan2()
, and so on)
Domain errors on standard library floating point functions result in implementation-defined values. If you use the function return value in subsequent computations, you can see unexpected results.
The fix depends on the root cause of the defect. Often the result details (or source code tooltips in Polyspace as You Code) show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show this event history, you can search for previous references of variables relevant to the defect using right-click options in the source code and find related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface or Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access).
It is a good practice to handle for domain errors before using a standard library
floating point function. For instance, before calling the acos
function, check if the argument is in [-1.0, 1.0] and handle the error.
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.
By default, a Bug Finder analysis does not recognize infinities and
NaNs
. Operations that results in infinities and
NaNs
might be flagged as defects. To handle infinities and
NaN
values in your code, use the option Consider non finite floats
(-allow-non-finite-floats).
Extend this checker to check for defects caused by specific values and invalid use of functions from a custom library. For instance:
You might be using a custom library of mathematical floating point functions. If a custom library function have the same domain and range as another function from the standard library, you can extend this checker to check the custom library function. See Extend Bug Finder Checkers for Standard Library Functions to Custom Libraries.
A default Bug Finder analysis might not raise a defect when the input values are unknown and only a subset of inputs can cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
#include <math.h> double arccosine(void) { double degree = 5.0; return acos(degree); //Noncompliant }
The input value to acos
must
be in the interval [-1,1]
. This input argument, degree
,
is outside this range.
One possible correction is to change the input value to fit the specified range. In this example, change the input value from degrees to radians to fix this defect.
#include <math.h> double arccosine(void) { double degree = 5.0; double radian = degree * 3.14159 / 180.; return acos(radian); }
#include <cmath> void InvalidUse(double& val1, double& val2){ int in = -5; int ratio = 0; //... val1 = std::sqrt(in); //Noncompliant val2 = std::log(ratio); //Noncompliant }
The input value to std::sqrt()
must be
nonnegative. Polyspace flags the use of negative input argument in
. The
input value to std::log
must be greater than zero. Polyspace flags calling std::log
by using
ratio
.
One possible correction is to check the logic and refactor
your code. For instance, instead of taking the square root of
-5
, perhaps val1
is indented to be the
negative square root of 5
. The function might be defining
ratio
incorrectly as well.
#include <cmath> int getRatio(void); void ValidUse(double& val1, double& val2){ int in = 5; int ratio = getRatio(); //... val1 = -1* std::sqrt(in); val2 = std::log(ratio); }
Invalid use of standard library integer routine
This issue occurs when you use invalid arguments with an integer function from the standard library. This defect picks up:
Character conversion functions (
toupper()
,tolower()
, and so on)Character check functions (
isalnum()
,isalpha()
,iscntrl()
,isdigit
, and so on)Integer division functions (
div()
,ldiv()
, and so on)Absolute value functions (
abs()
,labs()
, and so on)
The fix depends on the root cause of the defect. Often the result details (or source code tooltips in Polyspace as You Code) show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show this event history, you can search for previous references of variables relevant to the defect using right-click options in the source code and find related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface or Interpret Bug Finder Results in Polyspace Access Web Interface (Polyspace Access).
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.
Extend this checker to check for defects caused by specific values and invalid use of functions from a custom library. For instance:
You might be using a custom library of mathematical functions. If a custom library function have the same domain and range as another function from the standard library, you can extend this checker to check the custom library function. See Extend Bug Finder Checkers for Standard Library Functions to Custom Libraries.
A default Bug Finder analysis might not raise a defect when the input values are unknown and only a subset of inputs can cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
#include <limits.h> #include <stdlib.h> int absoluteValue(void) { int neg = INT_MIN; return abs(neg); //Noncompliant }
The input value to abs
is INT_MIN
.
The absolute value of INT_MIN
is INT_MAX+1
.
This number cannot be represented by the type int
.
One possible correction is to change the input
value to fit returned data type. In this example, change the input
value to INT_MIN+1
.
#include <limits.h> #include <stdlib.h> int absoluteValue(void) { int neg = INT_MIN+1; return abs(neg); }
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 //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; }
Use of plain char type for numeric value
This issue occurs when char
variables without explicit signedness
are used in these ways:
To store non-
char
constants.In an arithmetic operation when the
char
is:A negative value.
The result of a sign changing overflow.
As a buffer offset.
char
variables without a signed
or
unsigned
qualifier can be signed or unsigned depending on your
compiler.
Operations on a plain char can result in unexpected numerical values. If the char is used as an offset, the char can cause buffer overflow or underflow.
When initializing a char variable, to avoid implementation-defined confusion, explicitly state whether the char is signed or unsigned.
A default Bug Finder analysis might not raise this defect when the input values are unknown and only a subset of inputs cause an issue. To check for defects caused by specific system input values, run a stricter Bug Finder analysis. See Extend Bug Finder Checkers to Find Defects from Specific System Input Values.
#include <stdio.h> void badplaincharuse(void) { char c = 200; int i = 1000; (void)printf("i/c = %d\n", i/c); //Noncompliant }
In this example, the char variable c
can
be signed or unsigned depending on your compiler. Assuming 8-bit,
two's complement character types, the result is either i/c
= 5
(unsigned char) or i/c = -17
(signed
char). The correct result is unknown
without knowing the signedness of char
.
signed
QualifierOne possible correction is to add a signed
qualifier
to char
. This clarification makes the operation
defined.
#include <stdio.h> void badplaincharuse(void) { signed char c = -56; int i = 1000; (void)printf("i/c = %d\n", i/c); }
Check Information
Category: Others |
Version History
Introduced in R2024a
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 (한국어)