Skip to content

Commit

Permalink
Poison-pilling mismatched Protobuf Java Full/Lite versions.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 590333552
  • Loading branch information
protobuf-github-bot authored and copybara-github committed Jan 3, 2024
1 parent 807f00b commit 378bccc
Show file tree
Hide file tree
Showing 12 changed files with 316 additions and 221 deletions.
2 changes: 1 addition & 1 deletion java/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ LITE_SRCS = [
"src/main/java/com/google/protobuf/RawMessageInfo.java",
"src/main/java/com/google/protobuf/Reader.java",
"src/main/java/com/google/protobuf/RopeByteString.java",
"src/main/java/com/google/protobuf/RuntimeVersion.java",
"src/main/java/com/google/protobuf/RuntimeVersionLite.java",
"src/main/java/com/google/protobuf/Schema.java",
"src/main/java/com/google/protobuf/SchemaFactory.java",
"src/main/java/com/google/protobuf/SchemaUtil.java",
Expand Down
105 changes: 4 additions & 101 deletions java/core/src/main/java/com/google/protobuf/RuntimeVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,13 @@

package com.google.protobuf;

import java.util.logging.Logger;

/**
* Provides the version of this Protobuf Java runtime, and methods for Protobuf Java gencode to
* validate that versions are compatible. Fields and methods in this class should be only accessed
* by related unit tests and Protobuf Java gencode, and should not be used elsewhere.
*/
public final class RuntimeVersion {

/** Indicates the domain of the Protobuf artifact. */
public enum RuntimeDomain {
GOOGLE_INTERNAL,
PUBLIC,
}

// The version of this runtime.
// Automatically updated by Protobuf release process. Do not edit manually.
public static final RuntimeDomain DOMAIN = RuntimeDomain.PUBLIC;
public static final int MAJOR = 3;
public static final int MINOR = 26;
public static final int PATCH = 0;
public static final String SUFFIX = "-dev";
private static final String VERSION_STRING = versionString(MAJOR, MINOR, PATCH, SUFFIX);

/**
* Validates that the gencode is in the same domain as the runtime.
*
* <p>This method will be directly called by the google-internal gencode to verify no cross-domain
* usages.
*
* @param gencodeDomain the domain where Protobuf Java code was generated.
* @throws ProtobufRuntimeVersionException if gencodeDomain is not the same as DOMAIN.
*/
public static void validateProtobufGencodeDomain(RuntimeDomain gencodeDomain) {
// Check the environmental variable, and temporarily disable validation if it's set to true.
String disableFlag = java.lang.System.getenv("TEMORARILY_DISABLE_PROTOBUF_VERSION_CHECK");
if ((disableFlag != null && disableFlag.equals("true"))) {
return;
}

if (gencodeDomain != DOMAIN) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime domains: gencode %s, runtime %s. Cross-domain"
+ " usage of Protobuf is not supported.",
gencodeDomain, DOMAIN));
}
}

/** Provides methods to check Protobuf Java runtime version matches the gencode version. */
public class RuntimeVersion extends RuntimeVersionLite {
/**
* Validates that the gencode version is compatible with this runtime version according to
* https://protobuf.dev/support/cross-version-runtime-guarantee/.
*
* <p>This method is currently only used by Protobuf Java gencode in OSS.
* <p>This method is currently only used by Protobuf Java Full-version gencode in OSS.
*
* <p>This method is only for Protobuf Java gencode; do not call it elsewhere.
*
Expand All @@ -73,56 +26,6 @@ public static void validateProtobufGencodeDomain(RuntimeDomain gencodeDomain) {
*/
public static void validateProtobufGencodeVersion(
RuntimeDomain domain, int major, int minor, int patch, String suffix) {

// Check that version numbers are valid.
if (major < 0 || minor < 0 || patch < 0) {
throw new ProtobufRuntimeVersionException(
"Invalid gencode version: " + versionString(major, minor, patch, suffix));
}

validateProtobufGencodeDomain(domain);

String gencodeVersionString = versionString(major, minor, patch, suffix);
// Check that runtime major version is the same as the gencode major version.
if (major != MAJOR) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime major versions: gencode %s, runtime %s. Same"
+ " major version is required.",
gencodeVersionString, VERSION_STRING));
}

// Check that runtime version is newer than the gencode version.
if (MINOR < minor || (MINOR == minor && PATCH < patch)) {
throw new ProtobufRuntimeVersionException(
String.format(
"Protobuf Java runtime version cannot be older than the gencode version:"
+ "gencode %s, runtime %s.",
gencodeVersionString, VERSION_STRING));
}

// Check that runtime version suffix is the same as the gencode version suffix.
if (!suffix.equals(SUFFIX)) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime version suffixes: gencode %s, runtime %s."
+ " Version suffixes must be the same.",
gencodeVersionString, VERSION_STRING));
}
}

/**
* A runtime exception to be thrown by the version validator if version is not well defined or
* versions mismatch.
*/
public static final class ProtobufRuntimeVersionException extends RuntimeException {
public ProtobufRuntimeVersionException(String message) {
super(message);
}
}

/** Gets the version string given the version segments. */
private static String versionString(int major, int minor, int patch, String suffix) {
return String.format("%d.%d.%d%s", major, minor, patch, suffix);
validateProtobufGencodeVersionImpl(domain, major, minor, patch, suffix);
}
}
146 changes: 146 additions & 0 deletions java/core/src/main/java/com/google/protobuf/RuntimeVersionLite.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

package com.google.protobuf;

import java.util.logging.Logger;

/**
* Provides the version of this Protobuf Java runtime, and methods for Protobuf Java gencode to
* validate that versions are compatible. Fields and methods in this class should be only accessed
* by related unit tests and Protobuf Java gencode, and should not be used elsewhere.
*/
public class RuntimeVersionLite {

/** Indicates the domain of the Protobuf artifact. */
public enum RuntimeDomain {
GOOGLE_INTERNAL,
PUBLIC,
}

// The version of this runtime.
// Automatically updated by Protobuf release process. Do not edit manually.
public static final RuntimeDomain DOMAIN = RuntimeDomain.PUBLIC;
public static final int MAJOR = 3;
public static final int MINOR = 26;
public static final int PATCH = 0;
public static final String SUFFIX = "-dev";
private static final String VERSION_STRING = versionString(MAJOR, MINOR, PATCH, SUFFIX);

/**
* Validates that the gencode is in the same domain as the runtime.
*
* <p>This method will be directly called by the google-internal gencode to verify no cross-domain
* usages.
*
* @param gencodeDomain the domain where Protobuf Java code was generated.
* @throws ProtobufRuntimeVersionException if gencodeDomain is not the same as DOMAIN.
*/
public static void validateProtobufGencodeDomain(RuntimeDomain gencodeDomain) {
// Check the environmental variable, and temporarily disable validation if it's set to true.
String disableFlag = java.lang.System.getenv("TEMORARILY_DISABLE_PROTOBUF_VERSION_CHECK");
if ((disableFlag != null && disableFlag.equals("true"))) {
return;
}

if (gencodeDomain != DOMAIN) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime domains: gencode %s, runtime %s. Cross-domain"
+ " usage of Protobuf is not supported.",
gencodeDomain, DOMAIN));
}
}

/**
* Validates that the lite gencode version is compatible with this lite runtime version according
* to https://protobuf.dev/support/cross-version-runtime-guarantee/.
*
* <p>This method is currently only used by Protobuf Java Lite gencode in OSS.
*
* <p>This method is only for Protobuf Java gencode; do not call it elsewhere.
*
* @param domain the domain where Protobuf Java code was generated.
* @param major the major version of Protobuf Java gencode.
* @param minor the minor version of Protobuf Java gencode.
* @param patch the micro/patch version of Protobuf Java gencode.
* @param suffix the version suffix e.g. "-rc2", "-dev", etc.
* @throws ProtobufRuntimeVersionException if versions are incompatible.
*/
public static void validateProtobufLiteGencodeVersion(
RuntimeDomain domain, int major, int minor, int patch, String suffix) {
expectProtobufJavaLiteRuntime();
validateProtobufGencodeVersionImpl(domain, major, minor, patch, suffix);
}

/** Core method for version validation, regardless of the version fullness. */
protected static void validateProtobufGencodeVersionImpl(
RuntimeDomain domain, int major, int minor, int patch, String suffix) {

// Check that version numbers are valid.
if (major < 0 || minor < 0 || patch < 0) {
throw new ProtobufRuntimeVersionException(
"Invalid gencode version: " + versionString(major, minor, patch, suffix));
}

validateProtobufGencodeDomain(domain);

String gencodeVersionString = versionString(major, minor, patch, suffix);
// Check that runtime major version is the same as the gencode major version.
if (major != MAJOR) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime major versions: gencode %s, runtime %s. Same"
+ " major version is required.",
gencodeVersionString, VERSION_STRING));
}

// Check that runtime version is newer than the gencode version.
if (MINOR < minor || (MINOR == minor && PATCH < patch)) {
throw new ProtobufRuntimeVersionException(
String.format(
"Protobuf Java runtime version cannot be older than the gencode version:"
+ "gencode %s, runtime %s.",
gencodeVersionString, VERSION_STRING));
}

// Check that runtime version suffix is the same as the gencode version suffix.
if (!suffix.equals(SUFFIX)) {
throw new ProtobufRuntimeVersionException(
String.format(
"Mismatched Protobuf Gencode/Runtime version suffixes: gencode %s, runtime %s."
+ " Version suffixes must be the same.",
gencodeVersionString, VERSION_STRING));
}
}

/**
* A runtime exception to be thrown by the version validator if version is not well defined or
* versions mismatch.
*/
public static final class ProtobufRuntimeVersionException extends RuntimeException {
public ProtobufRuntimeVersionException(String message) {
super(message);
}
}

/** Gets the version string given the version segments. */
private static String versionString(int major, int minor, int patch, String suffix) {
return String.format("%d.%d.%d%s", major, minor, patch, suffix);
}

/** Checks that the full version runtime is not loaded for the lite gencode. */
private static void expectProtobufJavaLiteRuntime() {
try {
Class.forName("com.google.protobuf.RuntimeVersion");
} catch (ClassNotFoundException e) {
return;
}
throw new ProtobufRuntimeVersionException(
"Expected only Protobuf Java Lite runtime, but found Protobuf Java Full runtime.");
}
}
Loading

0 comments on commit 378bccc

Please sign in to comment.