ci: add static analysis and more compiler warnings - #690
Merged
Conversation
This was the only plain strdup() left in the tree; everything else uses g_strdup(), which aborts on allocation failure rather than returning NULL. The other return path of this very function already hands back memory from g_build_filename(), so this makes both paths consistent. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
So far the only check on the C code itself was clang-format. Add two static analyzers, each behind a make target so they can be run locally the same way CI runs them: - "make analyze" runs clang --analyze over every source file; - "make cppcheck" runs cppcheck with warning, performance and portability checks. Both are clean on the current tree and are wired into validate.yml as blocking jobs. Three clang checkers are disabled, and cppcheck's "style" checks are not enabled. The reasons are spelled out in the Makefile: none of the three models __attribute__((cleanup)), which this code base uses throughout, so they only produce false positives here. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
...and fix found issues. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
... and fix found warnings. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
All of these are already clean on the current tree, so they cost nothing today and only guard against new code: -Wmissing-prototypes -Wmissing-declarations -Wformat=2 -Wundef -Winit-self -Wnull-dereference -Wfloat-equal -Wdouble-promotion -Walloca -Wduplicated-cond -Wduplicated-branches -Wtrampolines The last three exist in gcc but not in clang, which rejects an unknown -W option outright, so they are added through a cc-option helper that probes the compiler first. The analyze target runs clang over the same CFLAGS, and so also needs -Wno-unknown-warning-option. -Wcast-align is deliberately not in the list: gcc does not warn about it on x86, but clang does, and it fires on the CMSG_DATA() casts in src/cmsg.c, where the kernel guarantees the alignment. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both parameters were named after, and shadowed, the globals of the same name, and both call sites passed in exactly those globals. Read the globals directly instead, so that a future reference to dev_null_r or dev_null_w inside this function cannot silently mean something else. No functional change. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One shadowed variable was left. The outer ret in main() was used only on the line right after it was assigned, while the inner one, in the waitpid() loop further down, is genuinely local to that block. Drop the outer variable rather than renaming either of them. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each of these had exactly one or two hits, all fixed here: - -Wvla: the inotify event buffer in oom_cb_cgroup_v2() was sized by a const size_t, which is not an integer constant expression in C, so it was a variable-length array. Size it by the expression itself and use sizeof() at the read() call. - -Wpointer-arith: arithmetic on the void * iov_base is a GNU extension; go through char * instead. - -Wjump-misses-init: the errorf() macro jumps to a label past the declaration of ret. The label does not use ret, so this was harmless, but declaring it up front with the other locals is both clearer and consistent with the rest of the function. - -Wswitch-default: remote_sock_shutdown() switches over an int, not an enum, so an explicit default belongs there. - -Wformat-signedness: st_uid is unsigned, and was printed with %d. -Wformat-signedness and -Wjump-misses-init exist in gcc and in clang 19 and later, but not in clang 18, which is what ubuntu-latest still ships, so they go through cc-option as well. -Wswitch-enum is deliberately left out: its only hit is stdpipe_name(), which already has a default case, and -Wall's -Wswitch already covers the case that matters. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The flag gives string literals the type they morally have, const char[], so that assigning one to a plain char * is diagnosed. All eleven hits were places that only ever read the string, so the fix throughout is to add the missing const: - opt_socket_path, whose default value is a literal; - the label member of struct local_sock_s; - the filename and error_var_name parameters of setup_fifo(); - the socket_relative_name parameter of bind_unix_socket(); - the local command in configure_runtime_args(); - driver, path and k8s_log_path in the log driver parsing, which also lets a cast away from const disappear. opt_socket_path stays a valid G_OPTION_ARG_STRING target: glib takes the address as a gpointer, and const char ** converts to void * without discarding anything, since the pointed-at type is itself unqualified. -Wcast-qual is not added. Three of its five hits cannot be fixed: two hash table keys are volatile because a signal handler writes them, and writev(2) takes a non-const iov_base, so the const has to come off. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collaborator
|
LGTM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Until now the only check on the C code itself was clang-format. This adds
two static analyzers and a larger set of compiler warnings, plus the small
fixes needed to make the tree clean under them.
Static analyzers
Two new make targets, so they can be run locally exactly the way CI runs
them, and two new blocking jobs in
validate.yml:make analyzerunsclang --analyzeover every source file;make cppcheckruns cppcheck with the warning, performance andportability checks.
Three clang checkers are disabled and cppcheck's
stylechecks are notenabled; the Makefile says why. The short version is that the clang static
analyzer does not model
__attribute__((cleanup)), which this code baseuses throughout, so every
_cleanup_free_/_cleanup_close_/_cleanup_fclose_variable looks either leaked or assigned but never read.The CFG does carry a
CleanupFunctionelement, but the engine neverevaluates it, and
ownership_takesdoes not help, since the attributewould refer to the address of the variable rather than to the pointer.
gcc -fanalyzeris deliberately not part of this. It does model thecleanup attribute, but it does not know that
execv(2)does not return,which costs six false fd-leak reports around the fork/exec path.
Warning flags
Everything added here is already clean on the tree, so it only guards
against new code. Flags that only some compilers have go through a
cc-optionhelper that probes the compiler first, because clang rejectsan unknown
-Woption outright.-Wformat-signednessand-Wjump-misses-initexist in gcc and in clang 19 and later, but not inclang 18, which is what ubuntu-latest still ships.
Three flags were considered and left out, each for a stated reason:
-Wcast-align(fires on theCMSG_DATA()casts, where the kernelguarantees the alignment),
-Wcast-qual(three of five hits cannot befixed: volatile hash table keys written by a signal handler, and the
non-const
iov_baseofwritev(2)), and-Wswitch-enum(its only hitalready has a default case).
Code changes
All of them are fixes for the above, and none is meant to change
behaviour:
socket_parent_dir()used the only plainstrdup()left in the tree;disconnect_std_streams()took two parameters that shadowed the globalsof the same name, which both call sites passed in anyway;
retinmain()shadowed a genuinely local one further down;oom_cb_cgroup_v2()was a variable-lengtharray, because a
const size_tis not an integer constant expression;void *iov_baseis a GNU extension;remote_sock_shutdown()switches over anint, so it wants a default;st_uidis unsigned and was printed with%d;conston strings that are only ever read.Testing
make,make analyze,make cppcheckand the meson build were all runagainst gcc 13 with clang 18 and gcc 16 with clang 22. The test suite was
not run locally, so CI is its first pass.