summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Dunstan2024-04-09 13:07:14 +0000
committerAndrew Dunstan2024-04-12 14:32:30 +0000
commit661ab4e185784db79c194b5758555b1db3f30483 (patch)
treec5fdde1cecca9ea8440f5e8e2412741acc34d580 /src
parentb9ecefecc7aaad117e0255b56b759f524f0f4363 (diff)
Fix some memory leaks associated with parsing json and manifests
Coverity complained about not freeing some memory associated with incrementally parsing backup manifests. To fix that, provide and use a new shutdown function for the JsonManifestParseIncrementalState object, in line with a suggestion from Tom Lane. While analysing the problem, I noticed a buglet in freeing memory for incremental json lexers. To fix that remove a bogus condition on freeing the memory allocated for them.
Diffstat (limited to 'src')
-rw-r--r--src/backend/backup/basebackup_incremental.c3
-rw-r--r--src/bin/pg_combinebackup/load_manifest.c3
-rw-r--r--src/bin/pg_verifybackup/pg_verifybackup.c3
-rw-r--r--src/common/jsonapi.c21
-rw-r--r--src/common/parse_manifest.c13
-rw-r--r--src/include/common/parse_manifest.h1
6 files changed, 32 insertions, 12 deletions
diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c
index 4962bf1529e..330a2294011 100644
--- a/src/backend/backup/basebackup_incremental.c
+++ b/src/backend/backup/basebackup_incremental.c
@@ -241,6 +241,9 @@ FinalizeIncrementalManifest(IncrementalBackupInfo *ib)
pfree(ib->buf.data);
ib->buf.data = NULL;
+ /* Done with inc_state, so release that memory too */
+ json_parse_manifest_incremental_shutdown(ib->inc_state);
+
/* Switch back to previous memory context. */
MemoryContextSwitchTo(oldcontext);
}
diff --git a/src/bin/pg_combinebackup/load_manifest.c b/src/bin/pg_combinebackup/load_manifest.c
index 9c9332cdd5c..d857ea00066 100644
--- a/src/bin/pg_combinebackup/load_manifest.c
+++ b/src/bin/pg_combinebackup/load_manifest.c
@@ -208,6 +208,9 @@ load_backup_manifest(char *backup_directory)
inc_state, buffer, rc, bytes_left == 0);
}
+ /* Release the incremental state memory */
+ json_parse_manifest_incremental_shutdown(inc_state);
+
close(fd);
}
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index 90ef4b20379..9594c615c7c 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -484,6 +484,9 @@ parse_manifest_file(char *manifest_path)
inc_state, buffer, rc, bytes_left == 0);
}
+ /* Release the incremental state memory */
+ json_parse_manifest_incremental_shutdown(inc_state);
+
close(fd);
}
diff --git a/src/common/jsonapi.c b/src/common/jsonapi.c
index 44dbb7f7f96..9dfbc397c06 100644
--- a/src/common/jsonapi.c
+++ b/src/common/jsonapi.c
@@ -488,19 +488,18 @@ freeJsonLexContext(JsonLexContext *lex)
if (lex->errormsg)
destroyStringInfo(lex->errormsg);
- if (lex->flags & JSONLEX_FREE_STRUCT)
+ if (lex->incremental)
{
- if (lex->incremental)
- {
- pfree(lex->inc_state->partial_token.data);
- pfree(lex->inc_state);
- pfree(lex->pstack->prediction);
- pfree(lex->pstack->fnames);
- pfree(lex->pstack->fnull);
- pfree(lex->pstack);
- }
- pfree(lex);
+ pfree(lex->inc_state->partial_token.data);
+ pfree(lex->inc_state);
+ pfree(lex->pstack->prediction);
+ pfree(lex->pstack->fnames);
+ pfree(lex->pstack->fnull);
+ pfree(lex->pstack);
}
+
+ if (lex->flags & JSONLEX_FREE_STRUCT)
+ pfree(lex);
}
/*
diff --git a/src/common/parse_manifest.c b/src/common/parse_manifest.c
index 970a756ce8a..a94e3d6b154 100644
--- a/src/common/parse_manifest.c
+++ b/src/common/parse_manifest.c
@@ -123,7 +123,6 @@ static bool parse_xlogrecptr(XLogRecPtr *result, char *input);
/*
* Set up for incremental parsing of the manifest.
- *
*/
JsonManifestParseIncrementalState *
@@ -164,6 +163,18 @@ json_parse_manifest_incremental_init(JsonManifestParseContext *context)
}
/*
+ * Free an incremental state object and its contents.
+ */
+void
+json_parse_manifest_incremental_shutdown(JsonManifestParseIncrementalState *incstate)
+{
+ pfree(incstate->sem.semstate);
+ freeJsonLexContext(&(incstate->lex));
+ /* incstate->manifest_ctx has already been freed */
+ pfree(incstate);
+}
+
+/*
* parse the manifest in pieces.
*
* The caller must ensure that the final piece contains the final lines
diff --git a/src/include/common/parse_manifest.h b/src/include/common/parse_manifest.h
index 3aa594fcac7..0d04239c38d 100644
--- a/src/include/common/parse_manifest.h
+++ b/src/include/common/parse_manifest.h
@@ -53,5 +53,6 @@ extern JsonManifestParseIncrementalState *json_parse_manifest_incremental_init(J
extern void json_parse_manifest_incremental_chunk(
JsonManifestParseIncrementalState *incstate, char *chunk, int size,
bool is_last);
+extern void json_parse_manifest_incremental_shutdown(JsonManifestParseIncrementalState *incstate);
#endif