Messages in this thread | | | From | Lukas Bulwahn <> | Date | Mon, 18 Oct 2021 18:14:53 +0200 | Subject | Some potentially uninitialized values in pid_list_refill_irq() |
| |
Dear Steven,
Commit 8d6e90983ade ("tracing: Create a sparse bitmask for pid filtering") in linux-next adds the new function pid_list_refill_irq(). For this function, 'make clang-analyzer' reports potentially uninitialized values for lower and upper under certain branch conditions, see the full report below.
As far as I understand the analyzer's report and the code at hand:
if lower_count is zero (and upper_count is not), then lower_next is not assigned (because the while lower_count loop is not entered) and lower is pointing to an address with an uninitialized value and hence, the if (lower) conditional reads this uninitialized value.
Analogously for upper_count:
if upper_count is zero (and lower_count is not), then upper_count is not assigned (because the while upper_count loop is not entered) and upper is pointing to an address with an uninitialized value and hence, the if (upper) conditional reads this uninitialized value.
I think this can be resolved by initializing upper and lower to point to an address carrying a zero; but I really fight understanding the whole pointer magic, you did :)
Let me know if clang-analyzer found something buggy here or if the tool and I misunderstood the code; we are certainly interested.
Lukas
---
./kernel/trace/pid_list.c:377:6: warning: Branch condition evaluates to a garbage value [clang-analyzer-core.uninitialized.Branch] if (upper) { ^~~~~ ./kernel/trace/pid_list.c:334:36: note: Left side of '&&' is false struct trace_pid_list *pid_list = container_of(iwork, struct trace_pid_list, ^ ./include/linux/container_of.h:19:61: note: expanded from macro 'container_of' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^ ./kernel/trace/pid_list.c:334:36: note: Taking false branch struct trace_pid_list *pid_list = container_of(iwork, struct trace_pid_list, ^ ./include/linux/container_of.h:19:2: note: expanded from macro 'container_of' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^ ./include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^ ./include/linux/compiler_types.h:329:2: note: expanded from macro 'compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^ ./include/linux/compiler_types.h:317:2: note: expanded from macro '_compiletime_assert' __compiletime_assert(condition, msg, prefix, suffix) ^ ./include/linux/compiler_types.h:309:3: note: expanded from macro '__compiletime_assert' if (!(condition)) \ ^ ./kernel/trace/pid_list.c:334:36: note: Loop condition is false. Exiting loop struct trace_pid_list *pid_list = container_of(iwork, struct trace_pid_list, ^ ./include/linux/container_of.h:19:2: note: expanded from macro 'container_of' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^ ./include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^ ./include/linux/compiler_types.h:329:2: note: expanded from macro 'compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^ ./include/linux/compiler_types.h:317:2: note: expanded from macro '_compiletime_assert' __compiletime_assert(condition, msg, prefix, suffix) ^ ./include/linux/compiler_types.h:307:2: note: expanded from macro '__compiletime_assert' do { \ ^ ./kernel/trace/pid_list.c:336:2: note: 'upper' declared without an initial value union upper_chunk *upper; ^~~~~~~~~~~~~~~~~~~~~~~~ ./kernel/trace/pid_list.c:351:6: note: Assuming 'upper_count' is > 0 if (upper_count <= 0 && lower_count <= 0) ^~~~~~~~~~~~~~~~ ./kernel/trace/pid_list.c:351:23: note: Left side of '&&' is false if (upper_count <= 0 && lower_count <= 0) ^ ./kernel/trace/pid_list.c:354:2: note: Loop condition is true. Entering loop body while (upper_count-- > 0) { ^ ./kernel/trace/pid_list.c:358:7: note: Assuming 'chunk' is null if (!chunk) ^~~~~~ ./kernel/trace/pid_list.c:358:3: note: Taking true branch if (!chunk) ^ ./kernel/trace/pid_list.c:359:4: note: Execution continues on line 365 break; ^ ./kernel/trace/pid_list.c:365:9: note: Assuming the condition is false while (lower_count-- > 0) { ^~~~~~~~~~~~~~~~~ ./kernel/trace/pid_list.c:365:2: note: Loop condition is false. Execution continues on line 376 while (lower_count-- > 0) { ^ ./kernel/trace/pid_list.c:377:6: note: Branch condition evaluates to a garbage value if (upper) { ^~~~~
./kernel/trace/pid_list.c:382:6: warning: Branch condition evaluates to a garbage value [clang-analyzer-core.uninitialized.Branch] if (lower) { ^~~~~ ./kernel/trace/pid_list.c:334:36: note: Left side of '&&' is false struct trace_pid_list *pid_list = container_of(iwork, struct trace_pid_list, ^ ./include/linux/container_of.h:19:61: note: expanded from macro 'container_of' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^ ./kernel/trace/pid_list.c:334:36: note: Taking false branch struct trace_pid_list *pid_list = container_of(iwork, struct trace_pid_list, ^ ./include/linux/container_of.h:19:2: note: expanded from macro 'container_of' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^ ./include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^ ./include/linux/compiler_types.h:329:2: note: expanded from macro 'compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^ ./include/linux/compiler_types.h:317:2: note: expanded from macro '_compiletime_assert' __compiletime_assert(condition, msg, prefix, suffix) ^ ./include/linux/compiler_types.h:309:3: note: expanded from macro '__compiletime_assert' if (!(condition)) \ ^ ./kernel/trace/pid_list.c:334:36: note: Loop condition is false. Exiting loop struct trace_pid_list *pid_list = container_of(iwork, struct trace_pid_list, ^ ./include/linux/container_of.h:19:2: note: expanded from macro 'container_of' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^ ./include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^ ./include/linux/compiler_types.h:329:2: note: expanded from macro 'compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^ ./include/linux/compiler_types.h:317:2: note: expanded from macro '_compiletime_assert' __compiletime_assert(condition, msg, prefix, suffix) ^ ./include/linux/compiler_types.h:307:2: note: expanded from macro '__compiletime_assert' do { \ ^ ./kernel/trace/pid_list.c:337:2: note: 'lower' declared without an initial value union lower_chunk *lower; ^~~~~~~~~~~~~~~~~~~~~~~~ ./kernel/trace/pid_list.c:351:6: note: Assuming 'upper_count' is > 0 if (upper_count <= 0 && lower_count <= 0) ^~~~~~~~~~~~~~~~ ./kernel/trace/pid_list.c:351:23: note: Left side of '&&' is false if (upper_count <= 0 && lower_count <= 0) ^ ./kernel/trace/pid_list.c:354:2: note: Loop condition is true. Entering loop body while (upper_count-- > 0) { ^ ./kernel/trace/pid_list.c:358:7: note: Assuming 'chunk' is non-null if (!chunk) ^~~~~~ ./kernel/trace/pid_list.c:358:3: note: Taking false branch if (!chunk) ^ ./kernel/trace/pid_list.c:354:9: note: Assuming the condition is false while (upper_count-- > 0) { ^~~~~~~~~~~~~~~~~ ./kernel/trace/pid_list.c:354:2: note: Loop condition is false. Execution continues on line 365 while (upper_count-- > 0) { ^ ./kernel/trace/pid_list.c:365:9: note: Assuming the condition is false while (lower_count-- > 0) { ^~~~~~~~~~~~~~~~~ ./kernel/trace/pid_list.c:365:2: note: Loop condition is false. Execution continues on line 376 while (lower_count-- > 0) { ^ ./kernel/trace/pid_list.c:377:6: note: 'upper' is non-null if (upper) { ^~~~~ ./kernel/trace/pid_list.c:377:2: note: Taking true branch if (upper) { ^ ./kernel/trace/pid_list.c:382:6: note: Branch condition evaluates to a garbage value if (lower) { ^~~~~
| |