# HG changeset patch # User Timo Sirainen # Date 1489619577 -7200 # Node ID 29066a72703ab4649671f52f53b8ed46355767ab # Parent 036d9f649c8b5696936236d9c3efda81087f87f6 lib-oauth2: Fix memory leak if HTTP URL parsing fails. Also delay calling the callback. The callers don't necessarily expect an immediate callback (auth/db-oauth2.c doesn't). diff -r 036d9f649c8b -r 29066a72703a src/lib-oauth2/oauth2-introspect.c --- a/src/lib-oauth2/oauth2-introspect.c Thu Mar 16 00:54:44 2017 +0200 +++ b/src/lib-oauth2/oauth2-introspect.c Thu Mar 16 01:12:57 2017 +0200 @@ -55,6 +55,16 @@ } } +static void oauth2_introspection_delayed_error(struct oauth2_request *req) +{ + struct oauth2_introspection_result fail = { + .success = FALSE, + .error = req->delayed_error + }; + oauth2_introspection_callback(req, &fail); + oauth2_request_free_internal(req); +} + #undef oauth2_introspection_start struct oauth2_request* oauth2_introspection_start(const struct oauth2_settings *set, @@ -67,9 +77,6 @@ pool_t pool = pool_alloconly_create_clean("oauth2 introspection", 1024); struct oauth2_request *req = p_new(pool, struct oauth2_request, 1); - struct oauth2_introspection_result fail = { - .success = FALSE, - }; struct http_url *url; const char *error; @@ -87,9 +94,10 @@ if (http_url_parse(str_c(enc), NULL, HTTP_URL_ALLOW_USERINFO_PART, pool, &url, &error) < 0) { - fail.error = t_strdup_printf("http_url_parse(%s) failed: %s", - str_c(enc), error); - oauth2_introspection_callback(req, &fail); + req->delayed_error = p_strdup_printf(pool, + "http_url_parse(%s) failed: %s", str_c(enc), error); + req->to_delayed_error = timeout_add_short(0, + oauth2_introspection_delayed_error, req); return req; } diff -r 036d9f649c8b -r 29066a72703a src/lib-oauth2/oauth2-private.h --- a/src/lib-oauth2/oauth2-private.h Thu Mar 16 00:54:44 2017 +0200 +++ b/src/lib-oauth2/oauth2-private.h Thu Mar 16 01:12:57 2017 +0200 @@ -11,6 +11,9 @@ struct istream *is; struct io *io; + const char *delayed_error; + struct timeout *to_delayed_error; + const char *username; void (*json_parsed_cb)(struct oauth2_request*, bool success, diff -r 036d9f649c8b -r 29066a72703a src/lib-oauth2/oauth2-refresh.c --- a/src/lib-oauth2/oauth2-refresh.c Thu Mar 16 00:54:44 2017 +0200 +++ b/src/lib-oauth2/oauth2-refresh.c Thu Mar 16 01:12:57 2017 +0200 @@ -95,6 +95,16 @@ } } +static void oauth2_refresh_delayed_error(struct oauth2_request *req) +{ + struct oauth2_refresh_result fail = { + .success = FALSE, + .error = req->delayed_error + }; + oauth2_refresh_callback(req, &fail); + oauth2_request_free_internal(req); +} + #undef oauth2_refresh_start struct oauth2_request* oauth2_refresh_start(const struct oauth2_settings *set, @@ -109,9 +119,6 @@ p_new(pool, struct oauth2_request, 1); struct http_url *url; const char *error; - struct oauth2_refresh_result fail = { - .success = FALSE - }; req->pool = pool; req->set = set; @@ -121,9 +128,11 @@ if (http_url_parse(req->set->refresh_url, NULL, HTTP_URL_ALLOW_USERINFO_PART, pool, &url, &error) < 0) { - fail.error = t_strdup_printf("http_url_parse(%s) failed: %s", - req->set->refresh_url, error); - oauth2_refresh_callback(req, &fail); + req->delayed_error = p_strdup_printf(pool, + "http_url_parse(%s) failed: %s", + req->set->refresh_url, error); + req->to_delayed_error = timeout_add_short(0, + oauth2_refresh_delayed_error, req); return req; } diff -r 036d9f649c8b -r 29066a72703a src/lib-oauth2/oauth2-token-validate.c --- a/src/lib-oauth2/oauth2-token-validate.c Thu Mar 16 00:54:44 2017 +0200 +++ b/src/lib-oauth2/oauth2-token-validate.c Thu Mar 16 01:12:57 2017 +0200 @@ -83,6 +83,16 @@ } } +static void oauth2_token_validation_delayed_error(struct oauth2_request *req) +{ + struct oauth2_token_validation_result fail = { + .success = FALSE, + .error = req->delayed_error + }; + oauth2_token_validation_callback(req, &fail); + oauth2_request_free_internal(req); +} + #undef oauth2_token_validation_start struct oauth2_request* oauth2_token_validation_start(const struct oauth2_settings *set, @@ -94,9 +104,6 @@ struct http_url *url; const char *error; - struct oauth2_token_validation_result fail = { - .success = FALSE - }; pool_t pool = pool_alloconly_create_clean("oauth2 token_validation", 1024); struct oauth2_request *req = @@ -113,9 +120,10 @@ if (http_url_parse(str_c(enc), NULL, HTTP_URL_ALLOW_USERINFO_PART, pool, &url, &error) < 0) { - fail.error = t_strdup_printf("http_url_parse(%s) failed: %s", - str_c(enc), error); - oauth2_token_validation_callback(req, &fail); + req->delayed_error = p_strdup_printf(pool, + "http_url_parse(%s) failed: %s", str_c(enc), error); + req->to_delayed_error = timeout_add_short(0, + oauth2_token_validation_delayed_error, req); return req; } diff -r 036d9f649c8b -r 29066a72703a src/lib-oauth2/oauth2.c --- a/src/lib-oauth2/oauth2.c Thu Mar 16 00:54:44 2017 +0200 +++ b/src/lib-oauth2/oauth2.c Thu Mar 16 01:12:57 2017 +0200 @@ -73,6 +73,8 @@ void oauth2_request_free_internal(struct oauth2_request *req) { + if (req->to_delayed_error != NULL) + timeout_remove(&req->to_delayed_error); pool_unref(&req->pool); }