diff --git a/include/tsutil/StringCompare.h b/include/tsutil/StringCompare.h new file mode 100644 index 00000000000..fa054ccf4e2 --- /dev/null +++ b/include/tsutil/StringCompare.h @@ -0,0 +1,49 @@ +/** @file + + Helper for std::string_view comparison + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#pragma once + +#include +#include + +namespace ts +{ +/** + Returns true iff @a lhs and @a rhs compare equal, ignoring case. + + Prefer this over libswoc's @c strcasecmp(std::string_view, std::string_view) when you only need + an equality check: this short-circuits on length mismatch, whereas the libswoc version must keep + comparing bytes to produce a correct ordering result even when the lengths differ. + + For case-sensitive comparison, use @c std::string_view::operator==. + */ +inline bool +iequals(std::string_view lhs, std::string_view rhs) noexcept +{ + if (lhs.size() != rhs.size()) { + return false; + } + + return ::strncasecmp(lhs.data(), rhs.data(), lhs.size()) == 0; +} +} // namespace ts diff --git a/src/proxy/hdrs/MIME.cc b/src/proxy/hdrs/MIME.cc index fc7fac251c9..f8e25de040b 100644 --- a/src/proxy/hdrs/MIME.cc +++ b/src/proxy/hdrs/MIME.cc @@ -24,6 +24,9 @@ #include "tscore/ink_defs.h" #include "tscore/ink_platform.h" #include "tscore/ink_memory.h" + +#include "tsutil/StringCompare.h" + #include #include #include @@ -1161,8 +1164,8 @@ _mime_hdr_field_list_search_by_string(MIMEHdrImpl *mh, std::string_view field_na too_far_field = &(fblock->m_field_slots[fblock->m_freetop]); while (field < too_far_field) { if (field->is_live() && - strcasecmp(std::string_view{field->m_ptr_name, static_cast(field->m_len_name)}, - field_name) == 0) { + ts::iequals(std::string_view{field->m_ptr_name, static_cast(field->m_len_name)}, + field_name)) { return field; } ++field; diff --git a/src/proxy/http/HttpSM.cc b/src/proxy/http/HttpSM.cc index c8a6b128dc8..d6188a7dbc0 100644 --- a/src/proxy/http/HttpSM.cc +++ b/src/proxy/http/HttpSM.cc @@ -25,6 +25,7 @@ #include "proxy/http/HttpConfig.h" #include "tscore/ink_hrtime.h" #include "tsutil/Metrics.h" +#include "tsutil/StringCompare.h" #include "tsutil/ts_bw_format.h" #include "proxy/ProxyTransaction.h" #include "proxy/http/HttpSM.h" @@ -791,7 +792,7 @@ HttpSM::state_read_client_request_header(int event, void *data) (t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_POST || t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_PUT)) { auto expect{t_state.hdr_info.client_request.value_get(static_cast(MIME_FIELD_EXPECT))}; - if (strcasecmp(expect, static_cast(HTTP_VALUE_100_CONTINUE)) == 0) { + if (ts::iequals(expect, static_cast(HTTP_VALUE_100_CONTINUE))) { // When receive an "Expect: 100-continue" request from client, ATS sends a "100 Continue" response to client // immediately, before receive the real response from original server. if (t_state.http_config_param->send_100_continue_response) { diff --git a/src/proxy/http/HttpTransactHeaders.cc b/src/proxy/http/HttpTransactHeaders.cc index 11e00c1bc18..fab348dd521 100644 --- a/src/proxy/http/HttpTransactHeaders.cc +++ b/src/proxy/http/HttpTransactHeaders.cc @@ -40,6 +40,7 @@ #include "iocore/utils/Machine.h" #include "tsutil/DbgCtl.h" +#include "tsutil/StringCompare.h" using namespace std::literals; @@ -898,7 +899,7 @@ HttpTransactHeaders::remove_100_continue_headers(HttpTransact::State *s, HTTPHdr { auto expect{s->hdr_info.client_request.value_get(static_cast(MIME_FIELD_EXPECT))}; - if (strcasecmp(expect, static_cast(HTTP_VALUE_100_CONTINUE)) == 0) { + if (ts::iequals(expect, static_cast(HTTP_VALUE_100_CONTINUE))) { outgoing->field_delete(static_cast(MIME_FIELD_EXPECT)); } }