From 157dfc8a104bcd8f493093922883485ba1868820 Mon Sep 17 00:00:00 2001 From: Kevin Albertson Date: Tue, 29 Jun 2021 15:27:23 -0400 Subject: [PATCH] MONGOCRYPT-321 fix double free on oauth cache expiration (#178) --- CMakeLists.txt | 1 + src/mongocrypt-cache-oauth.c | 1 + test/test-mongocrypt-cache-oauth.c | 57 ++++++++++++++++++++++++++++++ test/test-mongocrypt-cache.c | 1 - test/test-mongocrypt.c | 1 + test/test-mongocrypt.h | 3 ++ 6 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 test/test-mongocrypt-cache-oauth.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a5727531d..57fb8711c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,6 +238,7 @@ set (TEST_MONGOCRYPT_SOURCES test/test-conveniences.c test/test-mongocrypt-buffer.c test/test-mongocrypt-cache.c + test/test-mongocrypt-cache-oauth.c test/test-mongocrypt-ciphertext.c test/test-mongocrypt-crypto.c test/test-mongocrypt-crypto-hooks.c diff --git a/src/mongocrypt-cache-oauth.c b/src/mongocrypt-cache-oauth.c index ab3e6144d..f0073933a 100644 --- a/src/mongocrypt-cache-oauth.c +++ b/src/mongocrypt-cache-oauth.c @@ -97,6 +97,7 @@ _mongocrypt_cache_oauth_get (_mongocrypt_cache_oauth_t *cache) if (bson_get_monotonic_time () >= cache->expiration_time_us) { bson_destroy (cache->entry); + cache->entry = NULL; cache->expiration_time_us = 0; _mongocrypt_mutex_unlock (&cache->mutex); return NULL; diff --git a/test/test-mongocrypt-cache-oauth.c b/test/test-mongocrypt-cache-oauth.c new file mode 100644 index 000000000..fe7aaf8ab --- /dev/null +++ b/test/test-mongocrypt-cache-oauth.c @@ -0,0 +1,57 @@ +/* + * Copyright 2021-present MongoDB, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test-mongocrypt.h" +#include "mongocrypt-cache-oauth-private.h" + +static void _test_cache_oauth_expiration (_mongocrypt_tester_t *tester) { + _mongocrypt_cache_oauth_t* cache; + char *token; + bool ret; + mongocrypt_status_t* status; + + cache = _mongocrypt_cache_oauth_new (); + token = _mongocrypt_cache_oauth_get (cache); + BSON_ASSERT (!token); + + status = mongocrypt_status_new (); + ret = _mongocrypt_cache_oauth_add (cache, TMP_BSON ("{'expires_in': 0, 'access_token': 'foo'}"), status); + ASSERT_OR_PRINT (ret, status); + /* Attempting to get the token will purge the new token from the cache. */ + token = _mongocrypt_cache_oauth_get (cache); + BSON_ASSERT (!token); + + /* Attempt to get again, to ensure MONGOCRYPT-321 is fixed. */ + token = _mongocrypt_cache_oauth_get (cache); + BSON_ASSERT (!token); + + /* Add an unexpired token. */ + ret = _mongocrypt_cache_oauth_add (cache, TMP_BSON ("{'expires_in': 1000, 'access_token': 'bar'}"), status); + ASSERT_OR_PRINT (ret, status); + + token = _mongocrypt_cache_oauth_get (cache); + ASSERT_STREQUAL (token, "bar"); + bson_free (token); + + _mongocrypt_cache_oauth_destroy (cache); + mongocrypt_status_destroy (status); +} + +void +_mongocrypt_tester_install_cache_oauth (_mongocrypt_tester_t *tester) +{ + INSTALL_TEST (_test_cache_oauth_expiration); +} \ No newline at end of file diff --git a/test/test-mongocrypt-cache.c b/test/test-mongocrypt-cache.c index 368b5481d..fb28083a5 100644 --- a/test/test-mongocrypt-cache.c +++ b/test/test-mongocrypt-cache.c @@ -255,7 +255,6 @@ _test_cache_duplicates (_mongocrypt_tester_t *tester) mongocrypt_status_destroy (status); _mongocrypt_cache_cleanup (&cache); } - void _mongocrypt_tester_install_cache (_mongocrypt_tester_t *tester) { diff --git a/test/test-mongocrypt.c b/test/test-mongocrypt.c index 3313b4c0d..3c616f7cc 100644 --- a/test/test-mongocrypt.c +++ b/test/test-mongocrypt.c @@ -790,6 +790,7 @@ main (int argc, char **argv) _test_setopt_kms_providers, CRYPTO_OPTIONAL); _mongocrypt_tester_install_kek (&tester); + _mongocrypt_tester_install_cache_oauth (&tester); printf ("Running tests...\n"); diff --git a/test/test-mongocrypt.h b/test/test-mongocrypt.h index 45fd09f7e..30be89f93 100644 --- a/test/test-mongocrypt.h +++ b/test/test-mongocrypt.h @@ -274,6 +274,9 @@ _mongocrypt_tester_install_endpoint (_mongocrypt_tester_t *tester); void _mongocrypt_tester_install_kek (_mongocrypt_tester_t *tester); +void +_mongocrypt_tester_install_cache_oauth (_mongocrypt_tester_t *tester); + /* Conveniences for getting test data. */ /* Get a temporary bson_t from a JSON string. Do not free it. */