cmake: add `CURL_GCC_ANALYZER` option, enable in CI, fix/silence
No binary (build failed)
—
(log yok)
| @@ -174,11 +174,11 @@ jobs: | |
| install_steps: pytest | |
| configure: --with-openssl --enable-debug --disable-unity | |
| - | - name: 'openssl libssh2 sync-resolver valgrind 1' |
| + | - name: 'openssl libssh2 sync-resolver valgrind 1 +analyzer' |
| image: ubuntu-24.04-arm | |
| install_packages: libidn2-dev libssh2-1-dev libnghttp2-dev libldap-dev valgrind | |
| tflags: '--min=920 1 to 950' | |
| - | generate: -DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF |
| + | generate: -DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF -DCURL_GCC_ANALYZER=ON |
| - name: 'openssl libssh2 sync-resolver valgrind 2' | |
| image: ubuntu-24.04-arm | |
| @@ -314,10 +314,10 @@ jobs: | |
| compiler: clang | |
| install: gnutls nettle krb5 | |
| generate: -DENABLE_DEBUG=ON -DCURL_USE_GNUTLS=ON -DCURL_USE_OPENSSL=OFF -DCURL_USE_GSSAPI=ON -DGSS_ROOT_DIR=/opt/homebrew/opt/krb5 -DCURL_DISABLE_LDAP=ON -DUSE_SSLS_EXPORT=ON | |
| - | - name: 'aws-lc' |
| - | compiler: gcc-13 |
| + | - name: 'aws-lc +analyzer' |
| + | compiler: gcc-15 |
| install: aws-lc | |
| - | generate: -DENABLE_DEBUG=ON -DCURL_USE_OPENSSL=ON -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/aws-lc -DUSE_ECH=ON -DCURL_DISABLE_LDAP=ON -DUSE_SSLS_EXPORT=ON |
| + | generate: -DENABLE_DEBUG=ON -DCURL_USE_OPENSSL=ON -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/aws-lc -DUSE_ECH=ON -DCURL_DISABLE_LDAP=ON -DUSE_SSLS_EXPORT=ON -DCURL_GCC_ANALYZER=ON |
| - name: 'Rustls' | |
| compiler: clang | |
| install: rustls-ffi | |
| @@ -474,14 +474,14 @@ jobs: | |
| strategy: | |
| matrix: | |
| include: | |
| - | - name: 'schannel' # mingw-w64 12.0 |
| + | - name: 'schannel +analyzer' # mingw-w64 12.0 |
| sys: 'mingw64' | |
| dir: 'w64devkit' | |
| env: 'x86_64' | |
| ver: '15.1.0' | |
| url: 'https://github.com/skeeto/w64devkit/releases/download/v2.2.0/w64devkit-x64-2.2.0.7z.exe' | |
| SHA256: e02de30b97196329662007d64bc4509fbd7f5e14339d344075c7f1223dead4a2 | |
| - | config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=OFF -DENABLE_UNIX_SOCKETS=OFF' |
| + | config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=OFF -DENABLE_UNIX_SOCKETS=OFF -DCURL_GCC_ANALYZER=ON' |
| type: 'Release' | |
| - name: 'schannel' # mingw-w64 10.0 | |
| sys: 'mingw64' | |
| @@ -273,7 +273,7 @@ if(CURL_CLANG_TIDY) | |
| set(PICKY_COMPILER OFF) # Do a best effort and skip passing non-clang warning options to clang-tidy. | |
| # This lets through warning options enabled via CURL_WERROR=ON, affecting lib and src. | |
| endif() | |
| - | set(CURL_DISABLE_TYPECHECK ON) # to improve performance and avoid potential interference. |
| + | set(CURL_DISABLE_TYPECHECK ON) # to improve performance (1.4x), avoid potential interference and bugprone-macro-parentheses. |
| set(CMAKE_C_CLANG_TIDY "${CLANG_TIDY}") | |
| list(APPEND CMAKE_C_CLANG_TIDY "--config-file=${PROJECT_SOURCE_DIR}/.clang-tidy.yml") | |
| if(CURL_WERROR) | |
| @@ -285,6 +285,18 @@ if(CURL_CLANG_TIDY) | |
| endif() | |
| endif() | |
| + | option(CURL_GCC_ANALYZER "Enable GCC --analyzer option" OFF) |
| + | if(CURL_GCC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0) |
| + | set(CURL_DISABLE_TYPECHECK ON) # to improve performance (1.1x). |
| + | # https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html |
| + | set(CURL_ANALYZER_CFLAGS "-fanalyzer") |
| + | # disable checks causing false positives only |
| + | list(APPEND CURL_ANALYZER_CFLAGS "-Wno-analyzer-fd-leak" "-Wno-analyzer-fd-use-without-check" "-Wno-analyzer-file-leak") |
| + | list(APPEND CURL_ANALYZER_CFLAGS "-Wno-analyzer-infinite-loop") |
| + | list(APPEND CURL_ANALYZER_CFLAGS "-Wno-analyzer-malloc-leak") |
| + | list(APPEND CURL_ANALYZER_CFLAGS "-Wno-analyzer-out-of-bounds") |
| + | endif() |
| + | |
| option(CURL_CODE_COVERAGE "Enable code coverage build options" OFF) | |
| if(CURL_CODE_COVERAGE) | |
| if(CMAKE_C_COMPILER_ID STREQUAL "GNU") | |
| @@ -242,6 +242,7 @@ target_link_libraries(my_target PRIVATE CURL::libcurl) | |
| `wolfssl`, `gnutls`, `mbedtls`, `openssl`, `schannel`, `rustls` | |
| - `CURL_DROP_UNUSED`: Drop unused code and data from built binaries. Default: `OFF` | |
| - `CURL_ENABLE_EXPORT_TARGET`: Enable CMake export target. Default: `ON` | |
| + | - `CURL_GCC_ANALYZER`: Enable GCC `--analyzer` option. Default: `OFF` |
| - `CURL_HIDDEN_SYMBOLS`: Hide libcurl internal symbols (=hide all symbols that are not officially external). Default: `ON` | |
| - `CURL_LIBCURL_SOVERSION`: Enable libcurl SOVERSION. Default: `ON` for supported platforms | |
| - `CURL_LIBCURL_VERSIONED_SYMBOLS`: Enable libcurl versioned symbols. Default: `OFF` | |
| @@ -83,6 +83,9 @@ foreach(_target IN LISTS COMPLICATED_MAY_BUILD check_PROGRAMS _all) # keep 'COM | |
| endif() | |
| target_link_libraries(${_target_name} ${LIB_SELECTED} ${CURL_NETWORK_AND_TIME_LIBS} ${_more_libs}) | |
| target_compile_definitions(${_target_name} PRIVATE "CURL_NO_OLDIES" "$<$<BOOL:${WIN32}>:WIN32_LEAN_AND_MEAN>") | |
| + | if(CURL_ANALYZER_CFLAGS) |
| + | set_property(TARGET ${_target_name} APPEND PROPERTY COMPILE_OPTIONS ${CURL_ANALYZER_CFLAGS}) |
| + | endif() |
| set_target_properties(${_target_name} PROPERTIES OUTPUT_NAME "${_target}" PROJECT_LABEL "Example ${_target}" UNITY_BUILD OFF) | |
| endforeach() | |
| @@ -129,6 +129,10 @@ if(SHARE_LIB_OBJECT AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) | |
| if(CURL_CLANG_TIDY) | |
| set_target_properties(${LIB_OBJECT} PROPERTIES UNITY_BUILD OFF) | |
| endif() | |
| + | if(CURL_ANALYZER_CFLAGS) |
| + | set_target_properties(${LIB_OBJECT} PROPERTIES UNITY_BUILD OFF) |
| + | set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_OPTIONS ${CURL_ANALYZER_CFLAGS}) |
| + | endif() |
| if(CURL_CODE_COVERAGE) | |
| set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS ${CURL_COVERAGE_MACROS}) | |
| set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_OPTIONS ${CURL_COVERAGE_CFLAGS}) | |
| @@ -178,6 +182,10 @@ if(BUILD_STATIC_LIBS) | |
| set_target_properties(${LIB_STATIC} PROPERTIES UNITY_BUILD OFF) | |
| endif() | |
| endif() | |
| + | if(CURL_ANALYZER_CFLAGS) |
| + | set_target_properties(${LIB_STATIC} PROPERTIES UNITY_BUILD OFF) |
| + | set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_OPTIONS ${CURL_ANALYZER_CFLAGS}) |
| + | endif() |
| if(CURL_CODE_COVERAGE) | |
| set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS ${CURL_COVERAGE_MACROS}) | |
| set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_OPTIONS ${CURL_COVERAGE_CFLAGS}) | |
| @@ -243,6 +251,10 @@ if(BUILD_SHARED_LIBS) | |
| if(CURL_CLANG_TIDY) | |
| set_target_properties(${LIB_SHARED} PROPERTIES UNITY_BUILD OFF) | |
| endif() | |
| + | if(CURL_ANALYZER_CFLAGS) |
| + | set_target_properties(${LIB_SHARED} PROPERTIES UNITY_BUILD OFF) |
| + | set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_OPTIONS ${CURL_ANALYZER_CFLAGS}) |
| + | endif() |
| if(CURL_CODE_COVERAGE) | |
| set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS ${CURL_COVERAGE_MACROS}) | |
| set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_OPTIONS ${CURL_COVERAGE_CFLAGS}) | |
| @@ -558,7 +558,7 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data, | |
| struct cpool *cpool = cpool_get_instance(data); | |
| bool kept = TRUE; | |
| - | if(!data) |
| + | if(!data || !data->multi) |
| return kept; | |
| if(!data->multi->maxconnects) { | |
| @@ -375,6 +375,10 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf, | |
| (void)cf; | |
| DEBUGASSERT(data); | |
| + | |
| + | if(!data) |
| + | return CURLE_BAD_FUNCTION_ARGUMENT; |
| + | |
| stream = H2_STREAM_CTX(ctx, data); | |
| if(stream) { | |
| *pstream = stream; | |
| @@ -1940,10 +1944,15 @@ static CURLcode cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data, | |
| char *buf, size_t len, size_t *pnread) | |
| { | |
| struct cf_h2_ctx *ctx = cf->ctx; | |
| - | struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data); |
| + | struct h2_stream_ctx *stream; |
| CURLcode result, r2; | |
| struct cf_call_data save; | |
| + | if(!data) |
| + | return CURLE_HTTP2; |
| + | |
| + | stream = H2_STREAM_CTX(ctx, data); |
| + | |
| *pnread = 0; | |
| if(!stream) { | |
| /* Abnormal call sequence: either this transfer has never opened a stream | |
| @@ -693,13 +693,19 @@ out: | |
| static CURLcode oldap_state_mechs_resp(struct Curl_easy *data, | |
| LDAPMessage *msg, int code) | |
| { | |
| - | struct connectdata *conn = data->conn; |
| - | struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN); |
| + | struct connectdata *conn; |
| + | struct ldapconninfo *li; |
| int rc; | |
| BerElement *ber = NULL; | |
| CURLcode result = CURLE_OK; | |
| struct berval bv, *bvals; | |
| + | if(!data) |
| + | return CURLE_FAILED_INIT; |
| + | |
| + | conn = data->conn; |
| + | li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN); |
| + | |
| if(!li) | |
| return CURLE_FAILED_INIT; | |
| switch(ldap_msgtype(msg)) { | |
| @@ -1128,7 +1128,7 @@ CURLcode Curl_creader_set_fread(struct Curl_easy *data, curl_off_t len) | |
| struct cr_in_ctx *ctx; | |
| result = Curl_creader_create(&r, data, &cr_in, CURL_CR_CLIENT); | |
| - | if(result) |
| + | if(result || !r) |
| goto out; | |
| ctx = r->ctx; | |
| ctx->total_len = len; | |
| @@ -1689,6 +1689,9 @@ static CURLcode ws_send_raw_blocking(struct Curl_easy *data, | |
| CURLcode result = CURLE_OK; | |
| size_t nwritten; | |
| + | if(!data) |
| + | return result; |
| + | |
| (void)ws; | |
| while(buflen) { | |
| result = Curl_xfer_send(data, buffer, buflen, FALSE, &nwritten); | |
| @@ -124,6 +124,10 @@ endif() | |
| if(CURL_CLANG_TIDY) | |
| set_target_properties(${EXE_NAME} PROPERTIES UNITY_BUILD OFF) | |
| endif() | |
| + | if(CURL_ANALYZER_CFLAGS) |
| + | set_target_properties(${EXE_NAME} PROPERTIES UNITY_BUILD OFF) |
| + | set_property(TARGET ${EXE_NAME} APPEND PROPERTY COMPILE_OPTIONS ${CURL_ANALYZER_CFLAGS}) |
| + | endif() |
| if(ENABLE_UNICODE AND MINGW) | |
| if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) | |
| @@ -213,6 +213,8 @@ ParameterError varexpand(const char *line, struct dynbuf *out, bool *replaced) | |
| curlx_dyn_init(out, MAX_EXPAND_CONTENT); | |
| do { | |
| envp = strstr(line, "{{"); | |
| + | if(!envp) |
| + | break; |
| if((envp > line) && envp[-1] == '\\') { | |
| /* preceding backslash, we want this verbatim */ | |
| @@ -227,7 +229,7 @@ ParameterError varexpand(const char *line, struct dynbuf *out, bool *replaced) | |
| return PARAM_NO_MEM; | |
| line = &envp[2]; | |
| } | |
| - | else if(envp) { |
| + | else { |
| char name[MAX_VAR_LEN]; | |
| size_t nlen; | |
| size_t i; | |
| @@ -320,8 +322,7 @@ ParameterError varexpand(const char *line, struct dynbuf *out, bool *replaced) | |
| } | |
| line = &clp[2]; | |
| } | |
| - | |
| - | } while(envp); |
| + | } while(1); |
| if(added && *line) { | |
| /* add the "suffix" as well */ | |
| result = curlx_dyn_add(out, line); | |
| @@ -41,6 +41,9 @@ 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") | |
| @@ -158,7 +158,7 @@ static int setup_hx_upload(CURL *curl, const char *url, struct transfer_u *t, | |
| if(use_earlydata) | |
| curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_EARLYDATA); | |
| - | if(!strcmp("MIME", t->method)) { |
| + | if(t->method && !strcmp("MIME", t->method)) { |
| curl_mimepart *part; | |
| t->mime = curl_mime_init(curl); | |
| part = curl_mime_addpart(t->mime); | |
| @@ -208,6 +208,9 @@ static CURLcode test_unit1607(const char *arg) | |
| break; | |
| } | |
| + | if(!addr) |
| + | break; |
| + | |
| addr = addr->ai_next; | |
| } | |
| @@ -190,6 +190,9 @@ static CURLcode test_unit1609(const char *arg) | |
| break; | |
| } | |
| + | if(!addr) |
| + | break; |
| + | |
| addr = addr->ai_next; | |
| } | |