[DO-981] qt package (!15)

Co-authored-by: aleksandr.vodyanov <aleksandr.vodyanov@avroid.tech>
Reviewed-on: https://git.avroid.tech/Conan/conan_build/pulls/15
This commit is contained in:
Aleksandr Vodyanov
2025-02-13 12:25:48 +03:00
parent 60445ac09e
commit 3759e1163f
228 changed files with 16106 additions and 12 deletions

View File

@@ -0,0 +1,39 @@
sources:
"15.5":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v15.5/postgresql-15.5.tar.bz2"
sha256: "8f53aa95d78eb8e82536ea46b68187793b42bba3b4f65aa342f540b23c9b10a6"
"15.4":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v15.4/postgresql-15.4.tar.bz2"
sha256: "baec5a4bdc4437336653b6cb5d9ed89be5bd5c0c58b94e0becee0a999e63c8f9"
"15.3":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v15.3/postgresql-15.3.tar.bz2"
sha256: "ffc7d4891f00ffbf5c3f4eab7fbbced8460b8c0ee63c5a5167133b9e6599d932"
"14.9":
url: "https://nexus.avroid.tech/repository/all-raw-proxy-ftp_postgresql_org/pub/source/v14.9/postgresql-14.9.tar.bz2"
sha256: "b1fe3ba9b1a7f3a9637dd1656dfdad2889016073fd4d35f13b50143cbbb6a8ef"
patches:
"15.5":
- patch_file: "patches/15/001-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"
- patch_file: "patches/15.5/0001-Use-BIO_-get-set-_app_data-instead-of-BIO_-get-se.patch"
patch_description: "Fix libpq w/ openssl >=3.2.x"
patch_type: "backport"
"15.4":
- patch_file: "patches/15/001-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"
- patch_file: "patches/15/0001-Use-BIO_-get-set-_app_data-instead-of-BIO_-get-se.patch"
patch_description: "Fix libpq w/ openssl >=3.2.x"
patch_type: "backport"
"15.3":
- patch_file: "patches/15/001-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"
- patch_file: "patches/15/0001-Use-BIO_-get-set-_app_data-instead-of-BIO_-get-se.patch"
patch_description: "Fix libpq w/ openssl >=3.2.x"
patch_type: "backport"
"14.9":
- patch_file: "patches/14/002-mingw-build-static-libraries.patch"
patch_description: "port MinGW: Enable building static libraries in MinGW."
patch_type: "portability"

View File

@@ -0,0 +1,288 @@
from conan import ConanFile
from conan.tools.apple import fix_apple_shared_install_name
from conan.tools.build import cross_building
from conan.tools.env import Environment, VirtualBuildEnv, VirtualRunEnv
from conan.tools.files import apply_conandata_patches, chdir, copy, export_conandata_patches, get, replace_in_file, rm, rmdir
from conan.tools.gnu import Autotools, AutotoolsToolchain, AutotoolsDeps
from conan.tools.layout import basic_layout
from conan.tools.microsoft import is_msvc, msvc_runtime_flag, unix_path, VCVars
from conan.tools.scm import Version
import glob
import os
required_conan_version = ">=1.54.0"
class LibpqConan(ConanFile):
name = "libpq"
description = "The library used by all the standard PostgreSQL tools."
topics = ("postgresql", "database", "db")
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://www.postgresql.org/docs/current/static/libpq.html"
license = "PostgreSQL"
package_type = "library"
settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"fPIC": [True, False],
"with_openssl": [True, False],
"disable_rpath": [True, False],
}
default_options = {
"shared": False,
"fPIC": True,
"with_openssl": False,
"disable_rpath": False,
}
@property
def _is_clang8_x86(self):
return self.settings.os == "Linux" and \
self.settings.compiler == "clang" and \
self.settings.compiler.version == "8" and \
self.settings.arch == "x86"
@property
def _settings_build(self):
return getattr(self, "settings_build", self.settings)
def export_sources(self):
export_conandata_patches(self)
def config_options(self):
if self.settings.os == "Windows":
self.options.rm_safe("fPIC")
self.options.rm_safe("disable_rpath")
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.settings.rm_safe("compiler.libcxx")
self.settings.rm_safe("compiler.cppstd")
def layout(self):
basic_layout(self, src_folder="src")
def requirements(self):
if self.options.with_openssl:
self.requires("openssl/[>=1.1 <4]")
def build_requirements(self):
if is_msvc(self):
self.tool_requires("strawberryperl/5.32.1.1")
elif self._settings_build.os == "Windows":
self.win_bash = True
if not self.conf.get("tools.microsoft.bash:path", check_type=str):
self.tool_requires("msys2/cci.latest")
def source(self):
get(self, **self.conan_data["sources"][self.version], strip_root=True)
def generate(self):
env = VirtualBuildEnv(self)
env.generate()
if is_msvc(self):
vcvars = VCVars(self)
vcvars.generate()
config = "DEBUG" if self.settings.build_type == "Debug" else "RELEASE"
env = Environment()
env.define("CONFIG", config)
env.vars(self).save_script("conanbuild_msvc")
else:
if not cross_building(self):
env = VirtualRunEnv(self)
env.generate(scope="build")
tc = AutotoolsToolchain(self)
tc.configure_args.append('--without-readline')
tc.configure_args.append('--without-zlib')
tc.configure_args.append('--with-openssl' if self.options.with_openssl else '--without-openssl')
if cross_building(self) and not self.options.with_openssl:
tc.configure_args.append("--disable-strong-random")
if cross_building(self, skip_x64_x86=True):
tc.configure_args.append("USE_DEV_URANDOM=1")
if self.settings.os != "Windows" and self.options.disable_rpath:
tc.configure_args.append('--disable-rpath')
if self._is_clang8_x86:
tc.extra_cflags.append("-msse2")
tc.make_args.append(f"DESTDIR={unix_path(self, self.package_folder)}")
if self.settings.os == "Windows":
tc.make_args.append("MAKE_DLL={}".format(str(self.options.shared).lower()))
tc.generate()
AutotoolsDeps(self).generate()
def _patch_sources(self):
if is_msvc(self):
# https://www.postgresql.org/docs/8.3/install-win32-libpq.html
# https://github.com/postgres/postgres/blob/master/src/tools/msvc/README
if not self.options.shared:
replace_in_file(self,os.path.join(self.source_folder, "src", "tools", "msvc", "MKvcbuild.pm"),
"$libpq = $solution->AddProject('libpq', 'dll', 'interfaces',",
"$libpq = $solution->AddProject('libpq', 'lib', 'interfaces',")
host_deps = [dep for _, dep in self.dependencies.host.items()]
system_libs = []
for dep in host_deps:
system_libs.extend(dep.cpp_info.aggregated_components().system_libs)
linked_system_libs = ", ".join(["'{}.lib'".format(lib) for lib in system_libs])
replace_in_file(self,os.path.join(self.source_folder, "src", "tools", "msvc", "Project.pm"),
"libraries => [],",
"libraries => [{}],".format(linked_system_libs))
runtime = {
"MT": "MultiThreaded",
"MTd": "MultiThreadedDebug",
"MD": "MultiThreadedDLL",
"MDd": "MultiThreadedDebugDLL",
}.get(msvc_runtime_flag(self))
msbuild_project_pm = os.path.join(self.source_folder, "src", "tools", "msvc", "MSBuildProject.pm")
replace_in_file(self,msbuild_project_pm, "</Link>", """</Link>
<Lib>
<TargetMachine>$targetmachine</TargetMachine>
</Lib>""")
replace_in_file(self,msbuild_project_pm, "'MultiThreadedDebugDLL'", "'%s'" % runtime)
replace_in_file(self,msbuild_project_pm, "'MultiThreadedDLL'", "'%s'" % runtime)
config_default_pl = os.path.join(self.source_folder, "src", "tools", "msvc", "config_default.pl")
solution_pm = os.path.join(self.source_folder, "src", "tools", "msvc", "Solution.pm")
if self.options.with_openssl:
openssl = self.dependencies["openssl"]
for ssl in ["VC\\libssl32", "VC\\libssl64", "libssl"]:
replace_in_file(self,solution_pm,
"%s.lib" % ssl,
"%s.lib" % openssl.cpp_info.components["ssl"].libs[0])
for crypto in ["VC\\libcrypto32", "VC\\libcrypto64", "libcrypto"]:
replace_in_file(self,solution_pm,
"%s.lib" % crypto,
"%s.lib" % openssl.cpp_info.components["crypto"].libs[0])
replace_in_file(self,config_default_pl,
"openssl => undef",
"openssl => '%s'" % openssl.package_folder.replace("\\", "/"))
elif self.settings.os == "Windows":
if self.settings.get_safe("compiler.threads") == "posix":
# Use MinGW pthread library
replace_in_file(self, os.path.join(self.source_folder, "src", "interfaces", "libpq", "Makefile"),
"ifeq ($(enable_thread_safety), yes)\nOBJS += pthread-win32.o\nendif",
"")
# When linking to static openssl, it comes with static pthread library too, failing with:
# libpq.so.5.15: U pthread_exit@GLIBC_2.2.5: libpq must not be calling any function which invokes exit
# https://www.postgresql.org/message-id/20210703001639.GB2374652%40rfd.leadboat.com
if Version(self.version) >= "15":
replace_in_file(self, os.path.join(self.source_folder, "src", "interfaces", "libpq", "Makefile"),
"-v __cxa_atexit",
"-v __cxa_atexit -e pthread_exit")
def build(self):
apply_conandata_patches(self)
self._patch_sources()
if is_msvc(self):
with chdir(self, os.path.join(self.source_folder, "src", "tools", "msvc")):
self.run("perl build.pl libpq")
if not self.options.shared:
self.run("perl build.pl libpgport")
else:
autotools = Autotools(self)
with chdir(self, os.path.join(self.build_folder)):
autotools.configure()
with chdir(self, os.path.join(self.build_folder, "src", "backend")):
autotools.make(target="generated-headers")
with chdir(self, os.path.join(self.build_folder, "src", "common")):
autotools.make()
with chdir(self, os.path.join(self.build_folder, "src", "include")):
autotools.make()
with chdir(self, os.path.join(self.build_folder, "src", "interfaces", "libpq")):
autotools.make()
if Version(self.version) >= 12:
with chdir(self, os.path.join(self.build_folder, "src", "port")):
autotools.make()
with chdir(self, os.path.join(self.build_folder, "src", "bin", "pg_config")):
autotools.make()
def _remove_unused_libraries_from_package(self):
bin_folder = os.path.join(self.package_folder, "bin")
lib_folder = os.path.join(self.package_folder, "lib")
rm(self, "*.dll", lib_folder)
if self.options.shared:
for lib in glob.glob(os.path.join(lib_folder, "*.a")):
if not (self.settings.os == "Windows" and os.path.basename(lib) == "libpq.dll.a"):
os.remove(lib)
else:
rm(self, "*.dll", bin_folder)
rm(self, "*.dll.a", lib_folder)
rm(self, "*.so*", lib_folder)
rm(self, "*.dylib", lib_folder)
def package(self):
copy(self, "COPYRIGHT", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
if is_msvc(self):
copy(self, pattern="*postgres_ext.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*pg_config.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*pg_config_ext.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*libpq-fe.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*libpq-events.h", dst=os.path.join(self.package_folder, "include"), src=self.source_folder, keep_path=False)
copy(self, pattern="*.h", src=os.path.join(self.source_folder, "src", "include", "libpq"),
dst=os.path.join(self.package_folder, "include", "libpq"),
keep_path=False)
copy(self, pattern="*genbki.h", src=self.source_folder, dst=os.path.join(self.package_folder, "include", "catalog"), keep_path=False)
copy(self, pattern="*pg_type.h", src=self.source_folder, dst=os.path.join(self.package_folder, "include", "catalog"), keep_path=False)
if self.options.shared:
copy(self, pattern="**/libpq.dll", dst=os.path.join(self.package_folder, "bin"), src=self.source_folder, keep_path=False)
copy(self, pattern="**/libpq.lib", dst=os.path.join(self.package_folder, "lib"), src=self.source_folder, keep_path=False)
else:
copy(self, pattern="*.lib", dst=os.path.join(self.package_folder, "lib"), src=self.source_folder, keep_path=False)
else:
autotools = Autotools(self)
with chdir(self, os.path.join(self.build_folder, "src", "common")):
autotools.install()
with chdir(self, os.path.join(self.build_folder, "src", "include")):
autotools.install()
with chdir(self, os.path.join(self.build_folder, "src", "interfaces", "libpq")):
autotools.install()
if Version(self.version) >= 12:
with chdir(self, os.path.join(self.build_folder, "src", "port")):
autotools.install()
with chdir(self, os.path.join(self.build_folder, "src", "bin", "pg_config")):
autotools.install()
copy(self, "*.h", src=os.path.join(self.source_folder, "src", "include", "catalog"),
dst=os.path.join(self.package_folder, "include", "catalog"))
rmdir(self, os.path.join(self.package_folder, "share"))
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "include", "postgresql", "server"))
self._remove_unused_libraries_from_package()
fix_apple_shared_install_name(self)
copy(self, "*.h", src=os.path.join(self.source_folder, "src", "backend", "catalog"),
dst=os.path.join(self.package_folder, "include", "catalog"))
def package_info(self):
self.cpp_info.set_property("cmake_find_mode", "both")
self.cpp_info.set_property("cmake_file_name", "PostgreSQL")
self.cpp_info.set_property("cmake_target_name", "PostgreSQL::PostgreSQL")
self.cpp_info.set_property("pkg_config_name", "libpq")
self.env_info.PostgreSQL_ROOT = self.package_folder
self.cpp_info.components["pq"].libs = [f"{'lib' if is_msvc(self) else ''}pq"]
if self.options.with_openssl:
self.cpp_info.components["pq"].requires.append("openssl::openssl")
if not self.options.shared:
if is_msvc(self):
self.cpp_info.components["pgport"].libs = ["libpgport"]
self.cpp_info.components["pq"].requires.append("pgport")
self.cpp_info.components["pgcommon"].libs = ["libpgcommon"]
self.cpp_info.components["pq"].requires.append("pgcommon")
else:
self.cpp_info.components["pgcommon"].libs = ["pgcommon"]
self.cpp_info.components["pq"].requires.append("pgcommon")
self.cpp_info.components["pgcommon"].libs.append("pgcommon_shlib")
self.cpp_info.components["pgport"].libs = ["pgport", "pgport_shlib"]
if self.settings.os == "Windows":
self.cpp_info.components["pgport"].system_libs = ["ws2_32"]
self.cpp_info.components["pgcommon"].requires.append("pgport")
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["pq"].system_libs = ["pthread"]
elif self.settings.os == "Windows":
self.cpp_info.components["pq"].system_libs = ["ws2_32", "secur32", "advapi32", "shell32", "crypt32", "wldap32"]
self.cpp_info.names["cmake_find_package"] = "PostgreSQL"
self.cpp_info.names["cmake_find_package_multi"] = "PostgreSQL"

View File

@@ -0,0 +1,39 @@
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -358,7 +358,10 @@ else
# Win32 case
# See notes in src/backend/parser/Makefile about the following two rules
-$(stlib): $(shlib)
+$(stlib): $(OBJS) | $(SHLIB_PREREQS)
+ rm -f $@
+ $(LINK.static) $@ $^
+ $(RANLIB) $@
touch $@
# XXX A backend that loads a module linked with libgcc_s_dw2-1.dll will exit
@@ -371,12 +374,12 @@ $(stlib): $(shlib)
# Else we just use --export-all-symbols.
ifeq (,$(SHLIB_EXPORTS))
$(shlib): $(OBJS) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=lib$(NAME).dll.a
else
DLL_DEFFILE = lib$(NAME)dll.def
$(shlib): $(OBJS) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=lib$(NAME).dll.a
UC_NAME = $(shell echo $(NAME) | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
@@ -452,6 +455,9 @@ endif # not aix
ifneq (,$(findstring $(PORTNAME),win32 cygwin))
$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
endif
+ifneq (,$(findstring $(PORTNAME),win32))
+ $(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/lib$(NAME).dll.a'
+endif
else # no soname
$(INSTALL_SHLIB) $< '$(DESTDIR)$(pkglibdir)/$(shlib)'
endif

View File

@@ -0,0 +1,193 @@
From 672103a67aaf0dae5be6c5adcc5ce19e5b6d7676 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@neon.tech>
Date: Mon, 27 Nov 2023 11:49:52 -0600
Subject: [PATCH v1] Use BIO_{get,set}_app_data() instead of
BIO_{get,set}_data()
Compiling Postgres against OpenSSL 3.2 exposed a regression:
$ psql "postgresql://$DB?sslmode=require"
psql: error: connection to server at "redacted" (redacted), port 5432 failed: ERROR: Parameter 'user' is missing in startup packet.
double free or corruption (out)
Aborted (core dumped)
Analyzing the backtrace, openssl was overwriting heap-allocated data in
our PGconn struct because it thought BIO::ptr was a struct bss_sock_st
*. OpenSSL then called a memset() on a member of that struct, and we
zeroed out data in our PGconn struct.
BIO_get_data(3) says the following:
> These functions are mainly useful when implementing a custom BIO.
>
> The BIO_set_data() function associates the custom data pointed to by ptr
> with the BIO a. This data can subsequently be retrieved via a call to
> BIO_get_data(). This can be used by custom BIOs for storing
> implementation specific information.
If you take a look at my_BIO_s_socket(), we create a partially custom
BIO, but for the most part are defaulting to the methods defined by
BIO_s_socket(). We need to set application-specific data and not BIO
private data, so that the BIO implementation we rely on, can properly
assert that its private data is what it expects.
Rebased against libpq15
Co-authored-by: Bo Andreson <mail@boanderson.me>
---
src/backend/libpq/be-secure-openssl.c | 11 +++--------
src/include/pg_config.h.in | 3 ---
src/interfaces/libpq/fe-secure-openssl.c | 20 +++-----------------
src/tools/msvc/Solution.pm | 2 --
4 files changed, 6 insertions(+), 30 deletions(-)
diff --git a/configure b/configure
index d83a402ea1..d55440cd6a 100755
--- a/configure
+++ b/configure
@@ -13239,7 +13239,7 @@ done
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+ for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.ac b/configure.ac
index 570daced81..2bc752ca1a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1347,7 +1347,7 @@ if test "$with_ssl" = openssl ; then
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
+ AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
# OpenSSL versions before 1.1.0 required setting callback functions, for
# thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
# function was removed.
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index f5c5ed210e..aed8a75345 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -839,11 +839,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods = NULL;
static int
@@ -853,7 +848,7 @@ my_sock_read(BIO *h, char *buf, int size)
if (buf != NULL)
{
- res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_read(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -873,7 +868,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res = 0;
- res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_write(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -949,7 +944,7 @@ my_SSL_set_fd(Port *port, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, port);
+ BIO_set_app_data(bio, port);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set_bio(port->ssl, bio, bio);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index d09e9f9a1c..768e3d719c 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -77,9 +77,6 @@
/* Define to 1 if you have the `backtrace_symbols' function. */
#undef HAVE_BACKTRACE_SYMBOLS
-/* Define to 1 if you have the `BIO_get_data' function. */
-#undef HAVE_BIO_GET_DATA
-
/* Define to 1 if you have the `BIO_meth_new' function. */
#undef HAVE_BIO_METH_NEW
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index af59ff49f7..8d68d023e9 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1800,11 +1800,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods;
static int
@@ -1812,7 +1807,7 @@ my_sock_read(BIO *h, char *buf, int size)
{
int res;
- res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_read((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1842,7 +1837,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res;
- res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_write((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1933,7 +1928,7 @@ my_SSL_set_fd(PGconn *conn, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, conn);
+ BIO_set_app_data(bio, conn);
SSL_set_bio(conn->ssl, bio, bio);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 790f03b05e..a53239fa28 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -226,7 +226,6 @@ sub GenerateFiles
HAVE_ATOMICS => 1,
HAVE_ATOMIC_H => undef,
HAVE_BACKTRACE_SYMBOLS => undef,
- HAVE_BIO_GET_DATA => undef,
HAVE_BIO_METH_NEW => undef,
HAVE_CLOCK_GETTIME => undef,
HAVE_COMPUTED_GOTO => undef,
@@ -566,7 +565,6 @@ sub GenerateFiles
|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
{
$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
- $define{HAVE_BIO_GET_DATA} = 1;
$define{HAVE_BIO_METH_NEW} = 1;
$define{HAVE_HMAC_CTX_FREE} = 1;
$define{HAVE_HMAC_CTX_NEW} = 1;
--
Tristan Partin
Neon (https://neon.tech)

View File

@@ -0,0 +1,193 @@
From 672103a67aaf0dae5be6c5adcc5ce19e5b6d7676 Mon Sep 17 00:00:00 2001
From: Tristan Partin <tristan@neon.tech>
Date: Mon, 27 Nov 2023 11:49:52 -0600
Subject: [PATCH v1] Use BIO_{get,set}_app_data() instead of
BIO_{get,set}_data()
Compiling Postgres against OpenSSL 3.2 exposed a regression:
$ psql "postgresql://$DB?sslmode=require"
psql: error: connection to server at "redacted" (redacted), port 5432 failed: ERROR: Parameter 'user' is missing in startup packet.
double free or corruption (out)
Aborted (core dumped)
Analyzing the backtrace, openssl was overwriting heap-allocated data in
our PGconn struct because it thought BIO::ptr was a struct bss_sock_st
*. OpenSSL then called a memset() on a member of that struct, and we
zeroed out data in our PGconn struct.
BIO_get_data(3) says the following:
> These functions are mainly useful when implementing a custom BIO.
>
> The BIO_set_data() function associates the custom data pointed to by ptr
> with the BIO a. This data can subsequently be retrieved via a call to
> BIO_get_data(). This can be used by custom BIOs for storing
> implementation specific information.
If you take a look at my_BIO_s_socket(), we create a partially custom
BIO, but for the most part are defaulting to the methods defined by
BIO_s_socket(). We need to set application-specific data and not BIO
private data, so that the BIO implementation we rely on, can properly
assert that its private data is what it expects.
Rebased against libpq15
Co-authored-by: Bo Andreson <mail@boanderson.me>
---
src/backend/libpq/be-secure-openssl.c | 11 +++--------
src/include/pg_config.h.in | 3 ---
src/interfaces/libpq/fe-secure-openssl.c | 20 +++-----------------
src/tools/msvc/Solution.pm | 2 --
4 files changed, 6 insertions(+), 30 deletions(-)
diff --git a/configure b/configure
index d733a59..c13ad3d 100755
--- a/configure
+++ b/configure
@@ -13237,7 +13237,7 @@ done
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
+ for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.ac b/configure.ac
index 44868ba..77e59a2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1347,7 +1347,7 @@ if test "$with_ssl" = openssl ; then
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
+ AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
# OpenSSL versions before 1.1.0 required setting callback functions, for
# thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
# function was removed.
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 8f9b81c..9abee50 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -830,11 +830,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods = NULL;
static int
@@ -844,7 +839,7 @@ my_sock_read(BIO *h, char *buf, int size)
if (buf != NULL)
{
- res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_read(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -864,7 +859,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res = 0;
- res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size);
+ res = secure_raw_write(((Port *) BIO_get_app_data(h)), buf, size);
BIO_clear_retry_flags(h);
if (res <= 0)
{
@@ -940,7 +935,7 @@ my_SSL_set_fd(Port *port, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, port);
+ BIO_set_app_data(bio, port);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set_bio(port->ssl, bio, bio);
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index d09e9f9..768e3d7 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -77,9 +77,6 @@
/* Define to 1 if you have the `backtrace_symbols' function. */
#undef HAVE_BACKTRACE_SYMBOLS
-/* Define to 1 if you have the `BIO_get_data' function. */
-#undef HAVE_BIO_GET_DATA
-
/* Define to 1 if you have the `BIO_meth_new' function. */
#undef HAVE_BIO_METH_NEW
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c
index af59ff4..8d68d02 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1800,11 +1800,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name)
* to retry; do we need to adopt their logic for that?
*/
-#ifndef HAVE_BIO_GET_DATA
-#define BIO_get_data(bio) (bio->ptr)
-#define BIO_set_data(bio, data) (bio->ptr = data)
-#endif
-
static BIO_METHOD *my_bio_methods;
static int
@@ -1812,7 +1807,7 @@ my_sock_read(BIO *h, char *buf, int size)
{
int res;
- res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_read((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1842,7 +1837,7 @@ my_sock_write(BIO *h, const char *buf, int size)
{
int res;
- res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size);
+ res = pqsecure_raw_write((PGconn *) BIO_get_app_data(h), buf, size);
BIO_clear_retry_flags(h);
if (res < 0)
{
@@ -1933,7 +1928,7 @@ my_SSL_set_fd(PGconn *conn, int fd)
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
- BIO_set_data(bio, conn);
+ BIO_set_app_data(bio, conn);
SSL_set_bio(conn->ssl, bio, bio);
BIO_set_fd(bio, fd, BIO_NOCLOSE);
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 790f03b..a53239f 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -226,7 +226,6 @@ sub GenerateFiles
HAVE_ATOMICS => 1,
HAVE_ATOMIC_H => undef,
HAVE_BACKTRACE_SYMBOLS => undef,
- HAVE_BIO_GET_DATA => undef,
HAVE_BIO_METH_NEW => undef,
HAVE_CLOCK_GETTIME => undef,
HAVE_COMPUTED_GOTO => undef,
@@ -566,7 +565,6 @@ sub GenerateFiles
|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
{
$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
- $define{HAVE_BIO_GET_DATA} = 1;
$define{HAVE_BIO_METH_NEW} = 1;
$define{HAVE_HMAC_CTX_FREE} = 1;
$define{HAVE_HMAC_CTX_NEW} = 1;
--
Tristan Partin
Neon (https://neon.tech)

View File

@@ -0,0 +1,39 @@
--- a/src/Makefile.shlib
+++ b/src/Makefile.shlib
@@ -322,7 +322,10 @@ else # PORTNAME == aix
# AIX case
# See notes in src/backend/parser/Makefile about the following two rules
-$(stlib): $(shlib)
+$(stlib): $(OBJS) | $(SHLIB_PREREQS)
+ rm -f $@
+ $(LINK.static) $@ $^
+ $(RANLIB) $@
touch $@
$(shlib): $(OBJS) | $(SHLIB_PREREQS)
@@ -371,12 +374,12 @@ $(stlib): $(shlib)
# Else we just use --export-all-symbols.
ifeq (,$(SHLIB_EXPORTS))
$(shlib): $(OBJS) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--export-all-symbols -Wl,--out-implib=lib$(NAME).dll.a
else
DLL_DEFFILE = lib$(NAME)dll.def
$(shlib): $(OBJS) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
- $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=$(stlib)
+ $(CC) $(CFLAGS) -shared -static-libgcc -o $@ $(OBJS) $(DLL_DEFFILE) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK) $(LIBS) -Wl,--out-implib=lib$(NAME).dll.a
UC_NAME = $(shell echo $(NAME) | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
@@ -457,6 +460,9 @@ endif # not aix
ifneq (,$(findstring $(PORTNAME),win32 cygwin))
$(INSTALL_SHLIB) $< '$(DESTDIR)$(bindir)/$(shlib)'
endif
+ifneq (,$(findstring $(PORTNAME),win32))
+ $(INSTALL_SHLIB) $< '$(DESTDIR)$(libdir)/lib$(NAME).dll.a'
+endif
else # no soname
$(INSTALL_SHLIB) $< '$(DESTDIR)$(pkglibdir)/$(shlib)'
endif

View File

@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES C)
find_package(PostgreSQL REQUIRED)
add_executable(${PROJECT_NAME} test_package.c)
target_link_libraries(${PROJECT_NAME} PRIVATE PostgreSQL::PostgreSQL)

View File

@@ -0,0 +1,10 @@
{
"version": 4,
"vendor": {
"conan": {}
},
"include": [
"build/gcc-12-x86_64-gnu17-release/generators/CMakePresets.json",
"build/gcc-11.5-x86_64-17-release/generators/CMakePresets.json"
]
}

View File

@@ -0,0 +1,26 @@
from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout, CMake
import os
class TestPackageConan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv"
test_type = "explicit"
def layout(self):
cmake_layout(self)
def requirements(self):
self.requires(self.tested_reference_str)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(bin_path, env="conanrun")

View File

@@ -0,0 +1,17 @@
#include "libpq-fe.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
PGconn *conn = NULL;
const int version = PQlibVersion();
printf("PQlibVersion: %d\n", version);
conn = PQconnectdb("dbname = postgres");
PQstatus(conn);
PQfinish(conn);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES C)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/
${CMAKE_CURRENT_BINARY_DIR}/test_package/)

View File

@@ -0,0 +1,18 @@
from conans import ConanFile, CMake
from conan.tools.build import cross_building
import os
class TestPackageV1Conan(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package"
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
def test(self):
if not cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)

9
recipes/libpq/config.yml Normal file
View File

@@ -0,0 +1,9 @@
versions:
"15.5":
folder: all
"15.4":
folder: all
"15.3":
folder: all
"14.9":
folder: all