From 288f5a4b525da46fffe0f00f68cc9922aa2ab706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 9 Sep 2019 14:05:31 +0200 Subject: [PATCH] Various little fixes found by coccinelle The coccinellery repository provides many little semantic patches to fix common problems in the code. The number of semantic patches in the coccinellery repository is high and most of the semantic patches apply only for Linux, so it doesn't make sense to run them on regular basis as the processing takes a lot of time. The list of issue found in BIND 9, by no means complete, includes: - double assignment to a variable - `continue` at the end of the loop - double checks for `NULL` - useless checks for `NULL` (cannot be `NULL`, because of earlier return) - using `0` instead of `NULL` - useless extra condition (`if (foo) return; if (!foo) { ...; }`) - removing & in front of static functions passed as arguments --- bin/delv/delv.c | 8 ++--- bin/dig/dighost.c | 1 - bin/dnssec/dnssec-signzone.c | 2 -- bin/named/fuzz.c | 9 +++--- contrib/dlz/drivers/dlz_bdbhpt_driver.c | 3 +- contrib/dlz/drivers/dlz_mysql_driver.c | 7 +--- contrib/dlz/drivers/dlz_odbc_driver.c | 9 ++---- contrib/dlz/drivers/dlz_postgres_driver.c | 7 +--- .../dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c | 3 +- contrib/dlz/modules/common/dlz_dbi.c | 3 +- .../filesystem/dlz_filesystem_dynamic.c | 1 - contrib/dlz/modules/mysql/dlz_mysql_dynamic.c | 6 +--- .../dlz/modules/sqlite3/dlz_sqlite3_dynamic.c | 14 +++----- lib/dns/dnsrps.c | 2 +- lib/dns/dnstap.c | 32 +++++++++++-------- lib/dns/ds.c | 4 +-- lib/dns/openssldh_link.c | 2 +- lib/dns/opensslecdsa_link.c | 18 ++++------- lib/dns/openssleddsa_link.c | 9 ++---- lib/dns/opensslrsa_link.c | 5 ++- lib/isc/xoshiro128starstar.c | 4 +-- lib/isccfg/namedconf.c | 2 +- lib/ns/hooks.c | 4 +-- lib/ns/xfrout.c | 2 +- 24 files changed, 59 insertions(+), 98 deletions(-) diff --git a/bin/delv/delv.c b/bin/delv/delv.c index 7155d4b299..144b26c1f0 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -635,14 +635,12 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) { if (!match_root) { return (ISC_R_SUCCESS); } - if (!root_validation && match_root) { + + if (!root_validation) { return (ISC_R_SUCCESS); } - if (match_root) { - delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", - trust_anchor); - } + delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", trust_anchor); flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 222b7875bf..5e24af65e5 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -649,7 +649,6 @@ make_empty_lookup(void) { looknew->use_usec = false; looknew->nocrypto = false; looknew->ttlunits = false; - looknew->ttlunits = false; looknew->expandaaaa = false; looknew->qr = false; looknew->accept_reply_unexpected_src = false; diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 5f3cfa9ad4..8f3e74cb2c 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -1706,7 +1706,6 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which, result = dns_db_deleterdataset(gdb, node, gversion, type, covers); check_result(result, "dns_db_deleterdataset()"); - continue; } } dns_rdatasetiter_destroy(&rdsiter); @@ -3583,7 +3582,6 @@ main(int argc, char *argv[]) { outputformat = dns_masterformat_raw; } else if (strncasecmp(outputformatstr, "raw=", 4) == 0) { char *end; - outputformat = dns_masterformat_raw; outputformat = dns_masterformat_raw; rawversion = strtol(outputformatstr + 4, &end, 10); diff --git a/bin/named/fuzz.c b/bin/named/fuzz.c index 02c75d303a..0064d92075 100644 --- a/bin/named/fuzz.c +++ b/bin/named/fuzz.c @@ -142,7 +142,7 @@ fuzz_thread_client(void *arg) { * Read the reply message from named to unclog it. Don't * bother if there isn't a reply. */ - recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL); + (void)recvfrom(sockfd, buf, 65536, MSG_DONTWAIT, NULL, NULL); while (!ready) pthread_cond_wait(&cond, &mutex); @@ -412,8 +412,8 @@ fuzz_thread_resolver(void *arg) { * Flush any pending data on the authoritative server. */ socklen = sizeof(recvaddr); - sent = recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT, - (struct sockaddr *) &recvaddr, &socklen); + (void)recvfrom(listenfd, rbuf, 65536, MSG_DONTWAIT, + (struct sockaddr *) &recvaddr, &socklen); /* * Send a fixed client query to named(resolver) of @@ -511,7 +511,8 @@ fuzz_thread_resolver(void *arg) { * to the client(query driver), so we're * done. */ - recvfrom(sockfd, buf, 65536, 0, NULL, NULL); + (void)recvfrom(sockfd, buf, 65536, 0, NULL, + NULL); break; } diff --git a/contrib/dlz/drivers/dlz_bdbhpt_driver.c b/contrib/dlz/drivers/dlz_bdbhpt_driver.c index 1f20015860..4d3d935607 100644 --- a/contrib/dlz/drivers/dlz_bdbhpt_driver.c +++ b/contrib/dlz/drivers/dlz_bdbhpt_driver.c @@ -591,8 +591,7 @@ bdbhpt_lookup(const char *zone, const char *name, void *driverarg, if (data_cursor != NULL) data_cursor->c_close(data_cursor); - if (keyStr != NULL) - free(keyStr); + free(keyStr); if (tmp != NULL) free(tmp); diff --git a/contrib/dlz/drivers/dlz_mysql_driver.c b/contrib/dlz/drivers/dlz_mysql_driver.c index da1c9393c0..5e4366dac5 100644 --- a/contrib/dlz/drivers/dlz_mysql_driver.c +++ b/contrib/dlz/drivers/dlz_mysql_driver.c @@ -138,8 +138,7 @@ mysql_get_resultset(const char *zone, const char *record, /* if DBI is null, can't do anything else */ if (dbi == NULL) { - result = ISC_R_FAILURE; - goto cleanup; + return (ISC_R_FAILURE); } /* what type of query are we going to run? */ @@ -330,10 +329,6 @@ mysql_get_resultset(const char *zone, const char *record, cleanup: /* it's always good to cleanup after yourself */ - /* if we couldn't even get DBI, just return NULL */ - if (dbi == NULL) - return ISC_R_FAILURE; - /* free dbi->zone string */ if (dbi->zone != NULL) isc_mem_free(named_g_mctx, dbi->zone); diff --git a/contrib/dlz/drivers/dlz_odbc_driver.c b/contrib/dlz/drivers/dlz_odbc_driver.c index c5a1a156f3..59e31441e0 100644 --- a/contrib/dlz/drivers/dlz_odbc_driver.c +++ b/contrib/dlz/drivers/dlz_odbc_driver.c @@ -35,7 +35,7 @@ /* * Copyright (C) 1999-2001, 2016 Internet Systems Consortium, Inc. ("ISC") - * + * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -433,8 +433,7 @@ odbc_get_resultset(const char *zone, const char *record, /* if DBI is null, can't do anything else */ if (dbi == NULL) { - result = ISC_R_FAILURE; - goto cleanup; + return (ISC_R_FAILURE); } /* what type of query are we going to run? */ @@ -616,10 +615,6 @@ odbc_get_resultset(const char *zone, const char *record, cleanup: /* it's always good to cleanup after yourself */ - /* if we couldn't even allocate DBI, just return NULL */ - if (dbi == NULL) - return ISC_R_FAILURE; - /* free dbi->zone string */ if (dbi->zone != NULL) isc_mem_free(named_g_mctx, dbi->zone); diff --git a/contrib/dlz/drivers/dlz_postgres_driver.c b/contrib/dlz/drivers/dlz_postgres_driver.c index 3bd72b59ee..ec6fd93686 100644 --- a/contrib/dlz/drivers/dlz_postgres_driver.c +++ b/contrib/dlz/drivers/dlz_postgres_driver.c @@ -303,8 +303,7 @@ postgres_get_resultset(const char *zone, const char *record, /* if DBI is null, can't do anything else */ if (dbi == NULL) { - result = ISC_R_FAILURE; - goto cleanup; + return (ISC_R_FAILURE); } /* what type of query are we going to run? */ @@ -564,10 +563,6 @@ postgres_get_resultset(const char *zone, const char *record, "%d cleaning up", dlz_thread_num); #endif - /* if we couldn't even allocate DBI, just return NULL */ - if (dbi == NULL) - return ISC_R_FAILURE; - /* free dbi->zone string */ if (dbi->zone != NULL) isc_mem_free(named_g_mctx, dbi->zone); diff --git a/contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c b/contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c index 43e54f9792..859605f63c 100644 --- a/contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c +++ b/contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c @@ -594,8 +594,7 @@ isc_result_t dlz_lookup(const char *zone, const char *name, void *dbdata, if (data_cursor != NULL) data_cursor->c_close(data_cursor); - if (keyStr != NULL) - free(keyStr); + free(keyStr); if (tmp != NULL) free(tmp); diff --git a/contrib/dlz/modules/common/dlz_dbi.c b/contrib/dlz/modules/common/dlz_dbi.c index 7b4c9da5f0..e4c27bb746 100644 --- a/contrib/dlz/modules/common/dlz_dbi.c +++ b/contrib/dlz/modules/common/dlz_dbi.c @@ -255,8 +255,7 @@ build_querylist(const char *query_str, char **zone, char **record, flag_fail: /* get rid of what was build of the query list */ - if (tql != NULL) - destroy_querylist(&tql); + destroy_querylist(&tql); return (result); } diff --git a/contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c b/contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c index 494bd1805a..a143fd5e96 100644 --- a/contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c +++ b/contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c @@ -595,7 +595,6 @@ dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) { dir_entry_t *next_de; basepath = NULL; - dir_list = NULL; /* allocate memory for list */ dir_list = malloc(sizeof(dlist_t)); diff --git a/contrib/dlz/modules/mysql/dlz_mysql_dynamic.c b/contrib/dlz/modules/mysql/dlz_mysql_dynamic.c index a325fc5d22..84ab45f6e0 100644 --- a/contrib/dlz/modules/mysql/dlz_mysql_dynamic.c +++ b/contrib/dlz/modules/mysql/dlz_mysql_dynamic.c @@ -246,8 +246,7 @@ mysql_get_resultset(const char *zone, const char *record, #endif /* PTHREADS */ if (dbi == NULL) { - result = ISC_R_FAILURE; - goto cleanup; + return (ISC_R_FAILURE); } /* what type of query are we going to run? */ @@ -401,9 +400,6 @@ mysql_get_resultset(const char *zone, const char *record, result = ISC_R_FAILURE; cleanup: - if (dbi == NULL) - return (ISC_R_FAILURE); - if (dbi->zone != NULL) { free(dbi->zone); dbi->zone = NULL; diff --git a/contrib/dlz/modules/sqlite3/dlz_sqlite3_dynamic.c b/contrib/dlz/modules/sqlite3/dlz_sqlite3_dynamic.c index 2d7d0b0675..caf519f5d5 100644 --- a/contrib/dlz/modules/sqlite3/dlz_sqlite3_dynamic.c +++ b/contrib/dlz/modules/sqlite3/dlz_sqlite3_dynamic.c @@ -35,7 +35,7 @@ /* * Copyright (C) 1999-2001, 2013-2014, 2016 Internet Systems Consortium, Inc. ("ISC") - * + * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -277,8 +277,7 @@ sqlite3_get_resultset(const char *zone, const char *record, #endif /* PTHREADS */ if (dbi == NULL) { - result = ISC_R_FAILURE; - goto cleanup; + return (ISC_R_FAILURE); } /* what type of query are we going to run? */ @@ -431,16 +430,13 @@ sqlite3_get_resultset(const char *zone, const char *record, result = ISC_R_SUCCESS; if (query == COUNTZONE) { sqlite3_free_table(rs->pazResult); - if (rs == NULL) - result = ISC_R_FAILURE; } - *rsp = rs; + if (rsp != NULL) { + *rsp = rs; + } cleanup: - if (dbi == NULL) - return (ISC_R_FAILURE); - if (dbi->zone != NULL) { free(dbi->zone); dbi->zone = NULL; diff --git a/lib/dns/dnsrps.c b/lib/dns/dnsrps.c index 7ecc53f1c0..c4f68e15b3 100644 --- a/lib/dns/dnsrps.c +++ b/lib/dns/dnsrps.c @@ -146,7 +146,7 @@ dns_dnsrps_server_create(void) { isc_mutex_init(&dnsrps_mutex); - librpz->set_log(&dnsrps_log_fnc, NULL); + librpz->set_log(dnsrps_log_fnc, NULL); clist = librpz->clist_create(&emsg, dnsrps_lock, dnsrps_unlock, dnsrps_mutex_destroy, &dnsrps_mutex, diff --git a/lib/dns/dnstap.c b/lib/dns/dnstap.c index 7a4a01ea60..4e7d8e7b48 100644 --- a/lib/dns/dnstap.c +++ b/lib/dns/dnstap.c @@ -266,14 +266,17 @@ dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path, *envp = env; cleanup: - if (ffwopt != NULL) + if (ffwopt != NULL) { fstrm_file_options_destroy(&ffwopt); + } - if (fuwopt != NULL) + if (fuwopt != NULL) { fstrm_unix_writer_options_destroy(&fuwopt); + } - if (fwopt != NULL) + if (fwopt != NULL) { fstrm_writer_options_destroy(&fwopt); + } if (result != ISC_R_SUCCESS) { isc_mutex_destroy(&env->reopen_lock); @@ -337,8 +340,7 @@ dns_dt_reopen(dns_dtenv_t *env, int roll) { */ fwopt = fstrm_writer_options_init(); if (fwopt == NULL) { - isc_task_endexclusive(env->reopen_task); - return (ISC_R_NOMEMORY); + CHECK(ISC_R_NOMEMORY); } res = fstrm_writer_options_add_content_type(fwopt, @@ -414,17 +416,21 @@ dns_dt_reopen(dns_dtenv_t *env, int roll) { } cleanup: - if (ffwopt != NULL) - fstrm_file_options_destroy(&ffwopt); - - if (fw != NULL) + if (fw != NULL) { fstrm_writer_destroy(&fw); + } - if (fwopt != NULL) - fstrm_writer_options_destroy(&fwopt); - - if (fuwopt != NULL) + if (fuwopt != NULL) { fstrm_unix_writer_options_destroy(&fuwopt); + } + + if (ffwopt != NULL) { + fstrm_file_options_destroy(&ffwopt); + } + + if (fwopt != NULL) { + fstrm_writer_options_destroy(&fwopt); + } isc_task_endexclusive(env->reopen_task); diff --git a/lib/dns/ds.c b/lib/dns/ds.c index 857afe7ef2..8958fb89cf 100644 --- a/lib/dns/ds.c +++ b/lib/dns/ds.c @@ -118,8 +118,6 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, ret = dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds, &ds, &b); end: - if (md != NULL) { - isc_md_free(md); - } + isc_md_free(md); return (ret); } diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c index 7f9c244c6a..ff14c7e956 100644 --- a/lib/dns/openssldh_link.c +++ b/lib/dns/openssldh_link.c @@ -306,7 +306,7 @@ openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) { } else { /* cppcheck-suppress unreadVariable */ u.fptr = callback; - BN_GENCB_set(cb, &progress_cb, u.dptr); + BN_GENCB_set(cb, progress_cb, u.dptr); } if (!DH_generate_parameters_ex(dh, key->key_size, generator, diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c index 895f16da45..04cef6dbda 100644 --- a/lib/dns/opensslecdsa_link.c +++ b/lib/dns/opensslecdsa_link.c @@ -186,8 +186,7 @@ opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { ret = ISC_R_SUCCESS; err: - if (eckey != NULL) - EC_KEY_free(eckey); + EC_KEY_free(eckey); return (ret); } @@ -251,8 +250,7 @@ opensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { err: if (ecdsasig != NULL) ECDSA_SIG_free(ecdsasig); - if (eckey != NULL) - EC_KEY_free(eckey); + EC_KEY_free(eckey); return (ret); } @@ -340,8 +338,7 @@ opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { ret = ISC_R_SUCCESS; err: - if (eckey != NULL) - EC_KEY_free(eckey); + EC_KEY_free(eckey); return (ret); } @@ -396,8 +393,7 @@ opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) { ret = ISC_R_SUCCESS; err: - if (eckey != NULL) - EC_KEY_free(eckey); + EC_KEY_free(eckey); return (ret); } @@ -497,8 +493,7 @@ opensslecdsa_tofile(const dst_key_t *key, const char *directory) { ret = dst__privstruct_writefile(key, &priv, directory); err: - if (eckey != NULL) - EC_KEY_free(eckey); + EC_KEY_free(eckey); if (buf != NULL) isc_mem_put(key->mctx, buf, BN_num_bytes(privkey)); return (ret); @@ -529,8 +524,7 @@ ecdsa_check(EC_KEY *eckey, dst_key_t *pub) DST_RET (ISC_R_SUCCESS); err: - if (pubeckey != NULL) - EC_KEY_free(pubeckey); + EC_KEY_free(pubeckey); return (ret); } diff --git a/lib/dns/openssleddsa_link.c b/lib/dns/openssleddsa_link.c index 8357bee058..717e9eaa82 100644 --- a/lib/dns/openssleddsa_link.c +++ b/lib/dns/openssleddsa_link.c @@ -367,8 +367,7 @@ openssleddsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { ret = ISC_R_SUCCESS; err: - if (ctx != NULL) - EVP_MD_CTX_free(ctx); + EVP_MD_CTX_free(ctx); isc_buffer_free(&buf); dctx->ctxdata.generic = NULL; @@ -435,8 +434,7 @@ openssleddsa_verify(dst_context_t *dctx, const isc_region_t *sig) { } err: - if (ctx != NULL) - EVP_MD_CTX_free(ctx); + EVP_MD_CTX_free(ctx); isc_buffer_free(&buf); dctx->ctxdata.generic = NULL; @@ -507,8 +505,7 @@ openssleddsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { ret = ISC_R_SUCCESS; err: - if (ctx != NULL) - EVP_PKEY_CTX_free(ctx); + EVP_PKEY_CTX_free(ctx); return (ret); } diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index ecf13c7625..1a61c9f366 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -497,7 +497,7 @@ opensslrsa_generate(dst_key_t *key, int exp, void (*callback)(int)) { } else { /* cppcheck-suppress unreadVariable */ u.fptr = callback; - BN_GENCB_set(cb, &progress_cb, u.dptr); + BN_GENCB_set(cb, progress_cb, u.dptr); } if (RSA_generate_key_ex(rsa, key->key_size, e, cb)) { @@ -600,8 +600,7 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) { ret = ISC_R_SUCCESS; err: - if (rsa != NULL) - RSA_free(rsa); + RSA_free(rsa); return (ret); } diff --git a/lib/isc/xoshiro128starstar.c b/lib/isc/xoshiro128starstar.c index 0882041a74..abf1ea8455 100644 --- a/lib/isc/xoshiro128starstar.c +++ b/lib/isc/xoshiro128starstar.c @@ -50,7 +50,7 @@ static __declspec( thread ) uint32_t seed[4]; #else #if defined(_WIN32) || defined(_WIN64) #include -static volatile HANDLE _mutex = NULL; +static volatile void *_mutex = NULL; /* * Initialize the mutex on the first lock attempt. On collision, each thread @@ -60,7 +60,7 @@ static volatile HANDLE _mutex = NULL; #define _LOCK() \ do { \ if (!_mutex) { \ - HANDLE p = CreateMutex(NULL, FALSE, NULL); \ + void *p = CreateMutex(NULL, FALSE, NULL); \ if (InterlockedCompareExchangePointer \ ((void **)&_mutex, (void *)p, NULL)) { \ CloseHandle(p); \ diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index b6c70e4bc6..d427ec488d 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -312,7 +312,7 @@ static cfg_type_t cfg_type_matchtype = { static cfg_type_t cfg_type_matchname = { "optional_matchname", parse_matchname, cfg_print_ustring, - &doc_matchname, &cfg_rep_tuple, &cfg_type_ustring + doc_matchname, &cfg_rep_tuple, &cfg_type_ustring }; /*% diff --git a/lib/ns/hooks.c b/lib/ns/hooks.c index d89a063ad2..8a60042c51 100644 --- a/lib/ns/hooks.c +++ b/lib/ns/hooks.c @@ -211,9 +211,7 @@ cleanup: sizeof(*plugin)); } - if (handle != NULL) { - (void) dlclose(handle); - } + (void) dlclose(handle); } return (result); diff --git a/lib/ns/xfrout.c b/lib/ns/xfrout.c index 55609bbbaa..7672f59d9a 100644 --- a/lib/ns/xfrout.c +++ b/lib/ns/xfrout.c @@ -279,7 +279,7 @@ ixfr_rrstream_current(rrstream_t *rs, static void ixfr_rrstream_destroy(rrstream_t **rsp) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp; - if (s->journal != 0) + if (s->journal != NULL) dns_journal_destroy(&s->journal); isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); }