Ensure that integer overflow is properly handled in order to avoid unexpected behavior. Python data types can be divided into two categories:
Built-in types such as int
, float
, or complex
[Python 2024]. These types are provided by classes and are protected against overflows.
Primitive types share issues known from C
, or C++
and appear in Python
to:
time
.numpy
or ctype
.Developers should follow the C
guidelines when using or interacting wth C
type variables.
Using a numpy.int64
can cause an unintentional flip of its sign when reaching the maximum number that can be stored as demonstrated in noncompliant01.py
.
""" Non-compliant Code Example """
import numpy
a = numpy.int64(numpy.iinfo(numpy.int64).max)
print(a + 1) # RuntimeWarning and continues
print()
b = numpy.int64(numpy.iinfo(numpy.int64).max + 1) # OverflowError and stops
print(b) # we will never reach this
Adding +1
to 9223372036854775807
results in a negative number -9223372036854775808
and throws a RuntimeWarning
but continues.
An attempt to create int
from a too big number causes an OverflowError
and stops.
[!NOTE] It has been observed that different results may occur depending on the version of
numpy
. For reference, we are usingnumpy 1.23.1
and Python3.9.12.
The compliant01.py
code detects the integer overflow by catching the appropriate Exception.
""" Compliant Code Example """
import warnings
import numpy
warnings.filterwarnings("error")
a = numpy.int64(numpy.iinfo(numpy.int64).max)
with warnings.catch_warnings():
try:
print(a + 1)
except Warning as _:
print("Failed to increment " + str(a) + " due to overflow error")
# RuntimeWarning and continues
try:
b = numpy.int64(numpy.iinfo(numpy.int64).max + 1) # OverflowError and stops
except OverflowError as e:
print("Failed to assign value to B due to overflow error")
The noncompliant02.py
example tries to use time.localtime()
to get x
hours in the future but causes integer overflow as the given Python int
is too large to convert to C long
. This is possible because time
implements C representations of integers with all the security vulnerabilities as if you were using C
.
""" Non-compliant Code Example """
import time
def get_time_in_future(hours_in_future):
"""Gets the time n hours in the future"""
currtime = [tm for tm in time.localtime()]
currtime[3] = currtime[3] + hours_in_future
if currtime[3] + hours_in_future > 24:
currtime[3] = currtime[3] - 24
return time.asctime(tuple(currtime)).split(" ")[3]
#####################
# exploiting above code example
#####################
print(get_time_in_future(23**74))
This compliant02.py
solution handles OverflowError
Exception when a too large value is given to get_time_in_future
.
""" Compliant Code Example """
import time
def get_time_in_future(hours_in_future):
"""Gets the time n hours in the future"""
try:
currtime = list(time.localtime())
currtime[3] = currtime[3] + hours_in_future
if currtime[3] + hours_in_future > 24:
currtime[3] = currtime[3] - 24
return time.asctime(tuple(currtime)).split(" ")[3]
except OverflowError as _:
return "Number too large to set time in future " + str(hours_in_future)
#####################
# attempting to exploit above code example
#####################
print(get_time_in_future(23**74))
The noncompliant03.py
code example results in a OverflowError: math range error
. This is due to math.exp
being a C
implementation behind the scenes for better performance. So while it returns a Python float
it does use C
type of variables internally for the calculation in mathmodule.c
[cpython 2024].
""" Non-compliant Code Example """
import math
def calculate_exponential_value(number):
"""Return 'E' raised to the power of different numbers:"""
return math.exp(number)
#####################
# attempting to exploit above code example
#####################
print(calculate_exponential_value(1000))
This compliant03.py
solution detects the integer
overflow by catching the appropriate Exception on overflow:
""" Compliant Code Example """
import math
def calculate_exponential_value(number):
"""Return 'E' raised to the power of different numbers:"""
try:
return math.exp(number)
except OverflowError as _:
return "Number " + str(number) + " caused an integer overflow"
#####################
# attempting to exploit above code example
#####################
print(calculate_exponential_value(710))
[Python 2024] | Format String Syntax. Available from: https://docs.python.org/3.9/library/stdtypes.html [Accessed 20 June 2024] |
[cpython 2024] | mathmodule.c. Available from: https://github.com/python/cpython/blob/main/Modules/mathmodule.c) [Accessed 20 June 2024] |