Bug 213383

Summary: -Wsign-compare in isValidOptionSet
Product: WebKit Reporter: Michael Catanzaro <mcatanzaro>
Component: Web Template FrameworkAssignee: Michael Catanzaro <mcatanzaro>
Status: RESOLVED FIXED    
Severity: Minor CC: benjamin, cdumez, cmarcelo, darin, ddkilzer, ews-watchlist, mcatanzaro, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: PC   
OS: Linux   
Attachments:
Description Flags
Patch none

Michael Catanzaro
Reported 2020-06-19 09:23:00 PDT
Since r263208 "[IPC hardening] OptionSet<> values should be validated": [4332/4574] Building CXX object Source...ources/UnifiedSource-50d0d8dd-14.cpp.o In file included from /home/mcatanzaro/Projects/WebKit/Source/WebKit/Shared/glib/InputMethodState.h:31, from /home/mcatanzaro/Projects/WebKit/Source/WebKit/Shared/glib/InputMethodState.cpp:27, from DerivedSources/WebKit/unified-sources/UnifiedSource-50d0d8dd-14.cpp:1: DerivedSources/ForwardingHeaders/wtf/OptionSet.h: In instantiation of ‘constexpr bool WTF::isValidOptionSet(WTF::OptionSet<E>) [with E = WebKit::InputMethodState::Hint]’: /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/ArgumentCoders.h:69:35: required from ‘static bool IPC::ArgumentCoder<WTF::OptionSet<E> >::decode(IPC::Decoder&, WTF::OptionSet<E>&) [with T = WebKit::InputMethodState::Hint]’ /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/ArgumentCoder.h:72:41: required by substitution of ‘template<class T> static uint8_t IPC::UsesLegacyDecoder<WTF::OptionSet<WebKit::InputMethodState::Hint> >::checkArgumentCoder<T>(IPC::UsesLegacyDecoder<WTF::OptionSet<WebKit::InputMethodState::Hint> >::Helper<bool (*)(IPC::Decoder&, WTF::OptionSet<WebKit::InputMethodState::Hint>&), (& IPC::ArgumentCoder<T>::decode)>*) [with T = WTF::OptionSet<WebKit::InputMethodState::Hint>]’ /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/ArgumentCoder.h:76:85: required from ‘constexpr const bool IPC::UsesLegacyDecoder<WTF::OptionSet<WebKit::InputMethodState::Hint> >::value’ /home/mcatanzaro/Projects/WebKit/Source/WebKit/Platform/IPC/Decoder.h:140:126: required by substitution of ‘template<class T, std::enable_if_t<(((! std::is_enum<_Tp>::value) && (! std::is_arithmetic<_Tp>::value)) && (! IPC::UsesLegacyDecoder<U>::value))>* <anonymous> > bool IPC::Decoder::decode(T&) [with T = WTF::OptionSet<WebKit::InputMethodState::Hint>; std::enable_if_t<(((! std::is_enum<_Tp>::value) && (! std::is_arithmetic<_Tp>::value)) && (! IPC::UsesLegacyDecoder<U>::value))>* <anonymous> = <missing>]’ /home/mcatanzaro/Projects/WebKit/Source/WebKit/Shared/glib/InputMethodState.cpp:117:36: required from here DerivedSources/ForwardingHeaders/wtf/OptionSet.h:257:52: warning: comparison of integer expressions of different signedness: ‘WTF::OptionSet<WebKit::InputMethodState::Hint>::StorageType’ {aka ‘unsigned int’} and ‘int’ [-Wsign-compare] 257 | return (optionSet.toRaw() | allValidBitsValue) == allValidBitsValue; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
Attachments
Patch (1.53 KB, patch)
2020-06-19 12:00 PDT, Michael Catanzaro
no flags
Michael Catanzaro
Comment 1 2020-06-19 09:35:11 PDT
Since this is a bitwise comparison, and we don't normally want to use signed types for bitwise comparisons, we probably want to cast allValidBitsValue on the right side of the expression to unsigned. I think that can be done using std::make_unsigned. Testing this....
Michael Catanzaro
Comment 2 2020-06-19 10:46:26 PDT
So that does work, but I'm going to try to mandate use of unsigned type instead. Using signed types with OptionSet is probably a mistake.
Michael Catanzaro
Comment 3 2020-06-19 11:21:11 PDT
(In reply to Michael Catanzaro from comment #2) > So that does work, but I'm going to try to mandate use of unsigned type > instead. Using signed types with OptionSet is probably a mistake. So that was a bad idea, because OptionSet goes out of its way to allow this: using StorageType = std::make_unsigned_t<std::underlying_type_t<E>>; I think isValidOptionSet should do the same. Let me try that.
Michael Catanzaro
Comment 4 2020-06-19 11:57:40 PDT
OK, I present two... options. ;) Option #1: OptionSetValueChecker should match the OptionSet's StorageType, which is std::make_unsigned_t<std::underlying_type_t<E>>, instead of directly using std::underlying_type_t<E>: diff --git a/Source/WTF/wtf/OptionSet.h b/Source/WTF/wtf/OptionSet.h index de111b16b355..8450b1a240d9 100644 --- a/Source/WTF/wtf/OptionSet.h +++ b/Source/WTF/wtf/OptionSet.h @@ -253,8 +253,8 @@ private: template<typename E> WARN_UNUSED_RETURN constexpr bool isValidOptionSet(OptionSet<E> optionSet) { - auto allValidBitsValue = OptionSetValueChecker<std::underlying_type_t<E>, typename EnumTraits<E>::values>::allValidBits(); - return (optionSet.toRaw() | allValidBitsValue) == allValidBitsValue; + auto allValidBitsValue = OptionSetValueChecker<std::make_unsigned_t<std::underlying_type_t<E>>, typename EnumTraits<E>::values>::allValidBits(); + return (optionSet.toRaw() | allValidBitsValue) == std::underlying_type_t<E>(allValidBitsValue); } That fixes the warning without making any changes in other files. I'll attach this patch for review. Option #2: we could require the OptionSet to use an unsigned underlying value to call isValidOptionSet using std::enable_if. That would enforce unsigned underlying value only for OptionSets that are validated by isValidOptionSet. We only have to change the underlying type of WebKit::InputMethodState::Hint in Source/WebKit/Shared/glib/InputMethodState.h. I decided against making this my preferred option because valid OptionSets do not actually have to use unsigned underlying storage, so it would be a bit weird to require that to call isValidOptionSet, but this would be useful if we want to enforce this for types sent over IPC. (Do we want to enforce it for types sent over IPC?) Option #3: would be to prohibit OptionSet from ever using signed underlying value, but that's going to require changing a lot of enums. Doesn't seem worth it, so I don't propose this.
Michael Catanzaro
Comment 5 2020-06-19 12:00:07 PDT
(In reply to Michael Catanzaro from comment #4) > + return (optionSet.toRaw() | allValidBitsValue) == > std::underlying_type_t<E>(allValidBitsValue); That's a Ctrl+Z mistake, I'll attach a patch that actually works.
Michael Catanzaro
Comment 6 2020-06-19 12:00:23 PDT
Michael Catanzaro
Comment 7 2020-06-19 12:06:48 PDT
(In reply to Michael Catanzaro from comment #4) > this would be useful if we want to enforce this > for types sent over IPC. (Do we want to enforce it for types sent over IPC?) Maybe we do? r263208 ensured this for all types used in cross-platform code. If it's important, r- my patch and I'll upload a version that enforces this. The downside is that it would no longer be possible to call isValidOptionSet on valid OptionSets that use signed underlying storage, which would be weird.
EWS
Comment 8 2020-06-19 12:52:27 PDT
Committed r263280: <https://trac.webkit.org/changeset/263280> All reviewed patches have been landed. Closing bug and clearing flags on attachment 402301 [details].
Radar WebKit Bug Importer
Comment 9 2020-06-19 12:53:19 PDT
David Kilzer (:ddkilzer)
Comment 10 2020-06-22 14:44:07 PDT
Thanks Michael!
Note You need to log in before you can comment on or make changes to this bug.