summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-10-09 00:44:46 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-10-09 00:44:46 +0100
commitbe8cfdfbc0a65ce93269281418b3ab41082a6994 (patch)
tree9b94d092307d88054eadfb88e39a17fb1a022a8a
parentExplicit instantiation of checkResult (diff)
downloadlibdbpp-postgresql-be8cfdfbc0a65ce93269281418b3ab41082a6994.tar.bz2
libdbpp-postgresql-be8cfdfbc0a65ce93269281418b3ab41082a6994.tar.xz
libdbpp-postgresql-be8cfdfbc0a65ce93269281418b3ab41082a6994.zip
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.
-rw-r--r--libpqpp/pq-column.cpp13
-rw-r--r--libpqpp/pq-column.h10
2 files changed, 15 insertions, 8 deletions
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<const unsigned char *>(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<const unsigned char *>(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<unsigned char, pq_deleter<PQfreemem>>;
- mutable BufPtr buf;
+ struct Buffer {
+ using BufPtr = std::unique_ptr<unsigned char, pq_deleter<PQfreemem>>;
+ size_t row {};
+ size_t length {};
+ BufPtr data;
+ };
+
+ mutable Buffer buffer;
};
}