Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.20260708.0
1.20260708.1
10 changes: 8 additions & 2 deletions src/bindings/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ if(LIBOPENCOR_PYTHON_BINDINGS)

set(PYTHON_BINDINGS_DIR ${CMAKE_BINARY_DIR}/tests/bindings/python CACHE INTERNAL "Python bindings directory.")

# Check whether we need to provide a glibc compatibility wrapper for __isoc23_strtol() and __isoc23_strtoll().
# Check whether we need to provide a glibc compatibility wrapper for __isoc23_strtol(), __isoc23_strtoll(),
# __isoc23_strtoul(), and __isoc23_strtoull().
# Note: indeed, they are used by our prebuilt LLVM+Clang and libssh2 libraries which are compiled using glibc 2.38+
# (Ubuntu 24.04 LTS on GitHub Actions), but there are currently no versions of manylinux that uses glibc
# 2.38+, so we need to provide a compatibility wrapper for these functions in order to be able to build our
Expand All @@ -44,10 +45,15 @@ if(LIBOPENCOR_PYTHON_BINDINGS)

check_symbol_exists(__isoc23_strtol stdlib.h LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOL)
check_symbol_exists(__isoc23_strtoll stdlib.h LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOLL)
check_symbol_exists(__isoc23_strtoul stdlib.h LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOUL)
check_symbol_exists(__isoc23_strtoull stdlib.h LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOULL)

set(ACTUAL_PYTHON_SOURCE_FILES ${PYTHON_SOURCE_FILES})

if(LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOL AND LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOLL)
if( LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOL
AND LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOLL
AND LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOUL
AND LIBOPENCOR_GLIBC_HAS_ISOC23_STRTOULL)
list(REMOVE_ITEM ACTUAL_PYTHON_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/glibc.cpp)
endif()

Expand Down
24 changes: 18 additions & 6 deletions src/bindings/python/glibc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ limitations under the License.
*/

#if defined(__linux__) && defined(__GNUC__)
// On glibc 2.38+, strtol() and strtoll() are redirected to __isoc23_strtol() and __isoc23_strtoll(), respectively,
// either via preprocessor macro (Intel) or via __asm__("__isoc23_strtol") on the declaration (ARM). The latter is a
// compiler-level redirect that cannot be undone with #undef, so calling strtol() inside our __isoc23_strtol() wrapper
// would cause infinite recursion on ARM. To bypass this, we forward-declare strtol()/strtoll() ourselves without the
// compiler-level redirect, giving us a direct reference to glibc's implementation unaffected by any asm redirect on the
// standard names.
// On glibc 2.38+, strtol(), strtoll(), strtoul(), and strtoull() are redirected to __isoc23_strtol(),
// __isoc23_strtoll(), __isoc23_strtoul(), and __isoc23_strtoull(), respectively, either via preprocessor macro (Intel)
// or via __asm__("__isoc23_*") on the declaration (ARM). The latter is a compiler-level redirect that cannot be undone
// with #undef, so calling strtol() inside our __isoc23_strtol() wrapper would cause infinite recursion on ARM. To
// bypass this, we forward-declare the underlying functions ourselves without the compiler-level redirect, giving us a
// direct reference to glibc's implementation unaffected by any asm redirect on the standard names.

extern "C" {
long strtol(const char *pString, char **pEndPtr, int pBase);
long long strtoll(const char *pString, char **pEndPtr, int pBase);
unsigned long strtoul(const char *pString, char **pEndPtr, int pBase);
unsigned long long strtoull(const char *pString, char **pEndPtr, int pBase);

__attribute__((weak)) long __isoc23_strtol(const char *pString, char **pEndPtr, int pBase)
{
Expand All @@ -35,6 +37,16 @@ __attribute__((weak)) long long __isoc23_strtoll(const char *pString, char **pEn
{
return strtoll(pString, pEndPtr, pBase);
}

__attribute__((weak)) unsigned long __isoc23_strtoul(const char *pString, char **pEndPtr, int pBase)
{
return strtoul(pString, pEndPtr, pBase);
}

__attribute__((weak)) unsigned long long __isoc23_strtoull(const char *pString, char **pEndPtr, int pBase)
{
return strtoull(pString, pEndPtr, pBase);
}
}

#endif
Loading