From b62fed4a7e38efeeee9e2057d5556312a5a76cdf Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 19 Nov 2015 15:28:27 -0800 Subject: [PATCH 2/2] use configured malloc / free from the connection. --- src/interfaces/libpq/fe-connect.c | 5 +++ src/interfaces/libpq/fe-exec.c | 87 ++++++++++++++++++++++++++++----------- src/interfaces/libpq/libpq-int.h | 19 +++++++++ 3 files changed, 87 insertions(+), 24 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index d0e97ecdd4..203bbbc310 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3336,6 +3336,11 @@ makeEmptyPGconn(void) conn->noticeHooks.noticeRec = defaultNoticeReceiver; conn->noticeHooks.noticeProc = defaultNoticeProcessor; + /* set default allocators */ + conn->malloc = malloc; + conn->realloc = realloc; + conn->free = free; + conn->status = CONNECTION_BAD; conn->asyncStatus = PGASYNC_IDLE; conn->xactStatus = PQTRANS_IDLE; diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 464bdc635f..83a8bb627c 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -141,7 +141,7 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status) { PGresult *result; - result = (PGresult *) malloc(sizeof(PGresult)); + result = (PGresult *) conn->malloc(sizeof(PGresult)); if (!result) return NULL; @@ -164,6 +164,9 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status) result->curBlock = NULL; result->curOffset = 0; result->spaceLeft = 0; + result->malloc = conn->malloc; + result->realloc = conn->realloc; + result->free = conn->free; if (conn) { @@ -546,7 +549,7 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary) */ if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD) { - block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD); + block = (PGresult_data *) res->malloc(nBytes + PGRESULT_BLOCK_OVERHEAD); if (!block) return NULL; space = block->space + PGRESULT_BLOCK_OVERHEAD; @@ -570,7 +573,7 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary) } /* Otherwise, start a new block. */ - block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE); + block = (PGresult_data *) res->malloc(PGRESULT_DATA_BLOCKSIZE); if (!block) return NULL; block->next = res->curBlock; @@ -666,22 +669,22 @@ PQclear(PGresult *res) (void) res->events[i].proc(PGEVT_RESULTDESTROY, &evt, res->events[i].passThrough); } - free(res->events[i].name); + res->free(res->events[i].name); } if (res->events) - free(res->events); + res->free(res->events); /* Free all the subsidiary blocks */ while ((block = res->curBlock) != NULL) { res->curBlock = block->next; - free(block); + res->free(block); } /* Free the top-level tuple pointer array */ if (res->tuples) - free(res->tuples); + res->free(res->tuples); /* zero out the pointer fields to catch programming errors */ res->attDescs = NULL; @@ -693,7 +696,7 @@ PQclear(PGresult *res) /* res->curBlock was zeroed out earlier */ /* Free the PGresult structure itself */ - free(res); + res->free(res); } /* @@ -870,10 +873,10 @@ pqAddTuple(PGresult *res, PGresAttValue *tup) if (res->tuples == NULL) newTuples = (PGresAttValue **) - malloc(newSize * sizeof(PGresAttValue *)); + res->malloc(newSize * sizeof(PGresAttValue *)); else newTuples = (PGresAttValue **) - realloc(res->tuples, newSize * sizeof(PGresAttValue *)); + res->realloc(res->tuples, newSize * sizeof(PGresAttValue *)); if (!newTuples) return FALSE; /* malloc or realloc failed */ res->tupArrSize = newSize; @@ -931,7 +934,7 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value) prev->next = pstatus->next; else conn->pstatus = pstatus->next; - free(pstatus); /* frees name and value strings too */ + conn->free(pstatus); /* frees name and value strings too */ break; } } @@ -939,7 +942,7 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value) /* * Store new info as a single malloc block */ - pstatus = (pgParameterStatus *) malloc(sizeof(pgParameterStatus) + + pstatus = (pgParameterStatus *) conn->malloc(sizeof(pgParameterStatus) + strlen(name) + strlen(value) + 2); if (pstatus) { @@ -1157,7 +1160,7 @@ PQsendQuery(PGconn *conn, const char *query) /* and remember the query text too, if possible */ /* if insufficient memory, last_query just winds up NULL */ if (conn->last_query) - free(conn->last_query); + conn->free(conn->last_query); conn->last_query = strdup(query); /* @@ -1297,7 +1300,7 @@ PQsendPrepare(PGconn *conn, /* and remember the query text too, if possible */ /* if insufficient memory, last_query just winds up NULL */ if (conn->last_query) - free(conn->last_query); + conn->free(conn->last_query); conn->last_query = strdup(query); /* @@ -1546,7 +1549,7 @@ PQsendQueryGuts(PGconn *conn, /* and remember the query text too, if possible */ /* if insufficient memory, last_query just winds up NULL */ if (conn->last_query) - free(conn->last_query); + conn->free(conn->last_query); if (command) conn->last_query = strdup(command); else @@ -2159,7 +2162,7 @@ PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target) /* reset last-query string (not relevant now) */ if (conn->last_query) { - free(conn->last_query); + conn->free(conn->last_query); conn->last_query = NULL; } @@ -2866,11 +2869,11 @@ PQfnumber(const PGresult *res, const char *field_name) { if (strcmp(field_case, res->attDescs[i].name) == 0) { - free(field_case); + res->free(field_case); return i; } } - free(field_case); + res->free(field_case); return -1; } @@ -3391,7 +3394,7 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident) result_size = input_len + num_quotes + 3; /* two quotes, plus a NUL */ if (!as_ident && num_backslashes > 0) result_size += num_backslashes + 2; - result = rp = (char *) malloc(result_size); + result = rp = (char *) conn->malloc(result_size); if (rp == NULL) { printfPQExpBuffer(&conn->errorMessage, @@ -3555,7 +3558,15 @@ PQescapeByteaInternal(PGconn *conn, } *to_length = len; - rp = result = (unsigned char *) malloc(len); + if (conn) + { + rp = result = (unsigned char *) conn->malloc(len); + } + else + { + rp = result = (unsigned char *) malloc(len); + } + if (rp == NULL) { if (conn) @@ -3674,7 +3685,14 @@ PQunescapeByteaInternal(PGconn *conn, buflen = (strtextlen - 2) / 2; /* Avoid unportable malloc(0) */ - buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1); + if (conn) + { + buffer = (unsigned char *) conn->malloc(buflen > 0 ? buflen : 1); + } + else + { + buffer = (unsigned char *) malloc(buflen > 0 ? buflen : 1); + } if (buffer == NULL) return NULL; @@ -3705,7 +3723,14 @@ PQunescapeByteaInternal(PGconn *conn, * Length of input is max length of output, but add one to avoid * unportable malloc(0) if input is zero-length. */ - buffer = (unsigned char *) malloc(strtextlen + 1); + if (conn) + { + buffer = (unsigned char *) conn->malloc(strtextlen + 1); + } + else + { + buffer = (unsigned char *) malloc(strtextlen + 1); + } if (buffer == NULL) return NULL; @@ -3751,12 +3776,26 @@ PQunescapeByteaInternal(PGconn *conn, /* Shrink the buffer to be no larger than necessary */ /* +1 avoids unportable behavior when buflen==0 */ - tmpbuf = realloc(buffer, buflen + 1); + if (conn) + { + tmpbuf = conn->realloc(buffer, buflen + 1); + } + else + { + tmpbuf = realloc(buffer, buflen + 1); + } /* It would only be a very brain-dead realloc that could fail, but... */ if (!tmpbuf) { - free(buffer); + if (conn) + { + conn->free(buffer); + } + else + { + free(buffer); + } return NULL; } diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 42913604e3..356be9ccbc 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -80,6 +80,14 @@ typedef struct #endif #endif /* USE_OPENSSL */ + /* ---------------- + * malloc/realloc/free for PGResult is replasable for in-backend use + * ---------------- + */ +typedef void *(*PQpgresult_malloc)(size_t size); +typedef void *(*PQpgresult_realloc)(void *ptr, size_t size); +typedef void (*PQpgresult_free)(void *ptr); + /* * POSTGRES backend dependent Constants. */ @@ -162,6 +170,9 @@ typedef struct PGEvent void *passThrough; /* pointer supplied at registration time */ void *data; /* optional state (instance) data */ bool resultInitialized; /* T if RESULTCREATE/COPY succeeded */ + PQpgresult_malloc malloc; + PQpgresult_realloc realloc; + PQpgresult_free free; } PGEvent; struct pg_result @@ -208,6 +219,10 @@ struct pg_result PGresult_data *curBlock; /* most recently allocated block */ int curOffset; /* start offset of free space in block */ int spaceLeft; /* number of free bytes remaining in block */ + + PQpgresult_malloc malloc; + PQpgresult_realloc realloc; + PQpgresult_free free; }; /* PGAsyncStatusType defines the state of the query-execution state machine */ @@ -492,6 +507,10 @@ struct pg_conn /* Buffer for receiving various parts of messages */ PQExpBufferData workBuffer; /* expansible string */ + + PQpgresult_malloc malloc; + PQpgresult_realloc realloc; + PQpgresult_free free; }; /* PGcancel stores all data necessary to cancel a connection. A copy of this -- 2.11.0