From be8cfdfbc0a65ce93269281418b3ab41082a6994 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 9 Oct 2023 00:44:46 +0100 Subject: Avoid repeated calls to PQunescapeBytea Fixes issue where accessing the blob value of a column multiple times would free previously unescaped buffers resulting in dangling pointers. --- libpqpp/pq-column.cpp | 13 +++++++------ libpqpp/pq-column.h | 10 ++++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'libpqpp') diff --git a/libpqpp/pq-column.cpp b/libpqpp/pq-column.cpp index 5a5f6b6..e495f2a 100644 --- a/libpqpp/pq-column.cpp +++ b/libpqpp/pq-column.cpp @@ -89,12 +89,13 @@ PQ::Column::apply(DB::HandleField & h) const case TIMESTAMPTZOID: h.timestamp(boost::posix_time::time_from_string(value())); break; - case BYTEAOID: { - size_t len = 0; - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - buf = BufPtr {PQunescapeBytea(reinterpret_cast(value()), &len)}; - h.blob(DB::Blob(buf.get(), len)); + case BYTEAOID: + if (sc->tuple != buffer.row || !buffer.data) { + buffer.data = Buffer::BufPtr {// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + PQunescapeBytea(reinterpret_cast(value()), &buffer.length)}; + buffer.row = sc->tuple; + } + h.blob(DB::Blob(buffer.data.get(), buffer.length)); break; - } } } diff --git a/libpqpp/pq-column.h b/libpqpp/pq-column.h index fa4a78a..4ef102d 100644 --- a/libpqpp/pq-column.h +++ b/libpqpp/pq-column.h @@ -24,8 +24,14 @@ namespace PQ { const Oid oid; // Buffer for PQunescapeBytea - using BufPtr = std::unique_ptr>; - mutable BufPtr buf; + struct Buffer { + using BufPtr = std::unique_ptr>; + size_t row {}; + size_t length {}; + BufPtr data; + }; + + mutable Buffer buffer; }; } -- cgit v1.2.3