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 uses datetime.timedelta()
to get x
hours in the future or past for time travelers. The datetime
is interfacing with the operating system through the libpython
library written in C
. Overall the Georgian calender ISO 8601 is limited to 1 - 9999 years Python datetime 2025.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Noncompliant Code Example"""
from datetime import datetime, timedelta
def get_datetime(currtime: datetime, hours: int):
"""
Gets the time n hours in the future or past
Parameters:
currtime (datetime): A datetime object with the starting datetime.
hours (int): Hours going forward or backwards
Returns:
datetime: A datetime object
"""
return currtime + timedelta(hours=hours)
#####################
# attempting to exploit above code example
#####################
datetime.fromtimestamp(0)
currtime = datetime.fromtimestamp(1) # 1st Jan 1970
# OK values are expected to work
# NOK values trigger OverflowErrors in libpython written in C
hours_list = [
0, # OK
1, # OK
70389526, # OK
70389527, # NOK
51539700001, # NOK
24000000001, # NOK
-1, # OK
-17259889, # OK
-17259890, # NOK
-23999999999, # NOK
-51539699999, # NOK
]
for hours in hours_list:
try:
result = get_datetime(currtime, hours)
print(f"{hours} OK, datetime='{result}'")
except Exception as exception:
print(f"{hours} {repr(exception)}")
The noncompliant02.py
code is triggering various OverflowError
exceptions in the libpython
library:
date value out of range
OverflowError('Python int too large to convert to C int')
days=1000000000; must have magnitude <= 999999999
This compliant02.py
solution is preventing OverflowError
exception in libpython
by safeguarding the upper and lower limits in the provided hours
. Upper and lower limit for currtime
as well as input sanitization and secure logging are missing and must be added when interfacing with a lesser trusted entity.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Compliant Code Example"""
from datetime import datetime, timedelta
import logging
# Enabling verbose debugging
# logging.basicConfig(level=logging.DEBUG)
def get_datetime(currtime: datetime, hours: int):
"""
Gets the time n hours in the future or past
Parameters:
currtime (datetime): A datetime object with the starting datetime.
hours (int): Hours going forward or backwards
Returns:
datetime: A datetime object
"""
# TODO: input sanitation
# Calculate lower boundary, hours from year 1 to currtime:
timedelta_lowerbound = currtime - datetime(1, 1, 1) # 1st Jan 0001
hours_min = timedelta_lowerbound.total_seconds() // 3600 * -1
# Calculate upper boundary, hours from year 9999 to currtime:
timedelta_upperbound = datetime(9999, 12, 31) - currtime
hours_max = timedelta_upperbound.total_seconds() // 3600
# TODO: proper secure logging
logging.debug(
"hours_max=%s hours_min=%s hours=%s",
hours_max,
hours_min,
hours,
)
if (hours > hours_max) or (hours < hours_min):
raise ValueError("hours out of range")
return currtime + timedelta(hours=hours)
#####################
# attempting to exploit above code example
#####################
datetime.fromtimestamp(0)
currtime = datetime.fromtimestamp(1) # 1st Jan 1970
# OK values are expected to work
# NOK values trigger OverflowErrors in libpython written in C
hours_list = [
0, # OK
1, # OK
70389526, # OK
70389527, # NOK
51539700001, # NOK
24000000001, # NOK
-1, # OK
-17259889, # OK
-17259890, # NOK
-23999999999, # NOK
-51539699999, # NOK
]
for hours in hours_list:
try:
result = get_datetime(currtime, hours)
print(f"{hours} OK, datetime='{result}'")
except Exception as exception:
print(f"{hours} {repr(exception)}")
The compliant02.py
example is protecting the lower level c-lib from an OverflowError
by setting boundaries for valid values in hours
. Similar issues occure with any functionality provided through the operating system.
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. [online] Available from: https://docs.python.org/3.9/library/stdtypes.html [Accessed 20 June 2024] |
[cpython 2024] | mathmodule.c. [online] Available from: https://github.com/python/cpython/blob/main/Modules/mathmodule.c) [Accessed 20 June 2024] |
[Python datetime 2025] | datetime strftime() and strptime() Format Codes [online], Available from: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes [Accessed 27 March 2025] |