Copilot commented on code in PR #13903: URL: https://github.com/apache/trafficserver/pull/13903#discussion_r4383190765
########## tests/fuzzing/fuzz_ip.cc: ########## @@ -0,0 +1,145 @@ +/** @file + + fuzzing swoc IP address parsing and tscore ink_inet + + @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. +*/ + +#include "swoc/IPEndpoint.h" +#include "swoc/IPRange.h" +#include "swoc/IPSrv.h" +#include "tscore/ink_inet.h" + +#include <string> +#include <string_view> +#include <vector> + +#define kMinInputLength 4 +#define kMaxInputLength 4096 + +namespace +{ +bool +is_space(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; +} + +} // namespace + +extern "C" int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < kMinInputLength || size > kMaxInputLength) { + return 0; + } + + std::string_view text(reinterpret_cast<char const *>(data), size); + + // Parse every whitespace separated token with every IP text parser that + // trafficserver exposes and cross exercise the range set bookkeeping. + swoc::IPRangeSet ranges; + std::vector<swoc::IPAddr> addrs; + + size_t pos = 0; + while (pos < text.size()) { + while (pos < text.size() && is_space(text[pos])) { + ++pos; + } + size_t start = pos; + while (pos < text.size() && !is_space(text[pos])) { + ++pos; + } + if (pos == start) { + break; + } + std::string_view token = text.substr(start, pos - start); + + swoc::IPAddr addr; + if (addr.load(token)) { + addrs.push_back(addr); + (void)addr.family(); + (void)addr.is_ip4(); + (void)addr.is_ip6(); + (void)addr.is_valid(); + (void)addr.is_loopback(); + (void)addr.is_multicast(); + (void)addr.is_link_local(); + (void)addr.is_private(); + if (addr.is_ip4()) { + (void)addr.ip4().is_any(); + } else if (addr.is_ip6()) { + (void)addr.ip6().is_any(); + (void)addr.ip6().is_mapped_ip4(); + } + (void)(addr == swoc::IPAddr::INVALID); + } + + swoc::IPEndpoint endpoint; + if (endpoint.parse(token)) { + (void)endpoint.is_valid(); + (void)endpoint.host_order_port(); + (void)endpoint.network_order_port(); + (void)endpoint.is_multicast(); + } + + swoc::IPMask mask; + if (mask.load(token)) { + (void)mask.width(); + } + + swoc::IPRange range; + if (range.load(token)) { + ranges.mark(range); + swoc::IPAddr rmin = range.min(); + swoc::IPAddr rmax = range.max(); + (void)rmin.family(); + (void)rmax.family(); + (void)range.network_mask(); + (void)range.empty(); + } + + swoc::IPSrv srv; + if (srv.load(token)) { + (void)srv.addr(); + (void)srv.host_order_port(); + (void)srv.network_order_port(); + (void)srv.family(); + (void)srv.is_valid(); + } + + // Run the tscore parser on the same text and render the result back into + // a canonical string, which is parsed once more by swoc. + IpEndpoint ts_endpoint{}; + if (ats_ip_pton(token, &ts_endpoint.sa) == 0) { Review Comment: `token` is a `std::string_view` into the libFuzzer buffer and is not guaranteed to be NUL-terminated. For an input whose final token is a valid endpoint such as `192.0.2.1:80`, `ats_ip_pton` reaches `atoi(port.data())` in `src/tscore/ink_inet.cc`, which reads past the view looking for a terminator; under sanitizers this can make the new target report an out-of-bounds read for ordinary valid inputs. Pass a NUL-terminated copy to this API (or otherwise make the parser length-safe) before fuzzing it. ########## tests/fuzzing/fuzz_ip.cc: ########## @@ -0,0 +1,145 @@ +/** @file + + fuzzing swoc IP address parsing and tscore ink_inet + + @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. +*/ + +#include "swoc/IPEndpoint.h" +#include "swoc/IPRange.h" +#include "swoc/IPSrv.h" +#include "tscore/ink_inet.h" + +#include <string> +#include <string_view> +#include <vector> + +#define kMinInputLength 4 +#define kMaxInputLength 4096 Review Comment: The minimum-size guard drops valid IP inputs before any parser runs: `::` and `::1` are valid IPv6 addresses, and `0/0` is a valid range/mask input, but all are shorter than four bytes. Since this target is specifically intended to fuzz the IP parsers, please lower this threshold (or remove it) so these boundary forms can reach the harness. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
