Add underlying type to Balsa enums.
Otherwise the static_cast<ParseState>(-1) in HTTPBalsaFrame.ParseStateToString
in balsa_frame_test.cc is undefined behavior.
The C++ standard states: "A value of integral or enumeration type can be
explicitly converted to a complete enumeration type. If the enumeration type
has a fixed underlying type, the value is [...] converted [...] to the
enumeration type. If the enumeration type does not have a fixed underlying
type, the value is unchanged if the original value is within the range of the
enumeration values, and otherwise, the behavior is undefined." See
https://github.com/cplusplus/draft/blob/193a67c9f17e3d7102061e8e01250562b6292351/source/expressions.tex#L4005-L4017
(The actual standard is not available for free, this is an official draft.)
In other words, conversion of any value is well-defined if the enum has an
underlying type, but not otherwise.
I can reproduce by compiling the following example:
enum ParseState {
A,
B,
C,
};
int main() {
ParseState state = static_cast<ParseState>(8);
return state + 2;
}
clang enum.cc -fsanitize=undefined -l:libstdc++.a && ./a.out
enum.cc:11:10: runtime error: load of value 8, which is not a valid value for type 'ParseState'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior enum.cc:11:10 in
And if I add ParseState : int, the error goes away.
This was caught by Envoy ASAN CI, and is blocking Balsa integration to Envoy.
See
https://dev.azure.com/cncf/envoy/_build/results?buildId=108238&view=logs&j=1439b9f7-a348-5b50-b5fe-ea612ea91241&t=37b0a9be-1a71-50b3-594a-4c04a031247d.
Once here, add underlying type to all enums in balsa_enums.h.
PiperOrigin-RevId: 448474661
diff --git a/quiche/balsa/balsa_enums.h b/quiche/balsa/balsa_enums.h
index 2c067b6..9302881 100644
--- a/quiche/balsa/balsa_enums.h
+++ b/quiche/balsa/balsa_enums.h
@@ -10,7 +10,7 @@
namespace quiche {
struct QUICHE_EXPORT_PRIVATE BalsaFrameEnums {
- enum ParseState {
+ enum ParseState : int {
ERROR,
READING_HEADER_AND_FIRSTLINE,
READING_CHUNK_LENGTH,
@@ -25,7 +25,7 @@
NUM_STATES,
};
- enum ErrorCode {
+ enum ErrorCode : int {
// A sentinel value for convenience, none of the callbacks should ever see
// this error code.
NO_ERROR = 0,
@@ -113,7 +113,7 @@
};
struct QUICHE_EXPORT_PRIVATE BalsaHeadersEnums {
- enum ContentLengthStatus {
+ enum ContentLengthStatus : int {
INVALID_CONTENT_LENGTH,
CONTENT_LENGTH_OVERFLOW,
NO_CONTENT_LENGTH,