Skip to content

Commit

Permalink
894: Fix error-reporting crash in non-blocking connection. (#895)
Browse files Browse the repository at this point in the history
* 894: Fix error-reporting crash in non-blocking connection.

Fixes: #894

If construction of a non-blocking `connection` failed for a reason
_other_ than an out-of-memory error, then reporting of the error
would fail.  This happened because the error-reporting code tried to
read the error message _after it had already cleared the connection
pointer._  This means reading deallocated memory.

* Drop obsolete option in CircleCI build.

* Fix `assume()` chneck for clang C++17/C++20 build.

In clang 19, all of a sudden the compile-time feature check for
`[[assume()]]` support started issuing a warning: it says that
attribute is a "C++23 extension."  And the maintainer-mode build treats
warnings as wrrors, so...  Kaboom.

The problem is that in this mode, clang 19 does define the feature test
macro for this attribute even in C++ 17, but when you actually _use_ the
attribute, clang warns (at least with strict checking options) that it
is not part of C++17 (or C++20, as the case may be).

To get around that, I wrote a more substantial feature check and ran it
at _configure_ time.  This is where my work on systematising the feature
check mechanism really pays off — a few years ago this would have been a
fairly substantial change, with lots of opportunities to do it wrong.

* Work around clang compile problem in a test.

For some reason the line in this unit test where we create a
`std::vector<pqxx::binarystring>` triggers a deprecation warning, even
though the line is bracketed in an "ignore deprecations" block.

Since the whole class is deprecated, it wasn't really worth fixing
properly.  I'll just stop building this test on clang, until the time
comes to drop the whole class and its tests anyway.  Which I hope is
not too far off.
  • Loading branch information
jtv authored Oct 5, 2024
1 parent 793fbfe commit 7287495
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 10 deletions.
1 change: 0 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ jobs:
name: Configure
command: |
./configure \
--disable-documentation \
--enable-maintainer-mode \
--enable-audit \
--enable-shared --disable-static \
Expand Down
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Don't call`/bin/true`; macOS doesn't have it. Just call `true`. (#885)
- Deprecate `exec_prepared()`; just use `exec()` with a `pqxx::prepped`.
- Deprecate `exec1()` etc. Use `result::expect_rows()` etc.
- Fix error-reporting crash in non-blocking connection constructor. (#894)
7.9.2
- Fix CMake documentation install. (#848)
- More CMake build fix. (#869)
Expand Down
4 changes: 4 additions & 0 deletions cmake/pqxx_cxx_feature_checks.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Configuration for feature checks. Generated by generate_check_config.py.
include(CheckCXXSourceCompiles)
try_compile(
PQXX_HAVE_ASSUME ${PROJECT_BINARY_DIR}
SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_ASSUME.cxx
)
try_compile(
PQXX_HAVE_CHARCONV_FLOAT ${PROJECT_BINARY_DIR}
SOURCES ${PROJECT_SOURCE_DIR}/config-tests/PQXX_HAVE_CHARCONV_FLOAT.cxx
Expand Down
5 changes: 5 additions & 0 deletions config-tests/PQXX_HAVE_ASSUME.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
int main(int argc, char **argv)
{
[[assume(argv != nullptr)]];
return argc - 1;
}
1 change: 1 addition & 0 deletions configitems
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ PACKAGE_NAME internal autotools
PACKAGE_STRING internal autotools
PACKAGE_TARNAME internal autotools
PACKAGE_VERSION internal autotools
PQXX_HAVE_ASSUME public compiler
PQXX_HAVE_CHARCONV_INT internal compiler
PQXX_HAVE_CHARCONV_FLOAT internal compiler
PQXX_HAVE_CMP public compiler
Expand Down
28 changes: 28 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -17223,6 +17223,34 @@ fi # End of gcc-specific part.


# Configuration for feature checks. Generated by generate_check_config.py.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_ASSUME" >&5
printf %s "checking PQXX_HAVE_ASSUME... " >&6; }
PQXX_HAVE_ASSUME=yes
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(int argc, char **argv)

{

[[assume(argv != nullptr)]];

return argc - 1;

}


_ACEOF
if ac_fn_cxx_try_compile "$LINENO"
then :

printf "%s\n" "#define PQXX_HAVE_ASSUME 1" >>confdefs.h

else $as_nop
PQXX_HAVE_ASSUME=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PQXX_HAVE_ASSUME" >&5
printf "%s\n" "$PQXX_HAVE_ASSUME" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PQXX_HAVE_CHARCONV_FLOAT" >&5
printf %s "checking PQXX_HAVE_CHARCONV_FLOAT... " >&6; }
PQXX_HAVE_CHARCONV_FLOAT=yes
Expand Down
7 changes: 5 additions & 2 deletions include/pqxx/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

/* Define to 1 if you have the `pq' library (-lpq). */
/* Define to 1 if you have the 'pq' library (-lpq). */
#undef HAVE_LIBPQ

/* Define to 1 if you have the <stdint.h> header file. */
Expand Down Expand Up @@ -57,6 +57,9 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* Define if this feature is available. */
#undef PQXX_HAVE_ASSUME

/* Define if this feature is available. */
#undef PQXX_HAVE_CHARCONV_FLOAT

Expand Down Expand Up @@ -114,7 +117,7 @@
/* Define if this feature is available. */
#undef PQXX_HAVE_YEAR_MONTH_DAY

/* Define to 1 if all of the C90 standard headers exist (not just the ones
/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
Expand Down
9 changes: 3 additions & 6 deletions include/pqxx/internal/header-pre.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,8 @@


// C++23: Assume support.
// C++20: Assume __has_cpp_attribute is defined.
#if !defined(__has_cpp_attribute)
# define PQXX_ASSUME(condition) while (false)
#elif !__has_cpp_attribute(assume)
# define PQXX_ASSUME(condition) while (false)
#else
#if defined(PQXX_HAVE_ASSUME)
# define PQXX_ASSUME(condition) [[assume(condition)]]
#else
# define PQXX_ASSUME(condition) while (false)
#endif
10 changes: 10 additions & 0 deletions pqxx_cxx_feature_checks.ac
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
# Configuration for feature checks. Generated by generate_check_config.py.
AC_MSG_CHECKING([PQXX_HAVE_ASSUME])
PQXX_HAVE_ASSUME=yes
AC_COMPILE_IFELSE(
[read_test(PQXX_HAVE_ASSUME.cxx)],
AC_DEFINE(
[PQXX_HAVE_ASSUME],
1,
[Define if this feature is available.]),
PQXX_HAVE_ASSUME=no)
AC_MSG_RESULT($PQXX_HAVE_ASSUME)
AC_MSG_CHECKING([PQXX_HAVE_CHARCONV_FLOAT])
PQXX_HAVE_CHARCONV_FLOAT=yes
AC_COMPILE_IFELSE(
Expand Down
3 changes: 2 additions & 1 deletion src/connection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,10 @@ pqxx::connection::connection(
throw std::bad_alloc{};
if (status() == CONNECTION_BAD)
{
std::string const msg{PQerrorMessage(m_conn)};
PQfinish(m_conn);
m_conn = nullptr;
throw pqxx::broken_connection{PQerrorMessage(m_conn)};
throw pqxx::broken_connection{msg};
}
}

Expand Down
5 changes: 5 additions & 0 deletions test/unit/test_binarystring.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ void test_binarystring_stream()

void test_binarystring_array_stream()
{
// This test won't compile on clang in maintainer mode. For some reason,
// clang seems to ignore the ignore-deprecated headers in just this one
// function, where we create the vector of binarystring.
#if !defined(__clang__)
pqxx::connection cx;
pqxx::transaction tx{cx};
tx.exec("CREATE TEMP TABLE pqxxbinstream(id integer, vec bytea[])")
Expand Down Expand Up @@ -201,6 +205,7 @@ void test_binarystring_array_stream()
tx.query_value<std::size_t>(
"SELECT octet_length(vec[1]) FROM pqxxbinstream"),
std::size(data1), "Bytea length broke inside array.");
#endif // __clang__
}


Expand Down

0 comments on commit 7287495

Please sign in to comment.