Skip to content

Commit

Permalink
Problem: overriding postgres symbols
Browse files Browse the repository at this point in the history
Solution: add a target that checks if Postgres and a Postgres extension have
conflicting symbols. If conflicting symbols are detected the build shall fail.
  • Loading branch information
UkuLoskit committed Apr 16, 2024
1 parent ddfb860 commit 1538f36
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
12 changes: 11 additions & 1 deletion cmake/PostgreSQLExtension.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ function(add_postgresql_extension NAME)
add_library(${_ext_TARGET} MODULE ${_ext_SOURCES})
endif()

# inja ia a default target dependency for all extensions
# inja ia a default target dependency for all extensions
if(NOT TARGET inja)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../misc/inja" "${CMAKE_CURRENT_BINARY_DIR}/inja")
endif()
Expand Down Expand Up @@ -255,6 +255,16 @@ function(add_postgresql_extension NAME)
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
endif()

# Check that the extension has no conflicting symbols with the Postgres binary
# otherwise the linker might use the symbols from Postgres
find_package(Python COMPONENTS Interpreter REQUIRED)
execute_process(COMMAND dirname ${PG_CTL} OUTPUT_VARIABLE POSTGRES_BINARY)
get_filename_component(POSTGRES_BINARY ${PG_CTL}/../postgres ABSOLUTE)
set(SO_FILE "${CMAKE_CURRENT_BINARY_DIR}/${_ext_TARGET}${_suffix}")
add_custom_target(omni_check_symbol_conflict_${_ext_TARGET} ALL
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/check_symbol_conflict.py ${POSTGRES_BINARY} ${SO_FILE})

set(_pkg_dir "${CMAKE_BINARY_DIR}/packaged")

if(_ext_SOURCES)
Expand Down
35 changes: 35 additions & 0 deletions cmake/check_symbol_conflict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import platform
import subprocess
import sys


def get_symbols(binary):
symbols = set()
args = ["nm"]
if platform.system() == "Darwin":
args += ["-g", "-U", binary]
elif platform.system() == "Linux":
args += ["-g", "--defined-only", binary]
else:
raise Exception("Unsupported platform %s" % platform.system())
res = subprocess.run(args, stdout=subprocess.PIPE)
for line in res.stdout.decode("utf-8").split("\n"):
# skip over empty lines and lines that are not symbols
if line.strip() and "for architecture" not in line:
symbols.add(line.split(" ")[2])
return symbols



if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: %s <binary1> <binary2>" % sys.argv[0])
sys.exit(1)
binary1, binary2 = sys.argv[1:]
symbols1 = get_symbols(binary1)
symbols2 = get_symbols(binary2)
intersection = symbols1 & symbols2
if symbols1 & symbols2:
sys.stderr.write("Found symbols that are present in both binaries:\n")
sys.stderr.write("\n".join(intersection))
sys.exit(1)

0 comments on commit 1538f36

Please sign in to comment.