aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-05-04 10:44:32 +0200
committerChristian Grothoff <christian@grothoff.org>2023-05-04 10:47:02 +0200
commit9316c050740bf275468ca5429d402718d7e69a07 (patch)
treec6999df971ee7a4e995fe655bd4c1dfc56b0017c /src
parent8fd6f27d836f27c22f2af20099166b9e6febf905 (diff)
downloadmerchant-9316c050740bf275468ca5429d402718d7e69a07.tar.gz
merchant-9316c050740bf275468ca5429d402718d7e69a07.tar.bz2
merchant-9316c050740bf275468ca5429d402718d7e69a07.zip
fix memory leak from interaction of templates and new order logic
Diffstat (limited to 'src')
-rw-r--r--src/backend/taler-merchant-httpd_post-using-templates.c165
-rw-r--r--src/backend/taler-merchant-httpd_private-post-orders.c37
2 files changed, 121 insertions, 81 deletions
diff --git a/src/backend/taler-merchant-httpd_post-using-templates.c b/src/backend/taler-merchant-httpd_post-using-templates.c
index e2fb7d23..74eb0f44 100644
--- a/src/backend/taler-merchant-httpd_post-using-templates.c
+++ b/src/backend/taler-merchant-httpd_post-using-templates.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- (C) 2022 Taler Systems SA
+ (C) 2022-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@@ -21,6 +21,7 @@
* @file taler-merchant-httpd_post-using-templates.c
* @brief implementing POST /using-templates request handling
* @author Priscilla HUANG
+ * @author Christian Grothoff
*/
#include "platform.h"
#include "taler-merchant-httpd_post-using-templates.h"
@@ -29,6 +30,43 @@
#include <taler/taler_json_lib.h>
+/**
+ * Our context.
+ */
+struct UseContext
+{
+ /**
+ * Internal handler context we are passing into the
+ * POST /private/orders handler.
+ */
+ struct TMH_HandlerContext ihc;
+
+ /**
+ * Our template details from the DB.
+ */
+ struct TALER_MERCHANTDB_TemplateDetails etp;
+
+};
+
+
+/**
+ * Clean up a `struct UseContext *`
+ *
+ * @param cls a `struct UseContext *`
+ */
+static void
+cleanup_use_context (void *cls)
+{
+ struct UseContext *uc = cls;
+
+ TALER_MERCHANTDB_template_details_free (&uc->etp);
+ if (NULL != uc->ihc.cc)
+ uc->ihc.cc (uc->ihc.ctx);
+ json_decref (uc->ihc.request_body);
+ GNUNET_free (uc);
+}
+
+
MHD_RESULT
TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
struct MHD_Connection *connection,
@@ -44,7 +82,6 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
bool no_amount;
json_t *fake_body;
bool no_summary;
- struct TALER_MERCHANTDB_TemplateDetails etp;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("summary",
@@ -57,6 +94,15 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
&no_amount),
GNUNET_JSON_spec_end ()
};
+ struct UseContext *uc = hc->ctx;
+
+ if (NULL == uc)
+ {
+ uc = GNUNET_new (struct UseContext);
+ hc->ctx = uc;
+ hc->cc = &cleanup_use_context;
+ uc->ihc.instance = hc->instance;
+ }
{
enum GNUNET_GenericReturnValue res;
@@ -79,32 +125,35 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
qs = TMH_db->lookup_template (TMH_db->cls,
mi->settings.id,
template_id,
- &etp);
+ &uc->etp);
switch (qs)
{
case GNUNET_DB_STATUS_HARD_ERROR:
/* Clean up and fail hard */
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
case GNUNET_DB_STATUS_SOFT_ERROR:
/* this should be impossible (single select) */
GNUNET_break (0);
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ NULL);
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
/* template not found! */
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN,
- template_id);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_MERCHANT_GENERIC_TEMPLATE_UNKNOWN,
+ template_id);
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
/* all good */
break;
@@ -140,22 +189,22 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
const char *err_name;
unsigned int err_line;
- res = GNUNET_JSON_parse (etp.template_contract,
+ res = GNUNET_JSON_parse (uc->etp.template_contract,
tspec,
&err_name,
&err_line);
if (GNUNET_OK != res)
{
GNUNET_break (0);
- json_dumpf (etp.template_contract,
+ json_dumpf (uc->etp.template_contract,
stderr,
JSON_INDENT (2));
- TALER_MERCHANTDB_template_details_free (&etp);
GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- err_name);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ err_name);
}
}
@@ -163,7 +212,6 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
(! no_tamount) )
{
GNUNET_JSON_parse_free (spec);
- TALER_MERCHANTDB_template_details_free (&etp);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_CONFLICT,
@@ -174,7 +222,6 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
if (no_amount && no_tamount)
{
GNUNET_JSON_parse_free (spec);
- TALER_MERCHANTDB_template_details_free (&etp);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_CONFLICT,
@@ -186,7 +233,6 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
(NULL != tsummary) )
{
GNUNET_JSON_parse_free (spec);
- TALER_MERCHANTDB_template_details_free (&etp);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_CONFLICT,
@@ -198,48 +244,43 @@ TMH_post_using_templates_ID (const struct TMH_RequestHandler *rh,
(NULL == tsummary) )
{
GNUNET_JSON_parse_free (spec);
- TALER_MERCHANTDB_template_details_free (&etp);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY,
- NULL);
+ return TALER_MHD_reply_with_error (
+ connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_POST_USING_TEMPLATES_NO_SUMMARY,
+ NULL);
}
no_summary = (NULL == summary);
fake_body = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_object_steal ("order",
- GNUNET_JSON_PACK (
- TALER_JSON_pack_amount ("amount",
- no_amount ?
- &tamount :
- &amount),
- GNUNET_JSON_pack_string ("summary",
- no_summary ?
- tsummary :
- summary),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string (
- "fulfillment_url",
- fulfillment_url)),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string (
- "fulfillment_message",
- fulfillment_message))
- ))
+ GNUNET_JSON_pack_object_steal (
+ "order",
+ GNUNET_JSON_PACK (
+ TALER_JSON_pack_amount ("amount",
+ no_amount ?
+ &tamount :
+ &amount),
+ GNUNET_JSON_pack_string ("summary",
+ no_summary ?
+ tsummary :
+ summary),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string (
+ "fulfillment_url",
+ fulfillment_url)),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string (
+ "fulfillment_message",
+ fulfillment_message))
+ ))
);
}
- {
- struct TMH_HandlerContext fake_hc = {
- .request_body = fake_body,
- .instance = hc->instance
- };
- mret = TMH_private_post_orders_with_pos_secrets (NULL, /* not even used */
- connection,
- &fake_hc,
- etp.pos_key,
- etp.pos_algorithm);
- }
- TALER_MERCHANTDB_template_details_free (&etp);
- json_decref (fake_body);
+ uc->ihc.request_body = fake_body;
+ mret = TMH_private_post_orders_with_pos_secrets (
+ NULL, /* not even used */
+ connection,
+ &uc->ihc,
+ uc->etp.pos_key,
+ uc->etp.pos_algorithm);
return mret;
}
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c
index 951130d0..2c68e680 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.c
+++ b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -175,7 +175,7 @@ struct OrderContext
/**
* Shared key to use with @e pos_algorithm.
*/
- char *pos_key;
+ const char *pos_key;
/**
* Our order ID. Pointer into @e order.
@@ -293,7 +293,6 @@ clean_order (void *cls)
oc->uuids_length,
0);
json_decref (oc->order);
- GNUNET_free (oc->pos_key);
GNUNET_free (oc);
}
@@ -414,10 +413,10 @@ execute_order (struct OrderContext *oc)
struct TALER_Amount total;
const char *summary;
const char *fulfillment_msg = NULL;
- json_t *products;
- json_t *merchant;
- json_t *summary_i18n = NULL;
- json_t *fulfillment_i18n = NULL;
+ const json_t *products;
+ const json_t *merchant;
+ const json_t *summary_i18n = NULL;
+ const json_t *fulfillment_i18n = NULL;
struct GNUNET_TIME_Timestamp timestamp;
struct GNUNET_TIME_Timestamp refund_deadline = { 0 };
struct GNUNET_TIME_Timestamp wire_transfer_deadline;
@@ -432,21 +431,21 @@ execute_order (struct OrderContext *oc)
/**
* The following entries we don't actually need,
* except to check that the order is well-formed */
- GNUNET_JSON_spec_json ("products",
- &products),
- GNUNET_JSON_spec_json ("merchant",
- &merchant),
+ GNUNET_JSON_spec_array_const ("products",
+ &products),
+ GNUNET_JSON_spec_object_const ("merchant",
+ &merchant),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_json ("summary_i18n",
- &summary_i18n),
+ GNUNET_JSON_spec_object_const ("summary_i18n",
+ &summary_i18n),
NULL),
GNUNET_JSON_spec_mark_optional (
GNUNET_JSON_spec_string ("fulfillment_message",
&fulfillment_msg),
NULL),
GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_json ("fulfillment_message_i18n",
- &fulfillment_i18n),
+ GNUNET_JSON_spec_object_const ("fulfillment_message_i18n",
+ &fulfillment_i18n),
NULL),
GNUNET_JSON_spec_timestamp ("timestamp",
&timestamp),
@@ -574,6 +573,7 @@ execute_order (struct OrderContext *oc)
MHD_HTTP_CONFLICT,
TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS,
oc->order_id);
+ GNUNET_JSON_parse_free (spec);
return;
}
}
@@ -796,9 +796,9 @@ set_exchanges (struct OrderContext *oc)
return;
}
GNUNET_assert (0 ==
- json_object_set (oc->order,
- "exchanges",
- exchanges));
+ json_object_set_new (oc->order,
+ "exchanges",
+ exchanges));
oc->phase++;
}
@@ -1614,8 +1614,7 @@ TMH_private_post_orders_with_pos_secrets (
hc->cc = &clean_order;
oc->connection = connection;
oc->hc = hc;
- if (NULL != pos_key)
- oc->pos_key = GNUNET_strdup (pos_key);
+ oc->pos_key = pos_key;
oc->pos_algorithm = pos_algorithm;
}
while (1)