Skip to content

Commit aaef919

Browse files
committed
Complete migration from protoc-gen-validate to protovalidate v1.0.0
Signed-off-by: Matthieu MOREL <[email protected]>
1 parent 780236f commit aaef919

File tree

18 files changed

+72
-760
lines changed

18 files changed

+72
-760
lines changed

api/bazel/api_build_system.bzl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,14 @@ def api_proto_package(
149149
has_services = has_services,
150150
)
151151

152-
compilers = ["@io_bazel_rules_go//proto:go_proto", "@com_envoyproxy_protoc_gen_validate//bazel/go:pgv_plugin_go", "@envoy_api//bazel:vtprotobuf_plugin_go"]
152+
compilers = ["@io_bazel_rules_go//proto:go_proto", "@envoy_api//bazel:vtprotobuf_plugin_go"]
153153
if has_services:
154-
compilers = ["@io_bazel_rules_go//proto:go_proto", "@io_bazel_rules_go//proto:go_grpc_v2", "@com_envoyproxy_protoc_gen_validate//bazel/go:pgv_plugin_go", "@envoy_api//bazel:vtprotobuf_plugin_go"]
154+
compilers = ["@io_bazel_rules_go//proto:go_proto", "@io_bazel_rules_go//proto:go_grpc_v2", "@envoy_api//bazel:vtprotobuf_plugin_go"]
155155

156156
deps = (
157157
[_go_proto_mapping(dep) for dep in deps] +
158158
[
159-
"@com_envoyproxy_protoc_gen_validate//validate:go_default_library",
159+
"@build_buf_gen_go_bufbuild_protovalidate_protocolbuffers_go//buf/validate",
160160
"@org_golang_google_genproto_googleapis_api//annotations:annotations",
161161
"@org_golang_google_genproto_googleapis_rpc//status:status",
162162
"@org_golang_google_protobuf//types/known/anypb:go_default_library",

api/bazel/repositories.bzl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ def api_dependencies():
2222
external_http_archive(
2323
name = "com_github_bufbuild_protovalidate",
2424
)
25+
external_http_archive(
26+
name = "com_github_bufbuild_protovalidate_cc",
27+
)
2528
external_http_archive(
2629
name = "com_google_googleapis",
2730
)

api/bazel/repository_locations.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ REPOSITORY_LOCATIONS_SPEC = dict(
2525
license = "Apache-2.0",
2626
license_url = "https://github.com/bufbuild/protovalidate/blob/v{version}/LICENSE",
2727
),
28+
com_github_bufbuild_protovalidate_cc = dict(
29+
project_name = "protovalidate-cc",
30+
project_desc = "C++ Protocol Buffer Validation Library",
31+
project_url = "https://github.com/bufbuild/protovalidate-cc",
32+
use_category = ["api"],
33+
sha256 = "4270d3babf1d883fd89139d80d002ad0b2dd1f16656c905514ee2d41cf9a2cb8",
34+
version = "1.0.0",
35+
urls = ["https://github.com/bufbuild/protovalidate-cc/archive/refs/tags/v{version}.tar.gz"],
36+
strip_prefix = "protovalidate-cc-{version}",
37+
release_date = "2025-09-18",
38+
license = "Apache-2.0",
39+
license_url = "https://github.com/bufbuild/protovalidate-cc/blob/v{version}/LICENSE",
40+
),
2841
rules_jvm_external = dict(
2942
project_name = "Java Rules for Bazel",
3043
project_desc = "Bazel rules for Java",

mobile/.bazelrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ build:rules_xcodeproj --define=apple.experimental.tree_artifact_outputs=0
5151
# Disable global index store to work around https://github.com/buildbuddy-io/rules_xcodeproj/issues/1878
5252
build:rules_xcodeproj --features=-swift.use_global_index_store
5353

54-
# Override PGV validation with NOP functions for binary size savings.
55-
build --@com_envoyproxy_protoc_gen_validate//bazel:template-flavor=nop
54+
# Note: protovalidate (the successor to protoc-gen-validate) performs runtime validation
55+
# and does not require compile-time code generation or build flags.
5656

5757
build:mobile-dbg-common --compilation_mode=dbg
5858
# Enable source map for debugging in IDEs

source/common/protobuf/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ envoy_cc_library(
223223
"//source/common/common:utility_lib",
224224
"//source/common/protobuf:visitor_lib",
225225
"//source/common/runtime:runtime_features_lib",
226+
"@com_github_bufbuild_protovalidate_cc//buf/validate:validator",
226227
"@com_github_cncf_xds//udpa/annotations:pkg_cc_proto",
227228
"@com_google_protobuf//:protobuf",
228229
"@envoy_api//envoy/annotations:pkg_cc_proto",

source/common/protobuf/utility.cc

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
#include "source/common/runtime/runtime_features.h"
1818

1919
#include "absl/strings/match.h"
20+
#include "buf/validate/validator.h"
2021
#include "udpa/annotations/sensitive.pb.h"
2122
#include "udpa/annotations/status.pb.h"
22-
#include "validate/validate.h"
2323
#include "xds/annotations/v3/status.pb.h"
2424

2525
using namespace std::chrono_literals;
@@ -364,32 +364,55 @@ void MessageUtil::validateDurationFields(const Protobuf::Message& message, bool
364364

365365
namespace {
366366

367-
class PgvCheckVisitor : public ProtobufMessage::ConstProtoVisitor {
367+
class ProtovalidateCheckVisitor : public ProtobufMessage::ConstProtoVisitor {
368368
public:
369+
ProtovalidateCheckVisitor() {
370+
// Initialize the validator factory once
371+
auto factory_result = buf::validate::ValidatorFactory::New();
372+
if (!factory_result.ok()) {
373+
PANIC(fmt::format("Failed to create protovalidate ValidatorFactory: {}",
374+
factory_result.status().ToString()));
375+
}
376+
factory_ = std::move(factory_result.value());
377+
}
378+
369379
absl::Status onMessage(const Protobuf::Message& message,
370380
absl::Span<const Protobuf::Message* const>,
371381
bool was_any_or_top_level) override {
372-
Protobuf::ReflectableMessage reflectable_message = createReflectableMessage(message);
373-
std::string err;
374-
// PGV verification is itself recursive up to the point at which it hits an Any message. As
375-
// such, to avoid N^2 checking of the tree, we only perform an additional check at the point
376-
// at which PGV would have stopped because it does not itself check within Any messages.
377-
if (was_any_or_top_level &&
378-
!pgv::BaseValidator::AbstractCheckMessage(*reflectable_message, &err)) {
379-
std::string error = fmt::format("{}: Proto constraint validation failed ({})",
380-
reflectable_message->DebugString(), err);
381-
return absl::InvalidArgumentError(error);
382+
// Protovalidate validation is recursive, similar to PGV. We only perform an additional
383+
// check at the top level or when encountering Any messages to avoid N^2 checking.
384+
if (was_any_or_top_level) {
385+
google::protobuf::Arena arena;
386+
auto validator = factory_->NewValidator(&arena, false);
387+
auto result = validator.Validate(message);
388+
if (!result.ok()) {
389+
return absl::InvalidArgumentError(
390+
fmt::format("Proto constraint validation failed: {}", result.status().ToString()));
391+
}
392+
const auto& violations = result.value();
393+
if (violations.violations_size() > 0) {
394+
std::string error_msg = "Proto constraint validation failed:";
395+
for (int i = 0; i < violations.violations_size(); ++i) {
396+
const auto& violation = violations.violations(i);
397+
error_msg += fmt::format("\n - Field '{}': {}", violation.field_path(),
398+
violation.message());
399+
}
400+
return absl::InvalidArgumentError(error_msg);
401+
}
382402
}
383403
return absl::OkStatus();
384404
}
385405

386406
void onField(const Protobuf::Message&, const Protobuf::FieldDescriptor&) override {}
407+
408+
private:
409+
std::unique_ptr<buf::validate::ValidatorFactory> factory_;
387410
};
388411

389412
} // namespace
390413

391414
void MessageUtil::recursivePgvCheck(const Protobuf::Message& message) {
392-
PgvCheckVisitor visitor;
415+
ProtovalidateCheckVisitor visitor;
393416
THROW_IF_NOT_OK(ProtobufMessage::traverseMessage(visitor, message, true));
394417
}
395418

source/common/protobuf/yaml_utility.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include "udpa/annotations/sensitive.pb.h"
1919
#include "udpa/annotations/status.pb.h"
2020
#include "utf8_validity.h"
21-
#include "validate/validate.h"
2221
#include "xds/annotations/v3/status.pb.h"
2322
#include "yaml-cpp/yaml.h"
2423

test/extensions/filters/network/common/fuzz/BUILD

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,9 @@ envoy_proto_library(
4040
],
4141
)
4242

43-
envoy_cc_test_library(
44-
name = "vig_anymap_ext_lib",
45-
srcs = ["validated_input_generator_any_map_extensions.cc"],
46-
hdrs = ["validated_input_generator_any_map_extensions.h"],
47-
deps = [
48-
"//source/extensions/access_loggers/file:config",
49-
"//source/extensions/http/early_header_mutation/header_mutation:config",
50-
"//source/extensions/http/header_validators/envoy_default:config",
51-
"//source/extensions/http/original_ip_detection/custom_header:config",
52-
"//source/extensions/http/original_ip_detection/xff:config",
53-
"//source/extensions/matching/actions/format_string:config",
54-
"//source/extensions/matching/common_inputs/environment_variable:config",
55-
"//source/extensions/matching/input_matchers/consistent_hashing:config",
56-
"//source/extensions/matching/input_matchers/ip:config",
57-
"//source/extensions/request_id/uuid:config",
58-
"//test/fuzz:validated_input_generator_lib",
59-
"@envoy_api//envoy/config/route/v3:pkg_cc_proto",
60-
"@envoy_api//envoy/config/trace/v3:pkg_cc_proto",
61-
],
62-
)
43+
# Note: vig_anymap_ext_lib has been removed as part of the protoc-gen-validate
44+
# to protovalidate migration. The library was an extension of validated_input_generator_lib
45+
# which has been removed due to incompatibility with protovalidate's runtime validation.
6346

6447
envoy_cc_test_library(
6548
name = "uber_readfilter_lib",
@@ -93,7 +76,6 @@ envoy_cc_fuzz_test(
9376
rbe_pool = "6gig",
9477
deps = [
9578
":uber_readfilter_lib",
96-
":vig_anymap_ext_lib",
9779
"//source/common/config:utility_lib",
9880
"//source/common/http:rds_lib",
9981
"//test/config:utility_lib",
@@ -140,7 +122,6 @@ envoy_cc_fuzz_test(
140122
# these up via the NamedNetworkFilterConfigFactory.
141123
deps = [
142124
":uber_writefilter_lib",
143-
":vig_anymap_ext_lib",
144125
"//source/common/config:utility_lib",
145126
"//test/config:utility_lib",
146127
] + envoy_filters_from_selected(WRITEFILTER_FUZZ_FILTERS),

test/extensions/filters/network/common/fuzz/network_readfilter_fuzz_test.cc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "test/config/utility.h"
66
#include "test/extensions/filters/network/common/fuzz/network_readfilter_fuzz.pb.validate.h"
77
#include "test/extensions/filters/network/common/fuzz/uber_readfilter.h"
8-
#include "test/extensions/filters/network/common/fuzz/validated_input_generator_any_map_extensions.h"
98
#include "test/fuzz/fuzz_runner.h"
109
#include "test/test_common/test_runtime.h"
1110

@@ -100,10 +99,8 @@ static void TestOneProtoInput(const test::extensions::filters::network::FilterFu
10099
// Replaying a corpus through the fuzzer will not be affected by the
101100
// post-processor mutation.
102101
ensuredValidFilter(seed, input->mutable_config());
103-
104-
ProtobufMessage::ValidatedInputGenerator generator(
105-
seed, ProtobufMessage::composeFiltersAnyMap(), 20);
106-
ProtobufMessage::traverseMessage(generator, *input, true);
102+
// Note: ValidatedInputGenerator removed as part of protovalidate migration.
103+
// Fuzzer now relies solely on libprotobuf-mutator for input generation.
107104
}};
108105

109106
try {

test/extensions/filters/network/common/fuzz/network_writefilter_fuzz_test.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "test/config/utility.h"
66
#include "test/extensions/filters/network/common/fuzz/network_writefilter_fuzz.pb.validate.h"
77
#include "test/extensions/filters/network/common/fuzz/uber_writefilter.h"
8-
#include "test/extensions/filters/network/common/fuzz/validated_input_generator_any_map_extensions.h"
98
#include "test/fuzz/fuzz_runner.h"
109

1110
namespace Envoy {
@@ -39,9 +38,8 @@ DEFINE_PROTO_FUZZER(const test::extensions::filters::network::FilterFuzzTestCase
3938
input->mutable_config()->mutable_typed_config()->set_type_url(
4039
absl::StrCat("type.googleapis.com/",
4140
factory->createEmptyConfigProto()->GetDescriptor()->full_name()));
42-
ProtobufMessage::ValidatedInputGenerator generator(
43-
seed, ProtobufMessage::composeFiltersAnyMap(), 20);
44-
ProtobufMessage::traverseMessage(generator, *input, true);
41+
// Note: ValidatedInputGenerator removed as part of protovalidate migration.
42+
// Fuzzer now relies solely on libprotobuf-mutator for input generation.
4543
}};
4644
try {
4745
TestUtility::validate(input);

0 commit comments

Comments
 (0)