Skip to content

Whitespace trimming and libc++ compatibility workaround #280

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

Merged
merged 2 commits into from
Dec 6, 2019

Conversation

matvore
Copy link
Contributor

@matvore matvore commented Dec 3, 2019

I found a crashing bug when sending malformed input to the header-parsing code. It is particular to libc++ (i.e. it doesn't repro with other std C++ library implementations)

The exact error I saw was:

libc++abi.dylib: terminating with uncaught exception of type std::__1::regex_error: The complexity of an attempted match against a regular expression exceeded a pre-set level.
Abort trap: 6

@yhirose
Copy link
Owner

yhirose commented Dec 3, 2019

@matvore, thanks for the contribution. I just took a look at the code a little bit. But I found that all the examples in example/ directory cannot be built anymore. This is due to the gtest FRIEND_TEST macro in httplib.h. If I added the following code in httplib.h, then I am now able to build though...

#ifndef FRIEND_TEST
#define FRIEND_TEST(a, b)
#endif

Personally, I don't want to have this kind of code in httplib.h, because that is not directly related to the httplib.h functionalities. I understand that you wanted to test the private methods, but I just wonder if we could do so without touching httplib.h itself. I am thinking to make a test HTTP client class which feeds the bad test data described in your test cases. Anyway, thank you for finding the bug and showing the excellent solution!

HTTP Whitespace and regex whitespace are not the same, so we can't use
\s in regexes when parsing HTTP headers. Instead, explicitly specify
what is considered whitespace in the regex.
libc++ (the implementation of the C++ standard library usually used by
Clang) throws an exception for the regex used by parse_headers before
this patch for certain strings. Work around this by simplifying the
regex and parsing the header lines "by hand" partially. I have repro'd
this problem with Xcode 11.1 which I believe uses libc++ version 8.

This may be a bug in libc++ as I can't see why the regex would result in
asymptotic run-time complexity for any strings. However, it may take a
while for libc++ to be fixed and for everyone to migrate to it, so it
makes sense to work around it in this codebase for now.
@matvore matvore force-pushed the whitespace-and-libcxx-compat branch from 5d6f2cf to bc9251e Compare December 6, 2019 01:19
@matvore
Copy link
Contributor Author

matvore commented Dec 6, 2019

I've pushed a new version. This is more black-box, as you suggested. I do agree this is a better approach. However, I did expose some socket-creation logic - once internal to the Client class - so that it could be used in tests to trigger requests.

Note that I didn't create a test-Client class, but I did try to keep the redundant boilerplate to a reasonable amount.

@yhirose yhirose merged commit bc9251e into yhirose:master Dec 6, 2019
@yhirose
Copy link
Owner

yhirose commented Dec 6, 2019

@matvore, great! After I merged it, I made some changes to make it a bit more readable. Thanks for your contribution!

@matvore
Copy link
Contributor Author

matvore commented Dec 6, 2019

Thanks for the review :)

@matvore matvore deleted the whitespace-and-libcxx-compat branch December 6, 2019 18:33
matvore added a commit to matvore/cpp-httplib that referenced this pull request Feb 28, 2020
The regex that parses header lines potentially causes an unlimited
amount of backtracking, which can cause an exception in the libc++ regex
engine.

The exception that occurs looks like this and is identical to the
message of the exception fixed in
yhirose#280:

	libc++abi.dylib: terminating with uncaught exception of type
	std::__1::regex_error: The complexity of an attempted match
	against a regular expression exceeded a pre-set level.

This commit eliminates the problematic backtracking.
yhirose pushed a commit that referenced this pull request Feb 28, 2020
The regex that parses header lines potentially causes an unlimited
amount of backtracking, which can cause an exception in the libc++ regex
engine.

The exception that occurs looks like this and is identical to the
message of the exception fixed in
#280:

	libc++abi.dylib: terminating with uncaught exception of type
	std::__1::regex_error: The complexity of an attempted match
	against a regular expression exceeded a pre-set level.

This commit eliminates the problematic backtracking.
yhirose pushed a commit that referenced this pull request May 2, 2020
The regex that parses header lines potentially causes an unlimited
amount of backtracking, which can cause an exception in the libc++ regex
engine.

The exception that occurs looks like this and is identical to the
message of the exception fixed in
#280:

	libc++abi.dylib: terminating with uncaught exception of type
	std::__1::regex_error: The complexity of an attempted match
	against a regular expression exceeded a pre-set level.

This commit eliminates the problematic backtracking.
IdoeuRosen added a commit to IdoeuRosen/cpp-httplib that referenced this pull request Feb 19, 2023
The regex that parses header lines potentially causes an unlimited
amount of backtracking, which can cause an exception in the libc++ regex
engine.

The exception that occurs looks like this and is identical to the
message of the exception fixed in
yhirose/cpp-httplib#280:

	libc++abi.dylib: terminating with uncaught exception of type
	std::__1::regex_error: The complexity of an attempted match
	against a regular expression exceeded a pre-set level.

This commit eliminates the problematic backtracking.
ExclusiveOrange pushed a commit to ExclusiveOrange/cpp-httplib-exor that referenced this pull request May 2, 2023
The regex that parses header lines potentially causes an unlimited
amount of backtracking, which can cause an exception in the libc++ regex
engine.

The exception that occurs looks like this and is identical to the
message of the exception fixed in
yhirose#280:

	libc++abi.dylib: terminating with uncaught exception of type
	std::__1::regex_error: The complexity of an attempted match
	against a regular expression exceeded a pre-set level.

This commit eliminates the problematic backtracking.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants