Skip to content

Commit a3d4d75

Browse files
committed
tests: report a compiler diagnostic from a passing cross build
compile_obj and link_bin sent the compiler's stderr to a log and read it back only when the command failed, so a warning from a build that succeeded was written to a file and dropped. The cross build is the only one that compiles a test's arch-gated bodies on their own arch, which made it the one place a diagnostic could not be seen -- including from the -Werror= shift and overflow classes, fatal only when they fire as errors. The log is now shown whenever it is non-empty, without touching the exit status: the compiler's verdict stays the compiler's. run_target's output is collected per target and printed whole, so one header carries the attribution and the diagnostic keeps its own layout. With the output visible the flags can matter, so the set the native build carries applies here too, less three. -Wno-type-limits: the property generators clamp against per-arch bounds, and a bound that is 0 on s390 makes its comparison tautological there while load-bearing on the other sixteen. -Wno-unused-function and -Wno-unused-variable: a test binary links whole shipped translation units and calls part of each, so most of what it pulls in is legitimately unreached, and silencing that would mean annotating shipped code to suit a test link. Both are re-enabled for the two engine translation units, which carry only test code, where they mean what they mean natively -- a test body no arch reaches. The thirty-five existing bodies in that position are marked unused, the idiom the file already uses for helpers reachable from arch-gated tests only. hardening.c defines all[] in full: only the first nuniq entries carry a name, but the array is passed to kasld_project_posture as a pointer with the count as the only bound, and a compiler that cannot prove the read is count-bounded reports it uninitialised at the empty count.
1 parent 765bab7 commit a3d4d75

4 files changed

Lines changed: 111 additions & 43 deletions

File tree

src/render/hardening.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,12 @@ void build_hardening_report(struct hardening_report *r) {
416416
/* Each suggestion's silenced set is accumulated into the hardened union `all`
417417
* (deduped below); the lockdown/dmesg sets are kept for the leave-one-out
418418
* pass. All sets are bounded by the component count. */
419-
const char *all[MAX_COMPONENTS];
419+
/* Only the first nall entries carry a name, and only the first nuniq of those
420+
* survive the dedup below -- but the whole array is handed to
421+
* kasld_project_posture as a pointer, where the count is the only thing
422+
* bounding the read. Defined in full so the call is well-formed at any count,
423+
* including the empty one. */
424+
const char *all[MAX_COMPONENTS] = {0};
420425
int nall = 0;
421426
const char *ld_sil[MAX_COMPONENTS];
422427
int n_ld = 0;

tests/test-cross

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,24 @@ resolve_qemu() {
5151
# constant overflow gets caught. Kept targeted (not full -Werror) so the test
5252
# TUs' pre-existing unused-static warnings don't turn fatal. Both are front-end
5353
# diagnostics and fire at any optimisation level.
54-
CFLAGS=${CFLAGS:--std=c99 -O2 -static -I$ROOT/src -Werror=shift-count-overflow -Werror=overflow}
54+
# The same warning set the native build carries, so a diagnostic is not a
55+
# function of which build happened to compile the file. This is the only build
56+
# that compiles a test's arch-gated bodies on their own arch, so a warning
57+
# reachable nowhere else is reachable here.
58+
#
59+
# Three exclusions, each because the diagnostic describes this harness rather
60+
# than the code. -Wno-type-limits: the property generators clamp against per-arch
61+
# bounds, and a bound that is 0 on one arch makes its comparison tautological
62+
# there while remaining load-bearing on the other sixteen. -Wno-unused-function
63+
# and -Wno-unused-variable: a test binary links whole shipped translation units
64+
# and calls part of each, so most of what it pulls in is legitimately unreached
65+
# -- silencing that in the source would mean annotating shipped code to suit a
66+
# test link. -Wredundant-decls is left out for the same reason.
67+
KASLD_TEST_WARN="-Wall -Wextra -Wno-type-limits -Wno-unused-function\
68+
-Wno-unused-variable -Wshadow -Wcast-align -Wcast-qual -Wpointer-arith -Wundef\
69+
-Wvla -Wnull-dereference -Wlogical-op -Wduplicated-cond -Wduplicated-branches\
70+
-Wwrite-strings -Wbad-function-cast"
71+
CFLAGS=${CFLAGS:--std=c99 -O2 -static -I$ROOT/src -Werror=shift-count-overflow -Werror=overflow $KASLD_TEST_WARN}
5572
# Every binary this script builds is a test, so the hermeticity probe applies to
5673
# all of them: a test that reads a kernel fact from the machine running it is
5774
# asserting against that machine, on any architecture. Appended rather than put
@@ -94,6 +111,22 @@ show_cc_log() {
94111
fi
95112
}
96113

114+
# A compile that SUCCEEDS still has something to say. The log was written either
115+
# way and read only on failure, so a warning on a passing build was captured to a
116+
# file and dropped -- including one from the -Werror= classes above, which are
117+
# fatal only when they fire as errors. A cross build is where a word-size
118+
# diagnostic appears at all, so silence there is the one place it costs most.
119+
#
120+
# Reported without failing the target: the exit status is the compiler's verdict
121+
# and is not overridden here. run_target's output is collected per target and
122+
# printed whole, so one header carries the attribution and the diagnostic keeps
123+
# the compiler's own layout -- the caret lines are the useful half.
124+
show_cc_diagnostics() {
125+
[ -s "$1" ] || return 0
126+
printf 'WARN %-30s (%s)\n' "$triple" "$2"
127+
sed 's/^/ /' "$1"
128+
}
129+
97130
CORE="$ROOT/src/estimate.c $ROOT/src/quantities.c $ROOT/src/evidence.c $ROOT/src/engine.c"
98131
RULES=$(echo "$ROOT"/src/rules/*.c)
99132

@@ -109,6 +142,7 @@ compile_obj() {
109142
show_cc_log "$d/cc.log"
110143
return 1
111144
fi
145+
show_cc_diagnostics "$d/cc.log" "compile ${co_src##*/}"
112146
}
113147

114148
# link_bin <out> <object...> [-l...] — link step; libraries follow the objects.
@@ -120,6 +154,7 @@ link_bin() {
120154
show_cc_log "$d/cc.log"
121155
return 1
122156
fi
157+
show_cc_diagnostics "$d/cc.log" "link ${lb_out##*/}"
123158
}
124159

125160
# run_target writes its human-readable line(s) to stdout (the caller redirects
@@ -150,8 +185,14 @@ run_target() {
150185
# quantity tops / PHYS_OFFSET, so they are portable across 64-bit arches.
151186
# (This harness has caught real arch bugs this way: a 64-bit shift overflow
152187
# and PHYS_OFFSET-relative assertion errors.)
153-
compile_obj "$ROOT/tests/test_engine.c" "$obj/test_engine.o" || { echo fail >"$st"; return; }
154-
compile_obj "$ROOT/tests/test_engine_integration.c" "$obj/test_integration.o" || { echo fail >"$st"; return; }
188+
# The two engine TUs carry only test code, so the unused-* checks mean here
189+
# what they mean natively: a test body no arch reaches. Everything else this
190+
# script builds links whole shipped translation units and uses part of each,
191+
# where the same check would only describe the link.
192+
compile_obj "$ROOT/tests/test_engine.c" "$obj/test_engine.o" \
193+
-Wunused-function -Wunused-variable || { echo fail >"$st"; return; }
194+
compile_obj "$ROOT/tests/test_engine_integration.c" "$obj/test_integration.o" \
195+
-Wunused-function -Wunused-variable || { echo fail >"$st"; return; }
155196
# The parser / result-model / merge / engine-sync unit suite (its renderer
156197
# half is now test_render, below). It includes the orchestrator + render
157198
# translation units directly (hence -DKASLD_TESTING and -lpthread) and derives

0 commit comments

Comments
 (0)