-
Notifications
You must be signed in to change notification settings - Fork 1.7k
fix: integer type limits, 2nd try #3421
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
fix: integer type limits, 2nd try #3421
Conversation
@jonathansmith9485, @SonNgo2211, @EsadCetiner - here is the new one, please take a review this. |
@airween I've been testing for a day or so and so far I haven't had any issues |
Great news, thank you! |
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.
Much better!
I explained in my initial comment:
|
Co-authored-by: Max Leske <[email protected]>
Co-authored-by: Max Leske <[email protected]>
Co-authored-by: Max Leske <[email protected]>
|
what
This PR fixes the handling of integer type limits, eg.
SecRequestBodyNoFilesLimit
.Changes:
headers/modsecurity/rules_set_properties.h
I implemented a new template with nameConfigValue
parse()
method which reads safely the integer value from a string, which parsed by engine's SecLang parser (Bison)min
andmax
value to0
ConfigInt
) implementsint32_t
(signed int
on AMD64), then the min and max limits will be -2147483648 and +2147483647Request body excluding files is bigger than the maximum expected. Limit: -2147483648.000000
; the reason is (I write that below too) that the current implementation usesatoi()
function, which converts astring
tosigned int
, but if the value is bigger than the max value above, then it overflows and casts toint
's minimumConfigInt
(int32_t
),ConfigUnsignedInt
(uint32_t
) andConfigUnsignedLong
(uint64_t
)std::numeric_limits<T>::min()
andstd::numeric_limits<T>::max()
m_argumentsLimit
,m_requestBodyJsonDepthLimit
,m_requestBodyLimit
,m_requestBodyNoFilesLimit
,m_responseBodyLimit
,m_pcreMatchLimit
,m_uploadFileLimit
andm_uploadFileMode
; the current types are here; now there is no moreConfigDouble
type variablesrc/parser/seclang-parser.yy
I changed the type in grammar parser; there you can see the error handling (detailed error messages are in template'sparse()
method)src/parser/seclang-parser.cc
(it's a generated file by Bison, don't need to check it)Other changes:
ConfigDouble
,ConfigString
andConfigSet
implementations (also inheaders/modsecurity/rules_set_properties.h
)headers/modsecurity/rules_set_properties.h
I had to add undefining macro directives if the target isWIN32
, because the CI workflow was unsuccessful on Windows, because - probably -min
andmax
are Windows C++ macrosHow does it work
The most important part is the new
parse()
method. This decides what integer type is used in the derived class (signed/unsigned), and uses the necessary function (stoll()
/stoull()
). Then it checks that the conversion was success with the biggest sized integer. If not, then theerrno
will be1
and the value will be the max/min value of used type (int64_t
/uin64_t
). There is another check: does the parsed value fit into the chosen type (eg.int32_t
). If any condition matches, then the method returns with false at startup time.why
The problem with current solution is that the type of these variables are
ConfigDouble
, see the variable declarations and their type implementation.A quick review of current implementation:
atoi()
, which gives an integer with different bitsizeTherefore if a user gave an extra high value, then the
atoi()
converted it into a negative value.Previously I sent another PR (#3419), but I realized that solution wasn't complete. In this PR I reworked the whole storage implementation. Then I sent a new one (#3420), but there I continued to use
int
andunsigned long
types, but I realized those are not the same on different platforms (amd64 vs i386). In this PR I changed the types with fixed width types.references
Fixes #3352 and #3356.