commit b0c73f8d7c39b6c342b497030b31ec6dc089e9c5
parent c50f08ddd051b165012c9b331eb34acc5c03a828
Author: Christian Grothoff <grothoff@gnunet.org>
Date: Mon, 20 Jul 2026 09:19:39 +0200
keep data_source alive while MHD needs it
Diffstat:
4 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
@@ -329,6 +329,7 @@ handle_mhd_completion_callback (void *cls,
hc->cc (hc->ctx);
TALER_MHD_parse_post_cleanup_callback (hc->json_parse_context);
GNUNET_free (hc->infix);
+ GNUNET_free (hc->rewritten_url);
if (NULL != hc->request_body)
json_decref (hc->request_body);
if (NULL != hc->instance)
diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h
@@ -615,6 +615,17 @@ struct TMH_HandlerContext
char *infix;
/**
+ * URL a request was internally rewritten to (e.g. by the
+ * POST /reports/$REPORT_ID handler that re-dispatches to the
+ * report's data source). When a request is rewritten, query
+ * arguments are registered on the connection with pointers
+ * *into* this buffer via MHD_set_connection_value(), which does
+ * not copy them; the buffer must therefore stay alive until the
+ * connection is finished. Freed in the completion callback.
+ */
+ char *rewritten_url;
+
+ /**
* Which connection was suspended.
*/
struct MHD_Connection *connection;
diff --git a/src/backend/taler-merchant-httpd_dispatcher.c b/src/backend/taler-merchant-httpd_dispatcher.c
@@ -1475,6 +1475,10 @@ identify_handler (struct TMH_HandlerContext *hc,
suffix_url = slash + 1; /* skip the '/' */
suffix_strlen = strlen (suffix_url);
}
+ /* free any previously set infix in case the request is being
+ re-dispatched (e.g. via POST /reports/$REPORT_ID), otherwise
+ the earlier infix would be leaked */
+ GNUNET_free (hc->infix);
hc->infix = GNUNET_strndup (infix_url,
infix_strlen);
}
diff --git a/src/backend/taler-merchant-httpd_post-reports-REPORT_ID.c b/src/backend/taler-merchant-httpd_post-reports-REPORT_ID.c
@@ -174,6 +174,15 @@ TMH_post_reports_ID (
}
hc->rh = NULL; /* just to make it clear: current one will NOT remain */
+ /* The query arguments parsed above were registered on the
+ connection with pointers *into* @e data_source (MHD does not
+ copy them). Ownership of @e data_source is therefore handed to
+ @e hc, which frees it only once the connection is finished; we
+ must NOT free it here (doing so would leave the connection --
+ and the re-dispatched GET handler that reads those arguments --
+ with dangling pointers). */
+ GNUNET_free (hc->rewritten_url);
+ hc->rewritten_url = data_source;
ret = TMH_dispatch_request (hc,
data_source,
MHD_HTTP_METHOD_GET,
@@ -183,13 +192,11 @@ TMH_post_reports_ID (
if (GNUNET_OK != ret)
{
GNUNET_free (instance_id);
- GNUNET_free (data_source);
return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
}
GNUNET_break (NULL != hc->rh);
}
GNUNET_free (instance_id);
- GNUNET_free (data_source);
/* MHD will call the main handler again, which will now
dispatch into the _new_ handler callback we just installed! */
return MHD_YES;