From da7d81dd0579a2579741bcfc816cf614c58d0aab Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 8 Sep 2021 15:09:42 -0400 Subject: [PATCH] Avoid useless malloc/free traffic around getFormattedTypeName(). Coverity complained that one caller of getFormattedTypeName() failed to free the returned string. Which is true, but rather than fixing that one, let's get rid of this tedious and error-prone requirement. Now that getFormattedTypeName() caches its result, strdup'ing that result and expecting the caller to free it accomplishes little except to waste cycles. We do create a leak in the case where getTypes didn't make a TypeInfo for the type, but that basically shouldn't ever happen. Back-patch, as commit 6c450a861 was. This isn't a particularly interesting bug fix, but the API change seems like a hazard for future back-patching activity if we don't back-patch it. --- src/bin/pg_dump/pg_dump.c | 74 +++++++++++++++------------------------ 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 4f261e8bf6..e2a5bee960 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -255,7 +255,7 @@ static char *convertRegProcReference(Archive *fout, static char *getFormattedOperatorName(Archive *fout, const char *oproid); static char *convertTSFunction(Archive *fout, Oid funcOid); static Oid findLastBuiltinOid_V71(Archive *fout); -static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts); +static const char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts); static void getBlobs(Archive *fout); static void dumpBlob(Archive *fout, BlobInfo *binfo); static int dumpBlobs(Archive *fout, void *arg); @@ -11009,13 +11009,9 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo) } if (OidIsValid(tyinfo->typelem)) - { - char *elemType; - - elemType = getFormattedTypeName(fout, tyinfo->typelem, zeroIsError); - appendPQExpBuffer(q, ",\n ELEMENT = %s", elemType); - free(elemType); - } + appendPQExpBuffer(q, ",\n ELEMENT = %s", + getFormattedTypeName(fout, tyinfo->typelem, + zeroIsError)); if (strcmp(typcategory, "U") != 0) { @@ -11818,7 +11814,7 @@ format_function_arguments_old(Archive *fout, for (j = 0; j < nallargs; j++) { Oid typid; - char *typname; + const char *typname; const char *argmode; const char *argname; @@ -11857,7 +11853,6 @@ format_function_arguments_old(Archive *fout, argname ? fmtId(argname) : "", argname ? " " : "", typname); - free(typname); } appendPQExpBufferChar(&fn, ')'); return fn.data; @@ -11886,15 +11881,12 @@ format_function_signature(Archive *fout, FuncInfo *finfo, bool honor_quotes) appendPQExpBuffer(&fn, "%s(", finfo->dobj.name); for (j = 0; j < finfo->nargs; j++) { - char *typname; - if (j > 0) appendPQExpBufferStr(&fn, ", "); - typname = getFormattedTypeName(fout, finfo->argtypes[j], - zeroIsError); - appendPQExpBufferStr(&fn, typname); - free(typname); + appendPQExpBufferStr(&fn, + getFormattedTypeName(fout, finfo->argtypes[j], + zeroIsError)); } appendPQExpBufferChar(&fn, ')'); return fn.data; @@ -11938,7 +11930,6 @@ dumpFunc(Archive *fout, FuncInfo *finfo) char *prosupport; char *proparallel; char *lanname; - char *rettypename; int nallargs; char **allargtypes = NULL; char **argmodes = NULL; @@ -12295,14 +12286,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo) else if (funcresult) appendPQExpBuffer(q, " RETURNS %s", funcresult); else - { - rettypename = getFormattedTypeName(fout, finfo->prorettype, - zeroIsError); appendPQExpBuffer(q, " RETURNS %s%s", (proretset[0] == 't') ? "SETOF " : "", - rettypename); - free(rettypename); - } + getFormattedTypeName(fout, finfo->prorettype, + zeroIsError)); appendPQExpBuffer(q, "\n LANGUAGE %s", fmtId(lanname)); @@ -12509,8 +12496,8 @@ dumpCast(Archive *fout, CastInfo *cast) PQExpBuffer labelq; PQExpBuffer castargs; FuncInfo *funcInfo = NULL; - char *sourceType; - char *targetType; + const char *sourceType; + const char *targetType; /* Skip if not to be dumped */ if (!cast->dobj.dump || dopt->dataOnly) @@ -12596,9 +12583,6 @@ dumpCast(Archive *fout, CastInfo *cast) NULL, "", cast->dobj.catId, 0, cast->dobj.dumpId); - free(sourceType); - free(targetType); - destroyPQExpBuffer(defqry); destroyPQExpBuffer(delqry); destroyPQExpBuffer(labelq); @@ -12619,7 +12603,7 @@ dumpTransform(Archive *fout, TransformInfo *transform) FuncInfo *fromsqlFuncInfo = NULL; FuncInfo *tosqlFuncInfo = NULL; char *lanname; - char *transformType; + const char *transformType; /* Skip if not to be dumped */ if (!transform->dobj.dump || dopt->dataOnly) @@ -12726,7 +12710,6 @@ dumpTransform(Archive *fout, TransformInfo *transform) transform->dobj.catId, 0, transform->dobj.dumpId); free(lanname); - free(transformType); destroyPQExpBuffer(defqry); destroyPQExpBuffer(delqry); destroyPQExpBuffer(labelq); @@ -14018,17 +14001,11 @@ format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes) { appendPQExpBufferChar(&buf, '('); for (j = 0; j < agginfo->aggfn.nargs; j++) - { - char *typname; - - typname = getFormattedTypeName(fout, agginfo->aggfn.argtypes[j], - zeroIsError); - appendPQExpBuffer(&buf, "%s%s", (j > 0) ? ", " : "", - typname); - free(typname); - } + getFormattedTypeName(fout, + agginfo->aggfn.argtypes[j], + zeroIsError)); appendPQExpBufferChar(&buf, ')'); } return buf.data; @@ -18728,8 +18705,10 @@ findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj, * * This does not guarantee to schema-qualify the output, so it should not * be used to create the target object name for CREATE or ALTER commands. + * + * Note that the result is cached and must not be freed by the caller. */ -static char * +static const char * getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts) { TypeInfo *typeInfo; @@ -18740,15 +18719,15 @@ getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts) if (oid == 0) { if ((opts & zeroAsStar) != 0) - return pg_strdup("*"); + return "*"; else if ((opts & zeroAsNone) != 0) - return pg_strdup("NONE"); + return "NONE"; } /* see if we have the result cached in the type's TypeInfo record */ typeInfo = findTypeByOid(oid); if (typeInfo && typeInfo->ftypname) - return pg_strdup(typeInfo->ftypname); + return typeInfo->ftypname; query = createPQExpBuffer(); appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)", @@ -18762,9 +18741,14 @@ getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts) PQclear(res); destroyPQExpBuffer(query); - /* cache a copy for later requests */ + /* + * Cache the result for re-use in later requests, if possible. If we + * don't have a TypeInfo for the type, the string will be leaked once the + * caller is done with it ... but that case really should not happen, so + * leaking if it does seems acceptable. + */ if (typeInfo) - typeInfo->ftypname = pg_strdup(result); + typeInfo->ftypname = result; return result; }