CSC201 Sec 1 Proj 2 Team 6
CSC201 Sec 1 Proj 2 Team 6
CSC – 201
Team Members:
Sasi Kiran Kanduri
Ashish Tharanath Kotian
Rajasekhar Reddy Kolagotla
Chanakya Rudhra Baluguri
Introduction
• This standard provides rules for secure coding in the C/Java programming
languages. The goal of these rules and recommendations is to develop safe,
reliable, and secure systems, for example by eliminating undefined behaviors that
can lead to undefined program behaviors and exploitable vulnerabilities.
Rules Recommendations
● Violation of the guideline -> may ● Suggestions for improving code
adversely affect the safety, quality
reliability, or security of a system. ● Application of a guideline is likely to
Example: Security flaw -> exploitable improve the safety, reliability, or
Vulnerability security of software systems
● guideline does not rely on source code ● One or more of the requirements
annotations or assumptions necessary for a guideline to be
considered a rule cannot be met
Rules and Recommendations
Noncompliant Code Examples and Compliant Solutions
• Illustrate code that violates the guideline under discussion.
• Noncompliant code examples are typically followed by compliant solutions.
• Compliant solutions should comply with all of the secure coding rules but may on
occasion fail to comply with a recommendation.
Exceptions
• Exceptions can be specified for any rules or recommendations.
• Coding practices that specify one or more exceptions are identified by the
label exceptions.
Identifiers
Each rule and recommendation are given a unique identifier
o A three-letter mnemonic representing the section of the standard
o A two-digit numeric value in the range of 00 to 99
o The letter "J" indicates that this is a Java language guideline
Priority and Levels
Each rule has an assigned priority. Priorities are assigned using a metric based on
Failure Mode, Effects, and Criticality Analysis.
Severity—How serious are the consequences of the rule being ignored?
Likelihood—How likely is it that a flaw introduced by violating the rule can lead to an
exploitable vulnerability?
Rule: Priority and Levels
Remediation Cost—How expensive is it to comply with the rule?
Priority Levels
Rules For C
INT Rule04:
•INT33-C. Ensure that division and remainder operations do not result in divide-by-zero
errors
● Division: The result of the / operator is the quotient from the division of the
first arithmetic operand by the second arithmetic operand. Division operations
are susceptible to divide-by-zero errors.
Risk Assessment:
A divide-by-zero error can result in abnormal program termination and denial
of service.
INT 34-C.
Do not shift an expression by a negative number of bits or by greater
than or equal to the number of bits that exist in the operand
.
Does not Ensure that the right operand is not greater than the precision of the left
operand.
Right Shift :
Compliant Code Example:
The following compliant solution uses the popcount() method to calculate the
precision and makes sure that right operand is less that it.
Non-Compliant Code (signed Type):
This noncompliant code example fails to ensure that left and right operands have
nonnegative values and that the right operand is less than the precision of the
promoted left operand. This example does check for signed integer overflow.
In addition to the check for overflow, this compliant solution ensures that both the
left and right operands have nonnegative values and that the right operand is less
than the precision of the promoted left operand
Risk Assessment:
Although shifting a negative number of bits or shifting a number of bits greater than
or equal to the width of the promoted left operand is undefined behavior in C, the
risk is generally low because processors frequently reduce the shift amount modulo
the width of the type.
INT 35-C. Use Correct Integer Precisions.
● Integer types in C have precision.
● Precision is the number of bits used to represent the integer value.
● It can be retrieved for any object or type.
● Padding Bits: extra bits of 0 added to the higher end of integers to adhere to the
platform(computer architecture , 32/64).
● Programmers should use correct precision to avoid logic errors. *
Non-Compliant Code:
● This code is a function to returns 2 raised to the power of the argument. 2 exp.
● This function ensures the compliance of INT 34-C by checking that argument is less that number
of bits used to store the value.
● If this function runs on a platform where unsigned int is 64 bits but uses only 48 bits to represent
the value, this may result in undefined behavior.
Compliant Code:
● This function counts the number of bits of any unsigned integer.
● Can be used to calculate precision. We will need this function to revise a
compliant solution for INT 35-C.
● Using the popcount() function, we can define a revised pow2 function previously
discussed.
● The revised version of the pow2() function uses the PRECISION() macro to
determine the precision of the unsigned type:
Invalid precision can lead to errors in shift operations and cause undefined behaviors.
INT 36-C. Converting a pointer to integer or an integer
to pointer.
● Do not convert a pointer type to an integer type if the result cannot be
represented in the integer type.
● A pointer stores the address location and returns the value in that location.
This code will be wrong on an implementation of 64-bit ptr and 32-bit unsigned int.
A 64-bit ptr cannot be represented in a 32-bit integer.
Implementation:
● C provides types intprt_t and uintptr_t to convert a valid pointer to integer and
back again to pointer with no change in value.
● INT 36-C-EXC1: An integer to pointer is always safe when the integer is 0 as it will
result in a null pointer.
● In general, any pointer to void can be changed to intptr_t or uintptr_t and back
with no change in the value.
● Here, void generally does not have type so it can be changed back and forth.
Risk Assessment:
● INT07-C. Use only explicitly signed or unsigned char type for numeric values
● The reason for discouraging the use of formatted input stems from the fact that
there is no way to detect if overflow or underflow has occurred and it would simply
return a random value instead of the input given.
Noncompliant Code: Compliant Solution (Linux):
• Use only signed char and unsigned char types for the storage and use of numeric
values because it is the only portable way to guarantee the signedness of the
character types.
Noncompliant Code : Compliant Solution:
INT07-C-EX1: void FIO34-C. Use int to capture the return value of character IO
functions that might be used to check for end of file mentions that certain character
IO functions return a value of type int. Despite being returned in an arithmetic type, the
value is not actually numeric in nature, so it is acceptable to later store the result into a
variable of type char.
Risk Assessment:
This is a subtle error that results in a disturbingly broad range of potentially severe
vulnerabilities. At the very least, this error can lead to unexpected numerical results on
different platforms. Unexpected arithmetic values when applied to arrays or pointers can
yield buffer overflows or other invalid memory access.
INT08-C. Verify that all integer values are in range
● Integer operations must result in an integer value within the range of the integer type
● The range is more restrictive depending on the use of the integer value.
Ex: Index of an array.
● A program that detects an integer overflow to be imminent may do one of two things:
(1) Signal some sort of error condition: This can be handled by an error condition
complaining about a bad input and request for a new input.
(2) Produce an integer result that is within the range of representable integers on that
system and proceed with the computation thereby avoiding denial of service.
To produce integer results we can make use of these 3 techniques:
1) Saturation Semantics
2) Modwrap Semantics
3) Restricted Range Usage
Saturation Semantics:
The value returned to the user is set out in the following table:
In modwrap semantics (also called modulo arithmetic), integer values "wrap round." That
is, adding 1 to MAX produces MIN. This is a defined behavior of both signed int and
unsigned int. But it is more sensible to use saturation semantics instead of modwrap.
Ex: In the computation of a size (using unsigned integers), it is often better for the size to
stay at the maximum value in the event of overflow rather than to suddenly become a very
small value.
Another technique for avoiding integer overflow is to use only half the range of signed
integers. For example, when using an int, use only the range [INT_MIN/2, INT_MAX/2].
This practice has been a trick of the trade in Fortran for some time, and now that
optimizing C compilers are more sophisticated, it can be valuable in C.
Ex: Consider subtraction. If the user types the expression a - b, where both a and b are in
the range [INT_MIN/2, INT_MAX/2], the result will be in the range (INT_MIN, INT_MAX]
for a typical two's complement machine.
NoncompliantCode: CompliantSolution:
Out-of-range integer values can result in reading from or writing to arbitrary memory
locations and the execution of arbitrary code.
INT09-C. Ensure enumeration constants map to unique values.
• C language allows multiple enumerators of the same type to have the same
value, it is a common expectation that all enumerators of the same type have
distinct values.
• Defining two or more enumerators of the same type to have the same value
can lead to some nonobvious errors.
Noncompliant Code:
• In the Noncompliant code, two enumerators of type Color are assigned explicit values.
• It may not be obvious to the programmer that yellow and indigo have been declared
to be identical values (6), as are green and violet (7).
• The following code violates this semantic constraint and is required to be diagnosed by
a confirming compiler.
Compliant Solution:
To prevent the error discussed of the noncompliant code example, enumeration type
declarations must take one of the following forms:
• Assign a value to the first member only (the rest are then sequential), as in this example:
Of these three options, providing no explicit integer assignments is the preferred approach
unless the first enumerator must have a nonzero value.
INT09-C-EX1: In cases where defining an enumeration with two or more enumerators with
the same value is intended, the constant expression used to define the value of the
duplicate enumerator should reference the enumerator rather than the original
enumerator's value.
Risk Assessment:
Failing to ensure that constants within an enumeration have unique values can result in
unexpected results.
Rules For Java
NUM Rule03:
• Floating-point variables must not be used as loop counters because the processing
takes a lot of time and also if the processor doesn't have floating-point hardware,
it will take way more time to do a simple increment.
• For the purpose of this rule, a loop counter is an induction variable that is used as
an operand of a comparison expression that is used as the controlling expression
of a do, while or for loop.
Risk Assessment:
Rule: NUM10-J. Do not construct BigDecimal objects
from floating-point literals
• Literal decimal floating-point numbers cannot always be precisely
represented as an floating-point value.
• Consequently, the BigDecimal (double val) constructor must not be passed a
floating-point literal as an argument, when doing so results in an
unacceptable loss of precision.
Risk Assessment:
Risk Assessment:
Comparing or inspecting the string representation of floating-point values may
have unexpected results.
Rule: NUM12-J. Ensure conversions of numeric types to narrower
types do not result in lost or misinterpreted data
• Conversions of numeric types to narrower types can result in lost or misinterpreted
data if the value of the wider type is outside the range of values of the narrower type.
• Consequently, all narrowing conversions must be guaranteed safe by range-checking
the value before conversion.
• Java provides 22 possible narrowing primitive conversions.
• short to byte or char
• char to byte or short
• int to byte, short, or char
• long to byte, short, char, or int
• float to byte, short, char, int, or long
• double to byte, short, char, int, long, or float
• Narrowing primitive conversions are allowed in cases where the value of the wider
type is within the range of the narrower type.
Non-Compliant Code Example (Integer Narrowing):
Risk Assessment:
• Casting a numeric value to a narrower type can result in information loss related
to the sign and magnitude of the numeric value. As a result, data can be
misrepresented or interpreted incorrectly.
Rule: NUM13-J. Avoid loss of precision when
converting primitive integers to floating-point
• The following 19 specific conversions on primitive types are called the widening
primitive conversions:
• byte to short, int, long, float, or double
• short to int, long, float, or double
• char to int, long, float, or double
• int to long, float, or double
• long to float or double
• float to double
• Conversions from integral types smaller than int to a floating-point type and
conversions from int to double can never result in a loss of precision. Consequently,
programs must ensure that conversions from an int or long to a floating-point type or
from long to double do not result in a loss of required precision.
Non-Compliant Code Example:
• In this noncompliant code example, two identical large integer literals are passed as arguments to
the subFloatFromInt() method. The second argument is coerced to float, cast back to int, and
subtracted from a value of type int. The result is returned as a value of type int.
• This method could have unexpected results because of the loss of precision. The exponent allows
type float to represent a larger range than that of type int. However, the 23-bit mantissa means
that float supports exact representation only of integers whose representation fits within 23
bits; float supports only approximate representation of integers outside that range.
Exceptions:
NUM13-J-EX0: Conversion from integral types to floating-point types without a range check is
permitted when suitable numerical analysis demonstrates that the loss of the least significant bits of
precision is acceptable.
Rule: NUM14-J. Use shift operators correctly
• The shift operators in Java have the following properties,
• “>>” right shift is an arithmetic shift; “>>>” right shift is a logical shift.
• types boolean, float, and double can’t use the bit-shifting operators.
• When the value to be shifted is of type int, only the five lowest-order bits of
the right-hand operand are used as the shift distance.
• When the value to be shifted (left operand) is type long, only the last 6 bits
of the right-hand operand are used to perform the shift.
• The value to the right of a shift operation must be within the appropriate range
for the type of the numeric value to the left of the shift operation.
Rule: NUM14-J. Use shift operators correctly
• Arithmetic vs. Logical Shift:
• The JLS, defines the behavior of the arithmetic shift operator as follows:
• The value of n>>s is n right-shifted s bit positions with sign-extension. The resulting
value is floor(n / 2s). For nonnegative values of n, this is equivalent to truncating integer
division, as computed by the integer division operator /, by two to the power s.
• The JLS also defines the behavior of the logical shift operator:
• The value of n >>> s is n right-shifted s bit positions with zero-extension, where:
• If n is positive, then the result is the same as that of n >> s.
• If n is negative and the type of the left-hand operand is int, then the result is
equal to that of the expression (n >> s) + (2 << ~s).
• If n is negative and the type of the left-hand operand is long, then the result is
equal to that of the expression (n >> s) + (2L << ~s).
• Never use the arithmetic shift operator when the logical shift operator is required.
Noncompliant Code Example (Arithmetic vs. Logical):
NUM Recommendation03:
Promotion Rules:
Java Language Specification describes numeric promotion rules as follows:
• If any of the operands is of a reference type, unboxing conversion is performed.
• If either operand is of type double, the other is converted to double.
• Otherwise, if either operand is of type float, the other is converted to float.
• Otherwise, if either operand is of type long, the other is converted to long.
• Otherwise, both operands are converted to type int.
These conversions can occur when using the multiplicative operators (%, *, /),
additive operators (+, -), comparison operators (<, >, <=, >=), equality operators (==, !
=), and the integer bitwise operators (&, |, ^).
Examples:
In this example, a is promoted to a double before the + operator is applied
In this program fragment, b is first converted to int so that the + operator can be
applied to operands of the same type
Applicability
• Failing to consider integer promotions when dealing with floating-point and integer
operands can result in a loss of precision.
Automated Detection:
NUM53-J. Use the strictfp modifier for floating-point
calculation consistency across platforms
• Programs that require consistent results from floating-point operations across
different JVMs and platforms must use the strictfp modifier.
• It can have a substantial impact, however, on both the efficiency and the resulting
values of floating-point computations when executing on platforms that provide
extended floating-point support.
• On these platforms, using the strictfp modifier increases the likelihood that
intermediate operations will overflow or underflow because it restricts the range of
intermediate values that can be represented.
• It can also reduce computational efficiency.
• The strictfp modifier can be used with a class, method, or interface.
Non-Compliant Code Example
• The JVM may choose to treat this case as FP-strict; if it does so, overflow occurs.
Because the expression is not FP-strict, an implementation may use an extended
exponent range to represent intermediate results.
Compliant Solution:
• For maximum portability, use the strictfp modifier within an expression (class,
method, or interface) to guarantee that intermediate results do not vary because
of implementation-defined behavior.
Non-Compliant Code Example
• This compliant solution uses the strictfp keyword to require exact conformance with
the standard Java floating-point. Consequently, the intermediate value of both
computations of f * g is identical to the value stored in this.d, even on platforms that
support extended-range exponents.
Exceptions:
NUM06-J-EX0: This rule applies only to calculations that require consistent floating-
point results on all platforms. Applications that lack this requirement need not
comply.
Risk Assessment:
Failure to use the strictfp modifier can result in nonportable, implementation-defined
behavior with respect to the behavior of floating-point operations.
NUM54-J. Do not use denormalized numbers
• Java uses the IEEE 754 standard for floating-point representation.
• In this representation, floats are encoded using 1 sign bit, 8 exponent bits, and 23
mantissa bits.
• Doubles are encoded and used exactly the same way, except they use 1 sign bit, 11
exponent bits, and 52 mantissa bits.
• These bits encode the values of s, the sign; M, the significand; and E, the exponent.
• Floating-point numbers are then calculated as (-1)s * M * 2 E.
• Ordinarily, all of the mantissa bits are used to express significant figures, in addition to a
leading 1, which is implied and consequently omitted. As a result, floats have 24
significant bits of precision, and doubles have 53 significant bits of precision. Such
numbers are called normalized numbers.
• When the value to be represented is too small to encode normally, it is encoded in
denormalized form, indicated by an exponent value of Float.MIN_EXPONENT - 1 or
Double.MIN_EXPONENT - 1.
• Denormalized floating-point numbers have an assumed 0 in the ones' place and have
one or more leading zeros in the represented portion of their mantissa.
• Note that even using normalized numbers where precision is required can pose a risk.
Rule NUM04-J.
• The following code tests whether a float value is denormalized in FP-strict mode or for
platforms that lack extended-range support.
• Floats and normalized doubles, when formatted with the %a specifier, begin with a
leading nonzero digit. Denormalized doubles can begin with a leading zero to the left
of the decimal point in the mantissa.
Output:
Exceptions:
Risk Assessment
Floating-point numbers are an approximation; denormalized floating-point numbers
are a less precise approximation. The use of denormalized numbers can cause an
unexpected loss of precision, possibly leading to incorrect or unexpected results.
Although the severity for violations of this rule is low, applications that require
accurate results should make every attempt to comply.