From 8a9fd13438b9589f0d15ffe98f0d2554b39b5ad2 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 25 Sep 2022 23:33:03 +0300 Subject: [PATCH 16/16] Fix memory leaks from req_to_fstring() usage See osdn #45544 Signed-off-by: Marko Lindqvist --- common/requirements.c | 14 +++++++++----- common/requirements.h | 5 ++++- server/rssanity.c | 17 ++++++++++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/common/requirements.c b/common/requirements.c index db409ca94f..e1abad8a3d 100644 --- a/common/requirements.c +++ b/common/requirements.c @@ -582,23 +582,27 @@ int universal_number(const struct universal *source) return 0; } - /**************************************************************************** Returns the given requirement as a formatted string ready for printing. Does not care about the 'quiet' property. + + astring does not need to be initialized before the call, + but caller needs to call astr_free() for it once the returned + string is no longer needed. ****************************************************************************/ -const char *req_to_fstring(const struct requirement *req) +const char *req_to_fstring(const struct requirement *req, + struct astring *astr) { - struct astring printable_req = ASTRING_INIT; + astr_init(astr); - astr_set(&printable_req, "%s%s %s %s%s", + astr_set(astr, "%s%s %s %s%s", req->survives ? "surviving " : "", req_range_name(req->range), universal_type_rule_name(&req->source), req->present ? "" : "!", universal_rule_name(&req->source)); - return astr_str(&printable_req); + return astr_str(astr); } /**************************************************************************** diff --git a/common/requirements.h b/common/requirements.h index 9ad63dc347..62685f3eae 100644 --- a/common/requirements.h +++ b/common/requirements.h @@ -21,6 +21,8 @@ extern "C" { /* common */ #include "fc_types.h" +struct astring; + /* Range of requirements. * Used in the network protocol. * Order is important -- wider ranges should come later -- some code @@ -80,7 +82,8 @@ struct requirement { struct requirement req_from_str(const char *type, const char *range, bool survives, bool present, bool quiet, const char *value); -const char *req_to_fstring(const struct requirement *req); +const char *req_to_fstring(const struct requirement *req, + struct astring *astr); void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, diff --git a/server/rssanity.c b/server/rssanity.c index 3aed5d2a47..2a1734fc52 100644 --- a/server/rssanity.c +++ b/server/rssanity.c @@ -16,6 +16,7 @@ #endif /* utility */ +#include "astring.h" #include "deprecations.h" /* common */ @@ -300,10 +301,17 @@ static bool sanity_check_req_vec(const struct requirement_vector *preqs, } requirement_vector_iterate(preqs, nreq) { if (are_requirements_contradictions(preq, nreq)) { + struct astring astr; + struct astring nastr; + log_error("%s: Requirements {%s} and {%s} contradict each other.", list_for, - req_to_fstring(preq), - req_to_fstring(nreq)); + req_to_fstring(preq, &astr), + req_to_fstring(nreq, &nastr)); + + astr_free(&astr); + astr_free(&nastr); + return FALSE; } } requirement_vector_iterate_end; @@ -857,6 +865,8 @@ bool sanity_check_ruleset_data(void) requirement_vector_iterate(&(enabler->target_reqs), preq) { if (preq->source.kind == VUT_DIPLREL && preq->range == REQ_RANGE_LOCAL) { + struct astring astr; + /* A Local DiplRel requirement can be expressed as a requirement * in actor_reqs. Demand that it is there. This avoids breaking * code that reasons about actions. */ @@ -866,7 +876,8 @@ bool sanity_check_ruleset_data(void) "section \"Requirement vector rules\" in " "doc/README.actions", action_id_rule_name(act), - req_to_fstring(preq)); + req_to_fstring(preq, &astr)); + astr_free(&astr); ok = FALSE; } } requirement_vector_iterate_end; -- 2.35.1