Skip to content

treewide: initialize several stack-allocated, but uninitialized timer structs#17855

Merged
miri64 merged 2 commits intoRIOT-OS:masterfrom
miri64:ztimer/fix/init-unitialized
Mar 28, 2022
Merged

treewide: initialize several stack-allocated, but uninitialized timer structs#17855
miri64 merged 2 commits intoRIOT-OS:masterfrom
miri64:ztimer/fix/init-unitialized

Conversation

@miri64
Copy link
Member

@miri64 miri64 commented Mar 24, 2022

Contribution description

While digging around for my TinyDTLS issue reported in #17849, I did some valgrind probes with gcoap_dtls and noticed some missing initializations of timers. This PR fixes those.

Testing procedure

Compile examples/gcoap_dtls with valgrind support (for native) and start a shell with valgrind support:

sudo dist/tools/tapsetup/tapsetup
make -C examples/gcoap_dtls -j all-valgrind
make -C examples/gcoap_dtls term-valgrind

open another shell

PORT=tap1 make -C examples/gcoap_dtls term-valgrind

and send a coap request using the coap command. With this PR, valgrind will remain mostly silent, while in current master it will complain about several "Conditional jump or move depends on uninitialised value(s)"

e.g.:

==76316==    at 0x806F620: ztimer64_remove (sys/ztimer64/ztimer64.c:64)
==76316==    by 0x805C8D2: xtimer_remove (sys/include/ztimer64/xtimer_compat.h:150)
==76316==    by 0x805C8D2: gnrc_sock_recv (./gnrc_sock.c:143)
==76316==    by 0x805CFAE: sock_udp_recv_buf_aux (sys/net/gnrc/sock/udp/gnrc_sock_udp.c:237)
==76316==    by 0x806EDC0: sock_udp_recv_buf (/home/mlenders/Repositories/RIOT-OS/RIOT/sys/include/net/sock/udp.h:605)
==76316==    by 0x806EDC0: _udp_cb (./sock_dtls.c:872)
==76316==    by 0x806696B: _event_handler (sys/net/sock/async/event/sock_async_event.c:33)
==76316==    by 0x80501F8: event_loop_multi (sys/include/event.h:409)
==76316==    by 0x80501F8: event_loop (sys/include/event.h:431)
==76316==    by 0x80501F8: _event_loop (./gcoap.c:183)
==76316==    by 0x41BE788: makecontext (in /usr/lib32/libc.so.6)
==76316==  Uninitialised value was created by a stack allocation
==76316==    at 0x805C7E4: gnrc_sock_recv (sys/net/gnrc/sock/gnrc_sock.c:97)

Issues/PRs references

None

@miri64 miri64 added the Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) label Mar 24, 2022
@miri64 miri64 requested review from fjmolinas and removed request for PeterKietzmann, bergzand, cgundogan, haukepetersen and kaspar030 March 24, 2022 14:29
@miri64 miri64 changed the title Ztimer/fix/init unitialized treewide: several initialize several stack-allocated, but unitialized timer structs. Mar 24, 2022
@miri64 miri64 changed the title treewide: several initialize several stack-allocated, but unitialized timer structs. treewide: several initialize several stack-allocated, but unitialized timer structs Mar 24, 2022
@benpicco benpicco requested a review from kaspar030 March 24, 2022 14:57
Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK.

@kaspar030
Copy link
Contributor

maybe it should be ztimer_t foo = {0}, not sure, probably slower but less likely to break.

@miri64
Copy link
Member Author

miri64 commented Mar 24, 2022

maybe it should be ztimer_t foo = {0}, not sure, probably slower but less likely to break.

I seem to remember there were some problems with = {0} in general, so that's mostly why I chose some well known members. 🤷‍♀️

@miri64
Copy link
Member Author

miri64 commented Mar 24, 2022

maybe it should be ztimer_t foo = {0}, not sure, probably slower but less likely to break.

It all non-mentioned members will be set to zero anyway, but .next is the only one kept uninitialized (callback and args are usually set later on in the code)

@miri64 miri64 enabled auto-merge March 24, 2022 15:58
}
#if IS_USED(MODULE_ZTIMER_USEC)
ztimer_t timeout_timer;
ztimer_t timeout_timer = { .base = { .next = NULL } };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the initialsation is done with = {.callback = _callback_put} the rest of the struct should be initialised (to zero) as well.

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf (p.:142 pdf.:160 l:28 there is an example how to handel partial initialisation)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the initialsation is done with = {.callback = _callback_put} the rest of the struct should be initialised (to zero) as well.

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf (p.:142 pdf.:160 l:28 there is an example how to handel partial initialisation)

That should be the case for the way I picked it as well. That's why I picked a member where I know it should be 0 in any case.

}
#if IS_USED(MODULE_ZTIMER_USEC)
ztimer_t timeout_timer;
ztimer_t timeout_timer = { .base = { .next = NULL } };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ztimer_t timeout_timer = { .base = { .next = NULL } };
ztimer_t timeout_timer = {.callback = _callback_put};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callback is only needed for when the if is set below. So I would rather not initialize something that is not needed and go for the NULL initializer as picked.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about:

Suggested change
ztimer_t timeout_timer = { .base = { .next = NULL } };
ztimer_t timeout_timer = { .callback = NULL };

or

Suggested change
ztimer_t timeout_timer = { .base = { .next = NULL } };
ztimer_t timeout_timer = { 0 };

not naming parts of the ztimer_t struct that a user of ztimer should not have to deal with.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miri64 miri64 disabled auto-merge March 25, 2022 12:21
@miri64 miri64 added Area: network Area: Networking CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: timers Area: timer subsystems labels Mar 28, 2022
@miri64 miri64 changed the title treewide: several initialize several stack-allocated, but unitialized timer structs treewide: initialize several stack-allocated, but unitialized timer structs Mar 28, 2022
@miri64 miri64 changed the title treewide: initialize several stack-allocated, but unitialized timer structs treewide: initialize several stack-allocated, but uninitialized timer structs Mar 28, 2022
@miri64 miri64 enabled auto-merge March 28, 2022 13:59
@miri64 miri64 force-pushed the ztimer/fix/init-unitialized branch from 7b1786b to a81c5a5 Compare March 28, 2022 14:57
@github-actions github-actions bot added the Area: sys Area: System label Mar 28, 2022
@miri64
Copy link
Member Author

miri64 commented Mar 28, 2022

Bump github actions.

@miri64 miri64 merged commit ef7329f into RIOT-OS:master Mar 28, 2022
@miri64 miri64 deleted the ztimer/fix/init-unitialized branch March 28, 2022 18:15
@kaspar030
Copy link
Contributor

I seem to remember there were some problems with = {0} in general, so that's mostly why I chose some well known members. woman_shrugging

problems?

@kfessel
Copy link
Contributor

kfessel commented Mar 29, 2022

I seem to remember there were some problems with = {0} in general, so that's mostly why I chose some well known members. woman_shrugging

problems?

i think the problem is generated with c++ where {0} can only be used types that can be initialized by a scalar scalars and {} is the default initializer for struct and co.
but i could not generate any error for ztimer_t initializing it using {0}.

@miri64
Copy link
Member Author

miri64 commented Mar 29, 2022

i think the problem is generated with c++ where {0} can only be used types that can be initialized by a scalar scalars and {} is the default initializer for struct and co.
but i could not generate any error for ztimer_t initializing it using {0}.

IIRC the problem was also related to compiling on OSX using XCode, but tbh I don't know anymore. If there is no problem, I can adjust my style :-)

@chrysn
Copy link
Member

chrysn commented Mar 31, 2022

Just saw this now, and not objecting, but apart from valgrinding RIOT, might these cases be spottable more easily if we (by setting a flag, or merely by stating it needs to be done this way, even if the checks are only in with DEVELHELP) made ztimer complain loudly (as in assert) if a timer is added that is neither zerod where it matters nor on the clock it is being added to?

@OlegHahm OlegHahm added this to the Release 2022.04 milestone Apr 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: network Area: Networking Area: sys Area: System Area: timers Area: timer subsystems CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants