Memory leak using when using libpq PQExecParams() CRYPTO_zalloc()

From: Michael Arnold <myk321(at)gmail(dot)com>
To: pgsql-general(at)lists(dot)postgresql(dot)org
Subject: Memory leak using when using libpq PQExecParams() CRYPTO_zalloc()
Date: 2023-02-22 13:35:00
Message-ID: CAMOVWRiqweDi_m66mrVpA2yFe-dcxyF35mM5r1OkhTK0aj-hHg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hi,

Am looking for guidance on how to fix a memory leak when using libpq
PQExecParams(). Memory leaks through CRYPTO_zalloc() and arises when using
json_agg(). None-JSON based PQExecParams() calls are not leaking.

Using Postgresql 13.6 (Ubuntu 13.6-0ubuntu0.21.10.1) on
x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.2.0-7ubuntu2) 11.2.0, 64-bit
Accessed by a c/c++ application via libpq (libssl3 and libcrypt are also
linked)

Valgrind reports:

==4107== 2,712 bytes in 3 blocks are definitely lost in loss record 265 of
276
==4107== at 0x4848899: malloc (in
/usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==4107== by 0x4B1F41D: CRYPTO_zalloc (in
/usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==4107== by 0x4AD50A8: ??? (in /usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==4107== by 0x4AD51EC: ERR_clear_error (in
/usr/lib/x86_64-linux-gnu/libcrypto.so.3)
==4107== by 0x488D52A: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.14)
==4107== by 0x488E89D: ??? (in /usr/lib/x86_64-linux-gnu/libpq.so.5.14)
==4107== by 0x488E923: PQsendQueryParams (in
/usr/lib/x86_64-linux-gnu/libpq.so.5.14)
==4107== by 0x4893C27: PQexecParams (in
/usr/lib/x86_64-linux-gnu/libpq.so.5.14)
==4107== by 0x3E1613: getJSON(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >) (dbInterface.cpp:7202)
==4107== by 0x47ACEC:
tickerHandler::handleRequest(Poco::Net::HTTPServerRequest&,
Poco::Net::HTTPServerResponse&) (externalInterface.cpp:615)
==4107== by 0x5096E18: Poco::Net::HTTPServerConnection::run() (in
/usr/lib/x86_64-linux-gnu/libPocoNet.so.80)
==4107== by 0x50D935A: Poco::Net::TCPServerConnection::start() (in
/usr/lib/x86_64-linux-gnu/libPocoNet.so.80)

i.e. call to PQExecParams() within getJSON() is leaking via
CRYTO_zalloc(). The code for getJSON() is reproduced below.

std::string getJSON(std::string sqlQuery){
PGconn *dbConn = nullptr;
int nParams = 0;
int resultFormat = 1; //binary format
size_t noRecords = 0;
PGresult *res = nullptr;
std::string resultJSON;

std::string fullQuery = "select json_agg(t) FROM (" + sqlQuery + ") t;";

if ((dbConn = getConnection(connectionPool)) != nullptr) {
res = PQexecParams(dbConn,
fullQuery.c_str(),
nParams,
NULL,
NULL,
NULL,
NULL, resultFormat);

//Check if there was a problem
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
if (dbConn != nullptr){
returnConnection(connectionPool, dbConn);
PQclear(res);
}
return (resultJSON);
} //End of result checking

//If we successfully get the information then populate resultJSON
noRecords = (int64_t) PQntuples(res);
if (noRecords == 1)
resultJSON = std::string((const char*) PQgetvalue(res, 0, 0));

//Clean-up
PQclear(res);
returnConnection(connectionPool, dbConn);
}

//select json_arr may return an empty string "", but this is not valid json
and json.parse will error
// to avoid this return a valid json empty string
if (resultJSON.empty())
resultJSON = "\"\"";

return (resultJSON);
}

getConnection() and returnConnection() are application specific calls to
get and replace valid PGconn* to / from an in-app postgres connection pool.

Setup is really basic:
1. In postgresql.conf
1a. Uncomment listen_addresses
1b. Replace localhost with *
1c. Uncomment password_encryption

2. In pg_hba.conf
2a. Add the local network:
host all all 192.168.0.101/24 md5
2b. Replace ident with md5

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Jeffrey Walton 2023-02-22 15:13:33 Re: Memory leak using when using libpq PQExecParams() CRYPTO_zalloc()
Previous Message n.kobzarev 2023-02-22 10:03:48 RE: Event Triggers unable to capture the DDL script executed