smatch icon indicating copy to clipboard operation
smatch copied to clipboard

smatch misidentifies uninitialized variable after switch with no default:

Open jbrandeb opened this issue 4 years ago • 1 comments

I've got a simple reproducer for the issue that I found when scanning our ice driver in the kernel with smatch.

original repro against smatch HEAD 0951ed5915c0 ("db: fix uninitialized variable false positives") smatch reported: ~/git/smatch/smatch_scripts/kchecker drivers/net/ethernet/intel/ice/ice_ptp_hw.c drivers/net/ethernet/intel/ice/ice_ptp_hw.c:2852 ice_ptp_port_cmd_e810() error: uninitialized symbol 'cmd_val'.

Below is a simple c-code reproducer, compile with: gcc -o srt -Wextra -Wall smatch_switch_repro.c see error with

~/git/smatch/smatch smatch_switch_repro.c
smatch_switch_repro.c:43 badfunc() error: uninitialized symbol 'my_int'.

One bit of data that might be useful: it works fine with badfunc content inline in main() and fails when badfunc is a function with the enum argument. It also succeeds when there is a "default:" label and a simple assignment in that case (see the reproducer below and bit of commented out code)

// SPDX-License-Identifier: BSD-3-Clause
/*
 * Copyright 2021, Intel Corporation
 *
 * A quick demo of a smatch false positive
 */

#include <stdio.h>

enum three_values
{
        value_one,
        value_two,
        value_three
};

void badfunc(const enum three_values cmd)
{
        unsigned int my_int, new_int; //uninitialized

        switch (cmd) {
        case value_one:
                printf("one\n");
                my_int = 1;
                break;
        case value_two:
                printf("two\n");
                my_int = 2;
                break;
        case value_three:
                printf("three\n");
                my_int = 3;
                break;
        /* no default because all enum values handled, which has value
         * to developers because it forces compile error if not all enum values
         * handled and enum is changed */
        //default:
                //my_int = 4;
                //break;
        }

        new_int = 0;
        new_int |= my_int;

        printf("data: %d\n", new_int);
}

int main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
{
        enum three_values my_enum = value_two;

        badfunc(my_enum);

        return 0;
}

jbrandeb avatar Dec 21 '21 19:12 jbrandeb

@error27 - this one worked out pretty well, I hope this simple reproducer helps you figure out a fix.

jbrandeb avatar Dec 21 '21 19:12 jbrandeb