Skip to content

Commit

Permalink
Fix integer overflow
Browse files Browse the repository at this point in the history
  • Loading branch information
kimwalisch committed Jan 8, 2024
1 parent e7658c1 commit 3b116eb
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 19 deletions.
3 changes: 2 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Changes in primecount-7.10, 2024-01-02
Changes in primecount-7.10, 2024-01-08

* RiemannR.cpp: Fix integer overflows in Li_inverse(x) & Ri_inverse(x).
* cmake/OpenMP.cmake: Improve libatomic detection.
* .github/workflows/ci.yml: Port AppVeyor CI tests to GitHub Actions.
* Vector.hpp: Rename pod_vector to Vector and pod_array to Array.
Expand Down
76 changes: 60 additions & 16 deletions src/RiemannR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,34 +375,56 @@ int64_t Li(int64_t x)
return (int64_t) ::Li((long double) x);
}

int64_t Li_inverse(int64_t x)
int64_t Ri(int64_t x)
{
#if defined(HAVE_FLOAT128)
if (x > 1e14)
return (int64_t) ::Li_inverse((__float128) x);
return (int64_t) ::Ri((__float128) x);
#endif

return (int64_t) ::Li_inverse((long double) x);
return (int64_t) ::Ri((long double) x);
}

int64_t Ri(int64_t x)
int64_t Li_inverse(int64_t x)
{
#if defined(HAVE_FLOAT128)
if (x > 1e14)
return (int64_t) ::Ri((__float128) x);
{
__float128 res = ::Li_inverse((__float128) x);
if (res > (__float128) std::numeric_limits<int64_t>::max())
return std::numeric_limits<int64_t>::max();
return (int64_t) res;
}
#endif

return (int64_t) ::Ri((long double) x);
long double res = ::Li_inverse((long double) x);

// Prevent integer overflow
if (res > (long double) std::numeric_limits<int64_t>::max())
return std::numeric_limits<int64_t>::max();

return (int64_t) res;
}

int64_t Ri_inverse(int64_t x)
{
#if defined(HAVE_FLOAT128)
if (x > 1e14)
return (int64_t) ::Ri_inverse((__float128) x);
{
__float128 res = ::Ri_inverse((__float128) x);
if (res > (__float128) std::numeric_limits<int64_t>::max())
return std::numeric_limits<int64_t>::max();
return (int64_t) res;
}
#endif

return (int64_t) ::Ri_inverse((long double) x);
long double res = ::Ri_inverse((long double) x);

// Prevent integer overflow
if (res > (long double) std::numeric_limits<int64_t>::max())
return std::numeric_limits<int64_t>::max();

return (int64_t) res;
}

#ifdef HAVE_INT128_T
Expand All @@ -417,34 +439,56 @@ int128_t Li(int128_t x)
return (int128_t) ::Li((long double) x);
}

int128_t Li_inverse(int128_t x)
int128_t Ri(int128_t x)
{
#if defined(HAVE_FLOAT128)
if (x > 1e14)
return (int128_t) ::Li_inverse((__float128) x);
return (int128_t) ::Ri((__float128) x);
#endif

return (int128_t) ::Li_inverse((long double) x);
return (int128_t) ::Ri((long double) x);
}

int128_t Ri(int128_t x)
int128_t Li_inverse(int128_t x)
{
#if defined(HAVE_FLOAT128)
if (x > 1e14)
return (int128_t) ::Ri((__float128) x);
{
__float128 res = ::Li_inverse((__float128) x);
if (res > (__float128) std::numeric_limits<int128_t>::max())
return std::numeric_limits<int128_t>::max();
return (int128_t) res;
}
#endif

return (int128_t) ::Ri((long double) x);
long double res = ::Li_inverse((long double) x);

// Prevent integer overflow
if (res > (long double) std::numeric_limits<int128_t>::max())
return std::numeric_limits<int128_t>::max();

return (int128_t) res;
}

int128_t Ri_inverse(int128_t x)
{
#if defined(HAVE_FLOAT128)
if (x > 1e14)
return (int128_t) ::Ri_inverse((__float128) x);
{
__float128 res = ::Ri_inverse((__float128) x);
if (res > (__float128) std::numeric_limits<int128_t>::max())
return std::numeric_limits<int128_t>::max();
return (int128_t) res;
}
#endif

return (int128_t) ::Ri_inverse((long double) x);
long double res = ::Ri_inverse((long double) x);

// Prevent integer overflow
if (res > (long double) std::numeric_limits<int128_t>::max())
return std::numeric_limits<int128_t>::max();

return (int128_t) res;
}

#endif
Expand Down
25 changes: 24 additions & 1 deletion test/Li.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
/// @brief Test the offset logarithmic integral function.
/// Li(x) = li(x) - li(2)
///
/// Copyright (C) 2021 Kim Walisch, <[email protected]>
/// Copyright (C) 2024 Kim Walisch, <[email protected]>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <int128_t.hpp>
#include <imath.hpp>

#include <stdint.h>
Expand Down Expand Up @@ -97,6 +98,28 @@ int main()
}
}

{
int64_t x = std::numeric_limits<int64_t>::max() / 10;
int64_t res = Li_inverse(x);
if (res != std::numeric_limits<int64_t>::max())
{
std::cout << "Li_inverse(" << x << ") != INT64_MAX, failed to prevent integer overflow!" << std::endl;
std::exit(1);
}
}

#if defined(HAVE_INT128_T)
{
int128_t x = std::numeric_limits<int128_t>::max() / 10;
int128_t res = Li_inverse(x);
if (res != std::numeric_limits<int128_t>::max())
{
std::cout << "Li_inverse(" << x << ") != INT128_MAX, failed to prevent integer overflow!" << std::endl;
std::exit(1);
}
}
#endif

std::cout << std::endl;
std::cout << "All tests passed successfully!" << std::endl;

Expand Down
25 changes: 24 additions & 1 deletion test/Ri.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
/// @file Ri.cpp
/// @brief Test the Riemann R function.
///
/// Copyright (C) 2021 Kim Walisch, <[email protected]>
/// Copyright (C) 2024 Kim Walisch, <[email protected]>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <int128_t.hpp>
#include <imath.hpp>

#include <stdint.h>
Expand Down Expand Up @@ -126,6 +127,28 @@ int main()
}
}

{
int64_t x = std::numeric_limits<int64_t>::max() / 10;
int64_t res = Ri_inverse(x);
if (res != std::numeric_limits<int64_t>::max())
{
std::cout << "Ri_inverse(" << x << ") != INT64_MAX, failed to prevent integer overflow!" << std::endl;
std::exit(1);
}
}

#if defined(HAVE_INT128_T)
{
int128_t x = std::numeric_limits<int128_t>::max() / 10;
int128_t res = Ri_inverse(x);
if (res != std::numeric_limits<int128_t>::max())
{
std::cout << "Ri_inverse(" << x << ") != INT128_MAX, failed to prevent integer overflow!" << std::endl;
std::exit(1);
}
}
#endif

std::cout << std::endl;
std::cout << "All tests passed successfully!" << std::endl;

Expand Down

0 comments on commit 3b116eb

Please sign in to comment.