curl-curl/tests/CMakeLists.txt
Viktor Szakats 6d87eb2878
cmake: add CURL_GCC_ANALYZER option, enable in CI, fix/silence
Enable in one existing Linux, macOS and Windows job.

Cost:
- Linux: +1.3 minutes.
- macOS: +1.5 minutes.
- Windows: +2.5 minutes.

Fix or silence issues found:
- conncache: silence NULL deref warning.
  ```
  lib/conncache.c:564:18: warning: dereference of NULL '*data.multi' [CWE-476] [-Wanalyzer-null-dereference]
  ```
  Ref: ede6a8e087 #19378
- http2: check pointer for NULL.
  ```
  lib/http2.c:388:7: error: dereference of NULL ‘data’ [CWE-476] [-Wanalyzer-null-dereference]
  ```
- http2: silence potential NULL deref in `cf_h2_recv`.
  ```
  lib/http2.c: In function 'cf_h2_recv':
  lib/curl_trc.h:62:15: warning: dereference of NULL 'data' [CWE-476] [-Wanalyzer-null-dereference]
  ```
- openldap: silence deref before NULL check.
  Seen in GHA/Linux.
  ```
  lib/openldap.c: In function ‘oldap_state_mechs_resp’:
  lib/curl_trc.h:140:7: warning: check of ‘data’ for NULL after already dereferencing it [-Wanalyzer-deref-before-check]
  ```
- sendf: silence NULL deref false positive in `Curl_creader_set_fread`.
  It looks impossible to happen.
  ```
  lib/sendf.c:1133:7: warning: dereference of NULL 'r' [CWE-476] [-Wanalyzer-null-dereference]
  ```
- ws: silence deref before NULL check.
  ```
  lib/ws.c: In function 'ws_send_raw_blocking':
  lib/curl_trc.h:205:7: warning: check of 'data' for NULL after already dereferencing it [-Wanalyzer-deref-before-check]
  ```
- var: fix potential NULL deref
  ```
  src/var.c:216:29: warning: dereference of NULL 'envp' [CWE-476] [-Wanalyzer-null-dereference]
  ```
- cli_hx_upload.c: fix NULL check after dereference.
  ```
  tests/libtest/cli_hx_upload.c:170:7: warning: check of '*t.method' for NULL after already dereferencing it [-Wanalyzer-deref-before-check]
  ```
- unit1607, unit1609: fix theoretical NULL ptr dereference.
  ```
  tests/unit/unit1607.c:211:12: warning: dereference of NULL 'addr' [CWE-476] [-Wanalyzer-null-dereference]
  tests/unit/unit1609.c:193:12: warning: dereference of NULL 'addr' [CWE-476] [-Wanalyzer-null-dereference]
  ```
- globally disable checks triggering false positives only:
  ```
  docs/examples/externalsocket.c:135:8: warning: 'connect' on possibly invalid file descriptor 'sockfd' [-Wanalyzer-fd-use-without-check]
  lib/bufq.c:465:16: warning: infinite loop [CWE-835] [-Wanalyzer-infinite-loop] (gcc-15 Windows)
  lib/doh.c:1035:34: warning: stack-based buffer over-read [CWE-126] [-Wanalyzer-out-of-bounds] (gcc-15 macOS)
  lib/ftp.c:4022:20: warning: infinite loop [CWE-835] [-Wanalyzer-infinite-loop] (gcc-15 macOS)
  lib/http2.c:689:28: warning: buffer over-read [CWE-126] [-Wanalyzer-out-of-bounds] (gcc-15 macOS)
  lib/socketpair.c:195:5: warning: leak of file descriptor 'curl_dbg_socket(2, 1, 0, 192, "D:/a/curl/curl/lib/socketpair.c")' [CWE-775] [-Wanalyzer-fd-leak]
  src/tool_doswin.c:810:7: warning: leak of file descriptor '*tdata.socket_l' [CWE-775] [-Wanalyzer-fd-leak]
  src/tool_doswin.c:816:9: warning: leak of file descriptor '*tdata.socket_l' [CWE-775] [-Wanalyzer-fd-leak]
  src/tool_main.c:96:1: warning: leak of file descriptor 'fd[0]' [CWE-775] [-Wanalyzer-fd-leak]
  src/tool_main.c:96:1: warning: leak of file descriptor 'fd[1]' [CWE-775] [-Wanalyzer-fd-leak]
  src/tool_urlglob.c:48:17: warning: leak of 'malloc(8)' [CWE-401] [-Wanalyzer-malloc-leak]
  src/tool_writeout.c:870:3: warning: leak of FILE 'stream2' [CWE-775] [-Wanalyzer-file-leak]
  tests/libtest/lib518.c:90:1: warning: leak of FILE [CWE-775] [-Wanalyzer-file-leak]
  tests/libtest/lib537.c:87:1: warning: leak of FILE [CWE-775] [-Wanalyzer-file-leak]
  tests/server/tftpd.c:1147:10: warning: 'bind' on possibly invalid file descriptor 'sock' [-Wanalyzer-fd-use-without-check]
  tests/server/tftpd.c:1155:10: warning: 'bind' on possibly invalid file descriptor 'sock' [-Wanalyzer-fd-use-without-check]
  tests/server/tftpd.c:1259:10: warning: 'connect' on possibly invalid file descriptor '4294967295' [-Wanalyzer-fd-use-without-check]
  ```

Also:
- cmake: update clang-tidy typecheck comment.

Ref: https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html

Closes #20921
2026-03-16 11:49:34 +01:00

153 lines
5.5 KiB
CMake

#***************************************************************************
# _ _ ____ _
# 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
#
###########################################################################
find_program(TEST_NGHTTPX "nghttpx")
if(NOT TEST_NGHTTPX)
set(TEST_NGHTTPX "")
endif()
mark_as_advanced(TEST_NGHTTPX)
# Consumed variables: TEST_NGHTTPX
configure_file("config.in" "${CMAKE_CURRENT_BINARY_DIR}/config" @ONLY)
add_custom_target(tt)
if(BUILD_CURL_EXE)
add_dependencies(tt "curlinfo")
endif()
if(CURL_BUILD_EVERYTHING)
set_target_properties(tt PROPERTIES EXCLUDE_FROM_ALL FALSE)
endif()
if(CURL_CLANG_TIDY)
add_custom_target(tests-clang-tidy)
add_dependencies(tt tests-clang-tidy)
endif()
if(CURL_ANALYZER_CFLAGS)
set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS ${CURL_ANALYZER_CFLAGS})
endif()
add_custom_target(testdeps)
add_dependencies(testdeps "tt")
add_subdirectory(http)
add_subdirectory(server)
add_subdirectory(libtest)
add_subdirectory(tunit)
add_subdirectory(unit)
add_subdirectory(certs)
# Add a runtests target with customized flags
function(curl_add_runtests _targetname _test_flags)
if(NOT BUILD_LIBCURL_DOCS)
string(APPEND _test_flags " !documentation")
endif()
set(_depends "")
# Skip walking through dependent targets before running tests in CI.
# This avoids: GNU Make doing a slow re-evaluation of all targets and
# skipping them, MSBuild doing a re-evaluation, and actually rebuilding them.
if(NOT _targetname STREQUAL "test-ci")
if(BUILD_CURL_EXE)
list(APPEND _depends "${EXE_NAME}")
endif()
list(APPEND _depends "testdeps")
endif()
set(_setenvs "")
if(CMAKE_CONFIGURATION_TYPES)
list(APPEND _setenvs "CURL_DIRSUFFIX=$<CONFIG>")
endif()
if(WIN32 AND NOT CMAKE_HOST_WIN32)
list(APPEND _setenvs "CURL_TEST_EXE_EXT_SRV=${CMAKE_EXECUTABLE_SUFFIX}") # .exe
list(APPEND _setenvs "CURL_TEST_EXE_EXT_TOOL=${CMAKE_EXECUTABLE_SUFFIX}") # .exe
list(APPEND _setenvs "CURL_TEST_EXE_RUNNER=wine")
endif()
if(_setenvs)
set(_setenvs "${CMAKE_COMMAND}" -E env ${_setenvs})
endif()
# Use a special '$TFLAGS' placeholder as last argument which will be
# replaced by the contents of the environment variable in runtests.pl.
# This is a workaround for CMake's limitation where commands executed by
# 'make' or 'ninja' cannot portably reference environment variables.
string(REPLACE " " ";" _test_flags_list "${_test_flags}")
add_custom_target(${_targetname}
COMMAND
${_setenvs}
"${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runtests.pl"
${_test_flags_list}
"\$TFLAGS"
DEPENDS "${_depends}"
VERBATIM USES_TERMINAL
)
endfunction()
# Add a pytests target with customized flags
function(curl_add_pytests _targetname _test_flags)
set(_depends "")
if(NOT _targetname STREQUAL "pytest-ci")
if(BUILD_CURL_EXE)
list(APPEND _depends "${EXE_NAME}" "curlinfo")
endif()
list(APPEND _depends "libtests")
list(APPEND _depends "build-certs")
endif()
string(REPLACE " " ";" _test_flags_list "${_test_flags}")
add_custom_target(${_targetname}
COMMAND pytest ${_test_flags_list} "${CMAKE_CURRENT_SOURCE_DIR}/http"
DEPENDS "${_depends}"
VERBATIM USES_TERMINAL
)
endfunction()
# Create configurehelp.pm, used by tests needing to run the C preprocessor.
if(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CURL_CPP "\"${CMAKE_C_COMPILER}\" -E")
if(APPLE AND CMAKE_OSX_SYSROOT)
string(APPEND CURL_CPP " -isysroot ${CMAKE_OSX_SYSROOT}")
endif()
string(APPEND CURL_CPP " ${CMAKE_C_FLAGS}")
# Add header directories, like autotools builds do.
get_property(_include_dirs TARGET ${LIB_SELECTED} PROPERTY INCLUDE_DIRECTORIES)
foreach(_include_dir IN LISTS _include_dirs)
string(APPEND CURL_CPP " -I${_include_dir}")
endforeach()
else()
set(CURL_CPP "cpp")
endif()
# Generate version script for the linker, for versioned symbols.
# Consumed variable:
# CURL_CPP
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/configurehelp.pm.in"
"${CMAKE_CURRENT_BINARY_DIR}/configurehelp.pm" @ONLY)
curl_add_runtests(tests "-a") # Avoid 'test', which is a reserved target name in CMake
curl_add_runtests(test-quiet "-a -s")
curl_add_runtests(test-am "-a -am")
curl_add_runtests(test-full "-a -p -r")
# ~flaky means that it ignores results of tests using the flaky keyword
curl_add_runtests(test-nonflaky "-a -p ~flaky ~timing-dependent")
curl_add_runtests(test-ci "-a -p ~flaky ~timing-dependent -r --retry=5 -j20 --buildinfo")
curl_add_runtests(test-torture "-a -t -j20")
curl_add_runtests(test-event "-a -e")
curl_add_pytests(curl-pytest "-n auto")
curl_add_pytests(curl-pytest-ci "-n auto -v")