diff --git a/lib/hsts.c b/lib/hsts.c index c00481fe60..ff21ad98d5 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -91,6 +91,20 @@ void Curl_hsts_cleanup(struct hsts **hp) } } +/* append the new entry to the list after possibly removing an old entry + first */ +static void hsts_append(struct hsts *h, struct stsentry *sts) +{ + if(Curl_llist_count(&h->list) == MAX_HSTS_ENTRIES) { + /* It's full. Remove the first entry in the list */ + struct Curl_llist_node *e = Curl_llist_head(&h->list); + struct stsentry *oldsts = Curl_node_elem(e); + Curl_node_remove(e); + hsts_free(oldsts); + } + Curl_llist_append(&h->list, sts, &sts->node); +} + static CURLcode hsts_create(struct hsts *h, const char *hostname, size_t hlen, @@ -111,7 +125,7 @@ static CURLcode hsts_create(struct hsts *h, memcpy(sts->host, hostname, hlen); sts->expires = expires; sts->includeSubDomains = subdomains; - Curl_llist_append(&h->list, sts, &sts->node); + hsts_append(h, sts); } return CURLE_OK; } diff --git a/lib/hsts.h b/lib/hsts.h index e0f6363bb3..6bd6cdb9a5 100644 --- a/lib/hsts.h +++ b/lib/hsts.h @@ -28,6 +28,8 @@ #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) #include "llist.h" +#define MAX_HSTS_ENTRIES 1000 + #if defined(DEBUGBUILD) || defined(UNITTESTS) extern time_t deltatime; #endif diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index c3496b133f..0256d0b6fc 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -223,7 +223,7 @@ test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 \ test1658 test1659 test1660 test1661 test1662 test1663 test1664 test1665 \ test1666 test1667 test1668 test1669 \ \ -test1670 test1671 test1672 test1673 \ +test1670 test1671 test1672 test1673 test1674 \ \ test1680 test1681 test1682 test1683 test1684 test1685 \ \ diff --git a/tests/data/test1674 b/tests/data/test1674 new file mode 100644 index 0000000000..00b440856e --- /dev/null +++ b/tests/data/test1674 @@ -0,0 +1,38 @@ + + + + +unittest +HSTS + + + + + +unittest +HSTS + + +# This date is exactly "20190124 22:34:21" UTC + +CURL_TIME=1548369261 + + +HSTS load more than 1,000 entries from file + + +# test 1674 renders the input file itself, then reads it + +%LOGDIR/hsts%TESTNUMBER + + + + + +Number of entries: 1000 + + +Allocations: 1100 + + + diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc index d8b2ed2d2e..0ab45a4df1 100644 --- a/tests/unit/Makefile.inc +++ b/tests/unit/Makefile.inc @@ -42,6 +42,7 @@ TESTS_C = \ unit1650.c unit1651.c unit1652.c unit1653.c unit1654.c unit1655.c unit1656.c \ unit1657.c unit1658.c unit1660.c unit1661.c unit1663.c unit1664.c \ unit1666.c unit1667.c unit1668.c unit1669.c \ + unit1674.c \ unit1979.c unit1980.c \ unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c \ unit3200.c unit3205.c \ diff --git a/tests/unit/unit1674.c b/tests/unit/unit1674.c new file mode 100644 index 0000000000..0491db95c2 --- /dev/null +++ b/tests/unit/unit1674.c @@ -0,0 +1,82 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#include "unitcheck.h" + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) + +#include "urldata.h" +#include "hsts.h" + +/* create a HSTS file with lots of unique host names all using the same + fixed expire time */ +static void render_unit1674(const char *file) +{ + FILE *f = curlx_fopen(file, FOPEN_WRITETEXT); + size_t i; + if(!f) + return; + for(i = 0; i < (MAX_HSTS_ENTRIES + 5); i++) { + curl_mfprintf(f, "host%zu.readfrom.example \"20211001 04:47:41\"\n", i); + } + curlx_fclose(f); +} + +static CURLcode test_unit1674(const char *arg) +{ + UNITTEST_BEGIN_SIMPLE + + struct hsts *h = Curl_hsts_init(); + CURL *easy; + char savename[256]; + + abort_unless(h, "Curl_hsts_init()"); + + render_unit1674(arg); + + curl_global_init(CURL_GLOBAL_ALL); + easy = curl_easy_init(); + if(!easy) { + Curl_hsts_cleanup(&h); + abort_unless(easy, "curl_easy_init()"); + } + + Curl_hsts_loadfile(easy, h, arg); + + curl_mprintf("Number of entries: %zu\n", Curl_llist_count(&h->list)); + + curl_msnprintf(savename, sizeof(savename), "%s.save", arg); + (void)Curl_hsts_save(easy, h, savename); + Curl_hsts_cleanup(&h); + curl_easy_cleanup(easy); + + UNITTEST_END(curl_global_cleanup()) +} +#else +static CURLcode test_unit1674(const char *arg) +{ + UNITTEST_BEGIN_SIMPLE + puts("nothing to do when HTTP or HSTS are disabled"); + UNITTEST_END_SIMPLE +} +#endif