curl-curl/tests/unit/unit1398.c
Viktor Szakats 92f215fea1
build: address some -Weverything warnings, update picky warnings
`-Weverything` is not enabled by curl, and not recommended by LLVM,
because it may enable experimental options, and will result in new
fallouts after toolchain upgrades. This patch aims to fix/silence as much
as possible as found with llvm/clang 21.1.0. It also permanently enables
warnings that were fixed in source and deemed manageable in the future.
`-Wformat` warnings are addressed separately via #18343.

Fix/silence warnings in the source:
- typecheck-gcc.h: fix `-Wreserved-identifier`.
- lib: silence `-Wcast-function-type-strict`.
  For llvm 16+ or Apple clang 16+.
- asyn-ares: limit `HAPPY_EYEBALLS_DNS_TIMEOUT` to old c-ares versions.
- curl_trc: fix `-Wc++-hidden-decl`.
- doh: fix `-Wc++-keyword`.
- ftp: fix `-Wreserved-identifier`.
- ldap: fix `-Wreserved-identifier`.
- mqtt: comment unused macro to avoid warning.
- multi_ev: drop unused macros to avoid warnings.
- setopt: fix useless `break;` after `return;`.
- gtls, mbedtls, rustls: silence `-Wconditional-uninitialized`.
- socks_sspi, schannel, x509asn1: fix `-Wimplicit-int-enum-cast`.
- x509asn1: fix `-Wc++-keyword`.
- openssl: scope `OSSL_UI_METHOD_CAST` to avoid unused macro warning.
- libssh2, wolfssl: drop unused macros.
- curl_ngtcp2, curl_quiche, httpsrr, urlapi: drop/limit unused macros.
- tool_getparam: fix useless `break;` after `return;` or `break;`.
  Not normally enabled because it doesn't work with unity.
  https://github.com/llvm/llvm-project/issues/71046
- tool_operate: fix `-Wc++-keyword`.
- curlinfo: fix a `-Wunsafe-buffer-usage`.
- tests: silence `-Wformat-non-iso`.
- lib557: fix `-Wreserved-identifier`.
- lib1565: silence `-Wconditional-uninitialized`.

Enable the above clang warnings permanently in picky mode:
- `-Wc++-hidden-decl`
- `-Wc++-keyword` (except for Windows, where it collides with `wchar_t`)
- `-Wcast-function-type-strict`
- `-Wcast-function-type`
- `-Wconditional-uninitialized`
- `-Wformat-non-iso` (except for clang-cl)
- `-Wreserved-identifier`
- `-Wtentative-definition-compat`

Silence problematic `-Weverything` warnings globally (in picky mode):
- `-Wused-but-marked-unused` (88000+ hits) and
  `-Wdisabled-macro-expansion` (2600+ hits).
  Triggered by `typecheck-gcc.h` when building with clang 14+.
  Maybe there exists a way to fix within that header?
  Ref: https://discourse.llvm.org/t/removing-wused-but-marked-unused/55310
- `-Wunsafe-buffer-usage`. clang 16+. 7000+ hits.
  May be useful in theory, but such high volume of hits makes it
  impractical to review and possibly address. Meant for C++.
  Ref: https://clang.llvm.org/docs/SafeBuffers.html
  Ref: https://stackoverflow.com/questions/77017567/how-to-fix-code-to-avoid-warning-wunsafe-buffer-usage
  Ref: https://discourse.llvm.org/t/rfc-c-buffer-hardening/65734
  Ref: https://github.com/llvm/llvm-project/pull/111624
- `-Wimplicit-void-ptr-cast`. clang 21+. 1700+ hits.
  C++ warning, deemed pure noise.
  Ref: https://github.com/curl/curl/issues/18470#issuecomment-3253506266
- `-Wswitch-default` (180+ hits), `-Wswitch-enum` (190+ hits),
  `-Wcovered-switch-default` (20+ hits).
  Next to impossible to fix cleanly, esp. when the covered `case`
  branches depend on compile-time options.
- `-Wdocumentation-unknown-command` (8+ hits).
  Triggered in a few sources. Seems arbitrary and bogus.
- `-Wpadded` (550+ hits).
- `-Wc++-keyword` on Windows, where it collides with `wchar_t`.
  (100+ hits)
  Ref: https://github.com/llvm/llvm-project/issues/155988
- `-Wreserved-macro-identifier`. clang 13+. 5+ hits.
  Sometimes it's necessary to set external macros that use
  the reserved namespace. E.g. `_CRT_NONSTDC_NO_DEPRECATE`,
  `__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__`, `__NO_NET_API`,
  possibly `_REENTRANT`, and more.
  It's not worth trying to silence them individually.
- `-Wnonportable-system-include-path` with `clang-cl`.
  It'd be broken by doing what the warning suggests.
- `-Wformat-non-iso` for clang-cl.

CMake `PICKY_COMPILER=ON` (the default) or `./configure`
`--enable-warnings` (not the default) is required to enable these
silencing rules.

Also:
- autotools, cmake: fix Apple clang and mainline llvm version translations.
  Ref: https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
- autotools, cmake: enable `-Warray-compare` for clang 20+.
  Follow-up to 4b7accda5a #17196
- cmake: fix to enable `-Wmissing-variable-declarations` at an earlier
  clang version.
- cmake: update internal logic to handle warning options with `+` in
  them.
- cmake: fix internal logic to match the whole option when looking
  into `CMAKE_C_FLAGS` for custom-disabled warnings.

Follow-up to b85cb8cb4e #18485

Closes #18477
2025-09-20 10:16:15 +02:00

201 lines
8.5 KiB
C

/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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_GNUC_DIAG) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
#endif
static CURLcode test_unit1398(const char *arg)
{
UNITTEST_BEGIN_SIMPLE
int rc;
char buf[3] = {'b', 'u', 'g'};
static const char *str = "bug";
int width = 3;
char output[130];
/*#define curl_msnprintf snprintf */
/* without a trailing zero */
rc = curl_msnprintf(output, 4, "%.*s", width, buf);
fail_unless(rc == 3, "return code should be 3");
fail_unless(!strcmp(output, "bug"), "wrong output");
/* with a trailing zero */
rc = curl_msnprintf(output, 4, "%.*s", width, str);
fail_unless(rc == 3, "return code should be 3");
fail_unless(!strcmp(output, "bug"), "wrong output");
width = 2;
/* one byte less */
rc = curl_msnprintf(output, 4, "%.*s", width, buf);
fail_unless(rc == 2, "return code should be 2");
fail_unless(!strcmp(output, "bu"), "wrong output");
/* string with larger precision */
rc = curl_msnprintf(output, 8, "%.8s", str);
fail_unless(rc == 3, "return code should be 3");
fail_unless(!strcmp(output, "bug"), "wrong output");
/* longer string with precision */
rc = curl_msnprintf(output, 8, "%.3s", "0123456789");
fail_unless(rc == 3, "return code should be 3");
fail_unless(!strcmp(output, "012"), "wrong output");
/* negative width */
rc = curl_msnprintf(output, 8, "%-8s", str);
fail_unless(rc == 7, "return code should be 7");
fail_unless(!strcmp(output, "bug "), "wrong output");
/* larger width that string length */
rc = curl_msnprintf(output, 8, "%8s", str);
fail_unless(rc == 7, "return code should be 7");
fail_unless(!strcmp(output, " bu"), "wrong output");
/* output a number in a limited output */
rc = curl_msnprintf(output, 4, "%d", 10240);
fail_unless(rc == 3, "return code should be 3");
fail_unless(!strcmp(output, "102"), "wrong output");
/* padded strings */
rc = curl_msnprintf(output, 16, "%8s%8s", str, str);
fail_unless(rc == 15, "return code should be 15");
fail_unless(!strcmp(output, " bug bu"), "wrong output");
/* padded numbers */
rc = curl_msnprintf(output, 16, "%8d%8d", 1234, 5678);
fail_unless(rc == 15, "return code should be 15");
fail_unless(!strcmp(output, " 1234 567"), "wrong output");
#if defined(__clang__) && \
(__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 1))
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-non-iso"
#endif
/* double precision */
rc = curl_msnprintf(output, 24, "%2$.*1$.99d", 3, 5678);
fail_unless(rc == 0, "return code should be 0");
#if defined(__clang__) && \
(__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 1))
#pragma clang diagnostic pop
#endif
/* 129 input % flags */
rc = curl_msnprintf(output, 130,
"%s%s%s%s%s%s%s%s%s%s" /* 10 */
"%s%s%s%s%s%s%s%s%s%s" /* 20 */
"%s%s%s%s%s%s%s%s%s%s" /* 30 */
"%s%s%s%s%s%s%s%s%s%s" /* 40 */
"%s%s%s%s%s%s%s%s%s%s" /* 50 */
"%s%s%s%s%s%s%s%s%s%s" /* 60 */
"%s%s%s%s%s%s%s%s%s%s" /* 70 */
"%s%s%s%s%s%s%s%s%s%s" /* 80 */
"%s%s%s%s%s%s%s%s%s%s" /* 90 */
"%s%s%s%s%s%s%s%s%s%s" /* 100 */
"%s%s%s%s%s%s%s%s%s%s" /* 110 */
"%s%s%s%s%s%s%s%s%s%s" /* 120 */
"%s%s%s%s%s%s%s%s%s", /* 129 */
"a", "", "", "", "", "", "", "", "", "", /* 10 */
"b", "", "", "", "", "", "", "", "", "", /* 20 */
"c", "", "", "", "", "", "", "", "", "", /* 30 */
"d", "", "", "", "", "", "", "", "", "", /* 40 */
"e", "", "", "", "", "", "", "", "", "", /* 50 */
"f", "", "", "", "", "", "", "", "", "", /* 60 */
"g", "", "", "", "", "", "", "", "", "", /* 70 */
"h", "", "", "", "", "", "", "", "", "", /* 80 */
"i", "", "", "", "", "", "", "", "", "", /* 90 */
"j", "", "", "", "", "", "", "", "", "", /* 100 */
"k", "", "", "", "", "", "", "", "", "", /* 110 */
"l", "", "", "", "", "", "", "", "", "", /* 120 */
"m", "", "", "", "", "", "", "", "" /* 129 */
);
fail_unless(rc == 0, "return code should be 0");
/* 128 input % flags */
rc = curl_msnprintf(output, 130,
"%s%s%s%s%s%s%s%s%s%s" /* 10 */
"%s%s%s%s%s%s%s%s%s%s" /* 20 */
"%s%s%s%s%s%s%s%s%s%s" /* 30 */
"%s%s%s%s%s%s%s%s%s%s" /* 40 */
"%s%s%s%s%s%s%s%s%s%s" /* 50 */
"%s%s%s%s%s%s%s%s%s%s" /* 60 */
"%s%s%s%s%s%s%s%s%s%s" /* 70 */
"%s%s%s%s%s%s%s%s%s%s" /* 80 */
"%s%s%s%s%s%s%s%s%s%s" /* 90 */
"%s%s%s%s%s%s%s%s%s%s" /* 100 */
"%s%s%s%s%s%s%s%s%s%s" /* 110 */
"%s%s%s%s%s%s%s%s%s%s" /* 120 */
"%s%s%s%s%s%s%s%s", /* 128 */
"a", "", "", "", "", "", "", "", "", "", /* 10 */
"b", "", "", "", "", "", "", "", "", "", /* 20 */
"c", "", "", "", "", "", "", "", "", "", /* 30 */
"d", "", "", "", "", "", "", "", "", "", /* 40 */
"e", "", "", "", "", "", "", "", "", "", /* 50 */
"f", "", "", "", "", "", "", "", "", "", /* 60 */
"g", "", "", "", "", "", "", "", "", "", /* 70 */
"h", "", "", "", "", "", "", "", "", "", /* 80 */
"i", "", "", "", "", "", "", "", "", "", /* 90 */
"j", "", "", "", "", "", "", "", "", "", /* 100 */
"k", "", "", "", "", "", "", "", "", "", /* 110 */
"l", "", "", "", "", "", "", "", "", "", /* 120 */
"m", "", "", "", "", "", "", "" /* 128 */
);
fail_unless(rc == 13, "return code should be 13");
/* 129 output segments */
rc = curl_msnprintf(output, 130,
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 20 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 40 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 60 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 80 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 100 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 120 */
"%%%%%%%%%%%%%%%%%%" /* 129 */
);
fail_unless(rc == 0, "return code should be 0");
/* 128 output segments */
rc = curl_msnprintf(output, 129,
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 20 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 40 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 60 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 80 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 100 */
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" /* 120 */
"%%%%%%%%%%%%%%%%" /* 128 */
);
fail_unless(rc == 128, "return code should be 128");
UNITTEST_END_SIMPLE
}
#if defined(CURL_GNUC_DIAG) || defined(__clang__)
#pragma GCC diagnostic pop
#endif