Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scan-build errors found during 2019.07 testing #11852

Open
14 of 32 tasks
cladmi opened this issue Jul 16, 2019 · 3 comments · Fixed by #12274
Open
14 of 32 tasks

scan-build errors found during 2019.07 testing #11852

cladmi opened this issue Jul 16, 2019 · 3 comments · Fixed by #12274
Labels
Area: cpu Area: CPU/MCU ports Area: drivers Area: Device drivers Area: network Area: Networking Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework Area: tools Area: Supplementary tools Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)

Comments

@cladmi
Copy link
Contributor

cladmi commented Jul 16, 2019

Description

I am running scan-build checking for the 2019.07 release RIOT-OS/Release-Specs#128

I will try to list the issues I found here.

By running the scan-build command manually, you get the webpage that gives the path taken by the analyzer to show the error. Which is good to have context.

# Same boards as `RIOT` building for `llvm`
BOARDS="iotlab-m3 native nrf52dk mulle nucleo-f401re samr21-xpro slstk3402a"

export BUILD_IN_DOCKER=1
export TOOLCHAIN=llvm


# Cannot currently be done through `RIOT_MAKEFILES_GLOBAL_POST` with `docker`
# So hack it
echo 'CFLAGS += -Wno-deprecated-declarations' >> Makefile.include

for board in ${BOARDS}
do
    ./dist/tools/compile_and_test_for_board/compile_and_test_for_board.py --compile-targets scan-build-analyze --no-test . ${board} || true
done

The parsed result is available here: https://ci-ilab.imp.fu-berlin.de/job/RIOT%20scan-build-analyze/18/

How should issues be handled?

  • Is there a way in RIOT to define that an attribute is __nonnull ? I do not see it used but is defined in sys/cdefs.h.
  • Should we always disable -Wno-deprecated-declarations when running scan-build ? Or a way to have a supported CFLAGS_APPEND.
  • Should value is never read be disabled or correctly handled?

List of found issues:

TODO

  • list all (except packages for the moment)
  • sort real problems

Reported files

  • uint32_t blkopt = _decode_uint(data_start, option_len);

    TOOLCHAIN=llvm make -C examples/nanocoap_server/ scan-build
    
    sys/net/application_layer/nanocoap/nanocoap.c:307:23: warning: 2nd function call argument is an
    uninitialized value
        uint32_t blkopt = _decode_uint(data_start, option_len);
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    sys/net/application_layer/nanocoap/nanocoap.c:554:14: warning: The left expression of the compou
    nd assignment is an uninitialized value. The computed value will also be garbage
            *buf |= (val << shift);
            ~~~~ ^
    sys/net/application_layer/nanocoap/nanocoap.c:557:14: warning: The left expression of the compou
    nd assignment is an uninitialized value. The computed value will also be garbage
            *buf |= (13 << shift);
            ~~~~ ^
    sys/net/application_layer/nanocoap/nanocoap.c:561:14: warning: The left expression of the compou
    nd assignment is an uninitialized value. The computed value will also be garbage
            *buf |= (14 << shift);
            ~~~~ ^
    4 warnings generated.
    sys/net/application_layer/nanocoap/sock.c:147:17: warning: Value stored to 'res' is never read
                    res = sock_udp_send(&sock, buf, res, &remote);
                    ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 warning generated.
    

    Error handling is done on option_len but as there was no length,
    it is used not initialized.

  • MCLK->APBBMASK.reg |= (1 << (id + 7));

    BOARD=samr21-xpro TOOLCHAIN=llvm make -C examples/hello-world/ scan-build
    
    cpu/sam0_common/include/periph_cpu_common.h:395:46: warning: The result of the
        left shift is undefined due to shifting by '255',
        which is greater or equal to the width of type 'unsigned long'
        PM->APBCMASK.reg |= (PM_APBCMASK_SERCOM0 << id);
    

    The default case returns -1 for an uint8_t which also causes invalid C code.
    Could be replaced by a compile time error.

  • uint8_t atmel = spi_transfer_byte(SPIDEV, CSPIN, true, 0);

    TOOLCHAIN=llvm make -C tests/driver_ata8520e/ scan-build
    
    drivers/ata8520e/ata8520e.c: atmel/sigfox/sigfox2 are unused
    

    Could be (void) in an else statement.

  • _compute_b5(dev, ut, &b5);

    TOOLCHAIN=llvm make -C tests/driver_bmp180/ scan-build
    
    drivers/bmp180/bmp180.c:120:5: warning: 2nd function call argument is an uninitialized value _compute_b5(dev, ut, &b5);
    

    As the function does not check the return value, _compute_b5 can use uninitialized value in case of error.
    Also it currently acquires 2 times the i2c for _read_ut.

  • TOOLCHAIN=llvm make -C tests/driver_nrf24l01p_lowlevel scan-build
    
    drivers/nrf24l01p/nrf24l01p.c:644:5: warning: Undefined or garbage value returned to caller 'return pwr;'
    

    Would need an enum I guess instead of hardwriten values and generic type.

  • if (!drdy) {

    TOOLCHAIN=llvm make -C tests/driver_tmp006/ scan-build
    
    drivers/tmp006/tmp006.c:248:9: warning: Branch condition evaluates to a garbage value
        if (!drdy) {
            ^~~~~
    drivers/tmp006/tmp006.c:251:5: warning: 1st function call argument is an uninitialized value
        tmp006_convert(rawvolt, rawtemp,  &tamb, &tobj);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    drivers/tmp006/tmp006.c:251:5: warning: 2nd function call argument is an uninitialized value
        tmp006_convert(rawvolt, rawtemp,  &tamb, &tobj);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    As the function does not check the return value of tmp006_read in case of error,
    it would result in using drdy not initialized.
    There is even some drdy error checking, but what if the function failed…

  • iolist_t iolist[count];

    TOOLCHAIN=llvm make -C tests/lwip_sock_ip/ scan-build
    
    pkg/lwip/contrib/netdev/lwip_netdev.c:203:5: warning: Declared variable-length array (VLA) has zero size
        iolist_t iolist[count];
        ^~~~~~~~~~~~~~~ ~~~~~
    1 warning generated.
    pkg/lwip/contrib/sock/lwip_sock.c:522:14: warning: Dereference of null pointer (loaded from variable 'conn')
        else if (*conn != NULL) {
                 ^~~~~
    

    LL_COUNT(p, q, count); may return a 0 value for count.
    It seems that indeed conn can be NULL before being de-referenced

  • core/include/rmutex.h used by

    #include "net/gnrc.h"

    TOOLCHAIN=llvm make -C tests/netdev_test/ scan-build
    
    In file included from sys/net/gnrc/netif/gnrc_netif.c:23:
    In file included from sys/include/net/gnrc.h:294:
    In file included from sys/include/net/gnrc/netif.h:56:
    core/include/rmutex.h:79:13: warning: Dereference of null pointer (loaded from variable 'rmutex')
        *rmutex = empty_rmutex;
         ~~~~~~ ^
    

    There is an assert(netif != NULL) but still assumes that &netif->mutex can be NULL.
    The rmutex function could be decorated with a __nonnull attribute completely.

  • blockSize = 0;

    TOOLCHAIN=llvm make -C tests/unittests/ scan-build
    
    sys/hashes/sha3.c:427:13: warning: Value stored to 'blockSize' is never read
        blockSize = 0;
    

    The value is never used. This looks indeed not used. Not sure if it was meant
    or if it is an initialization that should be outside the loop.

  • dst[i] = src[i + 3];

    TOOLCHAIN=llvm make -C tests/unittests/ scan-build
    
    sys/hashes/sha256.c:80:20: warning: Assigned value is garbage or undefined
        dst[i] = src[i + 3];
               ^ ~~~~~~~~~~
    

    The compiler has no idea that src is of the right length.
    A more precise type definition could help, would be good to find the correct way of declaring this for the compiler.

  • const ipv6_hdr_t *hdr = pkt->next->data;

    TOOLCHAIN=llvm make -C tests/gnrc_rpl_srh/ scan-build
    
    sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c:232:23: warning: Value stored to 'hdr' during its initialization is never read
        const ipv6_hdr_t *hdr = pkt->next->data;
                              ^~~   ~~~~~~~~~~~~~~~
    

    Initialized even if DEBUG is not set.

  • sys/include/net/addr.h through

    TOOLCHAIN=llvm make -C examples/gnrc_networking scan-build
    
    In file included from sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c:23:
    In file included from sys/include/net/ipv6/hdr.h:27:
    sys/include/net/ipv6/addr.h:395:13: warning: Array access (via field 'u8') results in a null pointer dereference
        return (addr->u8[0] == 0xff);
                    ^~~~~~~~~~~
    

    Looks like it assumes that dst can be NULL. An assert or __nonnull attribute should help.

  • int res = sock_udp_create(&sock, &local, NULL, 0);

    TOOLCHAIN=llvm make -C examples/gnrc_border_router/ scan-build
    
    sys/net/application_layer/uhcp/uhcpc.c:40:9: warning: Value stored to 'res' during its initialization is never read
        int res = sock_udp_create(&sock, &local, NULL, 0);
                ^~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    Value is obviously ignored.

  • assert(udp->size >= sizeof(udp_hdr_t));

    TOOLCHAIN=llvm make -C examples/gnrc_border_router/ scan-build
    
    sys/net/gnrc/network_layer/sixlowpan/iphc/gnrc_sixlowpan_iphc.c:1007:20: warning: Access to field 'size' results
    in a dereference of a null pointer (loaded from variable 'udp')
                assert(udp->size >= sizeof(udp_hdr_t));
                       ^~~~~~~~~
    ssert.h:106:24: note: expanded from macro 'assert'
    #define assert(cond) ((cond) ? (void)0 : core_panic(PANIC_ASSERT_FAIL, assert_crash_message))
                           ^~~~
    1 warning generated.
    

    The function is so big that the reported analysis is on 300 lines.

  • TOOLCHAIN=llvm make -C examples/gnrc_networking_mac/ scan-build
    
    sys/net/gnrc/link_layer/gomach/gomach_internal.c:786:5: warning: Value stored to 'own_id' is never read
        own_id = 0;
        ^        ~
    sys/net/gnrc/link_layer/gomach/gomach_internal.c:605:13: warning: 3rd function call argument is an uninitialized value
            if (memcmp(&netif->mac.rx.slosch_list[i].node_addr.addr,
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    sys/net/gnrc/link_layer/gomach/gomach_internal.c:638:13: warning: 3rd function call argument is an uninitialized value
            if (memcmp(&netif->mac.rx.check_dup_pkt.last_nodes[i].node_addr.addr,
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    Minor one indeed set just after, could be removed.
    The other one is a quite complex analysis, should have focused review. 101 steps

  • const ipv6_hdr_t *hdr = pkt->next->data;

    TOOLCHAIN=llvm make -C examples/gnrc_networking_mac/ scan-build
    
    sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c:232:23: warning: Value stored to 'hdr' during its initialization is never read
        const ipv6_hdr_t *hdr = pkt->next->data;
                          ^~~   ~~~~~~~~~~~~~~~
    

    Value not used when debug disabled.

  • uint32_t next_ra_delay = random_uint32_range(0, NDP_MAX_RA_DELAY);

    TOOLCHAIN=llvm make -C examples/gnrc_networking_mac/ scan-build
    
    sys/net/gnrc/network_layer/ipv6/nib/nib.c:442:14: warning: Value stored to 'next_ra_delay' during its initialization is never read
        uint32_t next_ra_delay = random_uint32_range(0, NDP_MAX_RA_DELAY);
               ^~~~~~~~~~~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    sys/net/gnrc/network_layer/ipv6/nib/nib.c:498:9: warning: Value stored to 'nce' is never read
        nce = _nib_onl_get(&ipv6->src, netif->pid);
        ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    Is it finding that the branches using the values are not reachable ?

  • if ((ptr->next) && (ptr->next->type == GNRC_NETTYPE_NETIF)) {

    TOOLCHAIN=llvm make -C tests/gnrc_sixlowpan_frag scan-build
    
    sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c:74:13: warning: Access to field 'next' results in a dereference of a null pointer (loaded from variable 'ptr')
        if ((ptr->next) && (ptr->next->type == GNRC_NETTYPE_NETIF)) {
            ^~~~~~~~~~~
    

    Long path of pointers that could be said __nonnull.

  • assert(udp->size >= sizeof(udp_hdr_t));

    TOOLCHAIN=llvm make -C examples/gnrc_networking_mac scan-build
    
    sys/net/gnrc/network_layer/sixlowpan/iphc/gnrc_sixlowpan_iphc.c:1007:20: warning: Access to field 'size' results
    in a dereference of a null pointer (loaded from variable 'udp')
                assert(udp->size >= sizeof(udp_hdr_t));
                     ^~~~~~~~~
    

    It is after a long long analysis. 400 lines function.

  • (sock->remote.family != AF_UNSPEC)) {

    TOOLCHAIN=llvm make -C tests/gnrc_sock_ip/ scan-build
    
    sys/net/gnrc/sock/ip/gnrc_sock_ip.c:174:10: warning: Dereference of null pointer
        (sock->remote.family != AF_UNSPEC)) {
         ^~~~~~~~~~~~~~~~~~~
    

    This really looks like a case where it is NULL, if I can understand
    the number of branches.

  • LL_DELETE(base_entry->two_hop_set_head, th_entry);

    TOOLCHAIN=llvm make -C tests/nhdp scan-build
    
    sys/net/routing/nhdp/iib_table.c:717:5: warning: Use of memory after it is freed
        LL_DELETE(base_entry->two_hop_set_head, th_entry);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    sys/include/utlist.h:387:5: note: expanded from macro 'LL_DELETE'
        LL_DELETE2(head,del,next)
        ^~~~~~~~~~~~~~~~~~~~~~~~~
    sys/include/utlist.h:394:12: note: expanded from macro 'LL_DELETE2'
        (head)=(head)->next;
               ^~~~~~~~~~~~
    sys/net/routing/nhdp/iib_table.c:717:5: warning: Use of memory after it is freed
        LL_DELETE(base_entry->two_hop_set_head, th_entry);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    sys/include/utlist.h:387:5: note: expanded from macro 'LL_DELETE'
        LL_DELETE2(head,del,next)
        ^~~~~~~~~~~~~~~~~~~~~~~~~
    sys/include/utlist.h:397:12: note: expanded from macro 'LL_DELETE2'
        while (_tmp->next && (_tmp->next != (del))) {
    

    Use after free, this seems bad

  • char *hostend = hoststart;

    TOOLCHAIN=llvm make -C tests/unittests/ scan-build
    
    sys/net/sock/sock_util.c:154:11: warning: Value stored to 'hostend' during its initialization is never read
        char *hostend = hoststart;
                  ^~~~~~~   ~~~~~~~~~
    

    Initialization could be removed it is never used.

  • assert((ep->family == AF_INET) || (ep->family == AF_INET6));

    TOOLCHAIN=llvm make -C examples/posix_sockets/ scan-build
    
    sys/posix/sockets/posix_sockets.c:186:24: warning: The left operand of '==' is a garbage value
        assert((ep->family == AF_INET) || (ep->family == AF_INET6));
                ~~~~~~~~~~ ^
    

    Not correctly handled having invalid socket type for 'getsockname'

  • flashpage_pos += to_copy;

    TOOLCHAIN=llvm make -C tests/riotboot_flashwrite/ scan-build
    
    /home/harter/work/git/worktree/riot_release/sys/riotboot/flashwrite.c:79:9: warning: Value stored to 'flashpage_pos' is never read
            flashpage_pos += to_copy;
            ^                ~~~~~~~
    1 warning generated.
    

    Unused value

  • https:/github.com/RIOT-OS/RIOT/blob/14fe8f29e7c4aa424fce6f90fb598796b24fe063/sys/vfs/vfs_stdio.c#L61

    BOARD=mulle TOOLCHAIN=llvm make -C tests/minimal/ scan-build
    
    sys/vfs/vfs_stdio.c:61:5: warning: Value stored to 'fd' is never read
        fd = vfs_bind(STDIN_FILENO, O_RDONLY, &_stdio_ops, (void *)STDIN_FILENO);
        ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    sys/vfs/vfs_stdio.c:64:5: warning: Value stored to 'fd' is never read
        fd = vfs_bind(STDOUT_FILENO, O_WRONLY, &_stdio_ops, (void *)STDOUT_FILENO);
        ^    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    2 warnings generated.
    

    Mulle usess vfs by default ?
    fd is used only in assert but look like disabled…
    Maybe need a (void)fd everytime ?

  • *((volatile int *) FORBIDDEN_ADDRESS) = 12345;

    TOOLCHAIN=llvm make -C tests/fault_handler/ scan-build
    
    tests/fault_handler/main.c:43:43: warning: Dereference of null pointer
        *((volatile int *) FORBIDDEN_ADDRESS) = 12345;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
    ```1 warning generated.
    It is on purpose… is it possible to silent this?
    
    
  • https:/github.com/RIOT-OS/RIOT/blob/14fe8f29e7c4aa424fce6f90fb598796b24fe063/tests/gnrc_netif/common.c#L78

    tests/gnrc_netif/common.c:78:9: warning: Null pointer passed as an argument to a 'nonnull' parameter
            memcpy(tmp_buffer, data, data_len);
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 warning generated.
    

    Condition looks like it should be && instead of ||.

  • https:/github.com/RIOT-OS/RIOT/blob/14fe8f29e7c4aa424fce6f90fb598796b24fe063/tests/malloc/main.c#L59

    TOOLCHAIN=llvm make -C tests/malloc/ scan-build
    
    tests/malloc/main.c:59:13: warning: Branch condition evaluates to a garbage value
            if (head->next) {
                ^~~~~~~~~~
    1 warning generated.
    

    It assumes malloc can return null which is not handled.

  • res = sock_udp_send(&sock, buf, res, &remote);

    TOOLCHAIN=llvm make -C tests/nanocoap_cli/ scan-build
    
    tests/nanocoap_cli/nanocli_server.c:67:17: warning: Value stored to 'res' is never read
                    res = sock_udp_send(&sock, buf, res, &remote);
                    ^     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 warning generated.
    

    Value is obviously unused.

  • Some other "unused value" in tests.

  • ...

Versions

2019.07-RC1

@miri64 miri64 added Area: cpu Area: CPU/MCU ports Area: drivers Area: Device drivers Area: network Area: Networking Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework Area: tools Area: Supplementary tools Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) labels Jul 30, 2019
@miri64
Copy link
Member

miri64 commented Sep 19, 2019

For the gnrc_ipv6 related parts I provided #12274.

@miri64
Copy link
Member

miri64 commented Sep 20, 2019

Sorry, wasn't careful enough about my wording in #12274.

@miri64 miri64 reopened this Sep 20, 2019
@cladmi
Copy link
Contributor Author

cladmi commented Sep 20, 2019

Slap github :D

@MrKevinWeiss MrKevinWeiss removed this from the Release 2021.07 milestone Jul 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports Area: drivers Area: Device drivers Area: network Area: Networking Area: pkg Area: External package ports Area: sys Area: System Area: tests Area: tests and testing framework Area: tools Area: Supplementary tools Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants