-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Fix handling of cases where a duplicate item is added to a set and related cleanups #16238
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
Conversation
It's such a common operation to allocate the set and put an item in it, that it deserves a helper. set_ensure_put() has the same return values as set_put(). Comes with tests!
Patch contains a coccinelle script, but it only works in some cases. Many parts were converted by hand. Note: I did not fix errors in return value handing. This will be done separate to keep the patch comprehensible. No functional change is intended in this patch.
We would say "ignoring", but invalidate the peer anyway. Let's only do that if we modified the peer irreperably. Also add comments explaining allocation handling.
…tches
AddressSanitizer:DEADLYSIGNAL
=================================================================
==12==ERROR: AddressSanitizer: ABRT on unknown address 0x00000000000c (pc 0x7f0a518b3428 bp 0x7fffa463bfd0 sp 0x7fffa463be68 T0)
SCARINESS: 10 (signal)
#0 0x7f0a518b3428 in raise (/lib/x86_64-linux-gnu/libc.so.6+0x35428)
#1 0x7f0a518b5029 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x37029)
#2 0x7f0a52ca635a in log_assert_failed_realm /work/build/../../src/systemd/src/basic/log.c:819:9
#3 0x4eea92 in config_parse_wireguard_endpoint /work/build/../../src/systemd/src/network/netdev/wireguard.c:808:9
#4 0x7f0a52b2f74e in next_assignment /work/build/../../src/systemd/src/shared/conf-parser.c:133:32
#5 0x7f0a52b2954e in parse_line /work/build/../../src/systemd/src/shared/conf-parser.c:242:16
#6 0x7f0a52b28911 in config_parse /work/build/../../src/systemd/src/shared/conf-parser.c:377:21
#7 0x7f0a52b29ec6 in config_parse_many_files /work/build/../../src/systemd/src/shared/conf-parser.c:439:21
#8 0x7f0a52b2a5a6 in config_parse_many /work/build/../../src/systemd/src/shared/conf-parser.c:507:16
#9 0x4d8d6c in netdev_load_one /work/build/../../src/systemd/src/network/netdev/netdev.c:732:13
#10 0x4d3e2b in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/network/fuzz-netdev-parser.c:23:16
#11 0x6b3266 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:558:15
#12 0x6af860 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/libfuzzer/FuzzerLoop.cpp:470:3
#13 0x6b6970 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__1::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /src/libfuzzer/FuzzerLoop.cpp:770:7
#14 0x6b7376 in fuzzer::Fuzzer::Loop(std::__1::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /src/libfuzzer/FuzzerLoop.cpp:799:3
#15 0x67573f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:846:6
#16 0x667097 in main /src/libfuzzer/FuzzerMain.cpp:19:10
#17 0x7f0a5189e82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#18 0x4295a8 in _start (out/fuzz-netdev-parser+0x4295a8)
DEDUP_TOKEN: raise--abort--log_assert_failed_realm
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: ABRT (/lib/x86_64-linux-gnu/libc.so.6+0x35428) in raise
==12==ABORTING
This version is more efficient, which doesn't matter, but it allows us to remove a bunch of error handling, which is always nice.
set_put()/set_ensure_put() return 0, not -EEXIST, if the entry is already found in the set. In this case this does not make any difference, but let's not confuse the reader.
d6479b4 to
2d41c31
Compare
|
Updated with a fix for the issue found by @qhill and two failures found by CI (with test case for one of them). |
This combines set_ensure_allocated() with set_consume(). The cool thing is that because we know the hash ops, we can correctly free the item if appropriate. Similarly to set_consume(), the goal is to simplify handling of the case where the item needs to be freed on error and if already present in the set.
…ery() Old code was correct, but let's make things more explicit.
_cleanup_set_free_ is enough for unit_files, because unit_files is allocated in set_put_strdup(), which uses string_hash_ops_free. This fixes a leak if marker was already present in the table.
… the set I'm not sure if it is actually possible to encounter this condition. But let's make the handling correct regardless.
On error, we'd just free the object, and not close the fd. While at it, let's use set_ensure_consume() to make sure we don't leak the object if it was already in the set. I'm not sure if that condition can be achieved.
I'm not sure if I understand the code correctly, but it seems that if storig in the second set failed, we'd return with the first set having no reference on the link object, and the link object could be freed in the future, leaving the set with a dangling reference.
No funtional change.
Also use double space before the tracking args at the end. Without the comma this looks ugly, but it's a bit better with the double space. At least it doesn't look like a variable with a type.
2d41c31 to
e198eba
Compare
|
set_ensure_consume() was busted. I was even failing under valgrind the test I added in the patch. Somehow I managed to miss that ;( |
| for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) { | ||
|
|
||
| STRV_FOREACH(p, sysvrcnd_path) | ||
| for (unsigned i = 0; i < ELEMENTSOF(rcnd_table); i ++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should probably be size_t as ELEMENTOFS() reurns size_t
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a static table with 4 elements, u8 would suffice ;) I don't think it's worth spinning up the CI for this...
| } | ||
|
|
||
| for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) | ||
| for (unsigned i = 0; i < ELEMENTSOF(rcnd_table); i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
|
|
||
| finish: | ||
| for (i = 0; i < ELEMENTSOF(rcnd_table); i++) | ||
| for (unsigned i = 0; i < ELEMENTSOF(rcnd_table); i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
|
bionic-amd64 timed out, but I don't quite see why. I'll assume this is unrelated. |
No description provided.