Skip to content

Commit 320eafa

Browse files
authored
Weaken vulnerable gencode poison pills to warning by default.
Weaken vulnerable gencode poison pills to warning by default. Merge pull request #21688 from esrauchg/25.x
2 parents c710036 + f584fe3 commit 320eafa

File tree

5 files changed

+136
-24
lines changed

5 files changed

+136
-24
lines changed

java/core/BUILD.bazel

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ junit_tests(
369369
"src/test/java/com/google/protobuf/TestUtil.java",
370370
"src/test/java/com/google/protobuf/TestUtilLite.java",
371371
"src/test/java/com/google/protobuf/GeneratedMessagePre22WarningDisabledTest.java",
372+
"src/test/java/com/google/protobuf/GeneratedMessagePre22ErrorTest.java",
372373
],
373374
),
374375
data = ["//src/google/protobuf:testdata"],
@@ -473,6 +474,7 @@ LITE_TEST_EXCLUSIONS = [
473474
"src/test/java/com/google/protobuf/FieldPresenceTest.java",
474475
"src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java",
475476
"src/test/java/com/google/protobuf/GeneratedMessagePre22WarningDisabledTest.java",
477+
"src/test/java/com/google/protobuf/GeneratedMessagePre22ErrorTest.java",
476478
"src/test/java/com/google/protobuf/GeneratedMessageTest.java",
477479
"src/test/java/com/google/protobuf/LazyFieldTest.java",
478480
"src/test/java/com/google/protobuf/LazyStringEndToEndTest.java",
@@ -545,6 +547,24 @@ java_test(
545547
],
546548
)
547549

550+
java_test(
551+
name = "GeneratedMessagePre22ErrorTest",
552+
size = "small",
553+
srcs = [
554+
"src/test/java/com/google/protobuf/GeneratedMessagePre22ErrorTest.java",
555+
],
556+
jvm_flags = ["-Dcom.google.protobuf.error_on_unsafe_pre22_gencode"],
557+
deps = [
558+
":core",
559+
":generic_test_protos_java_proto",
560+
":java_test_protos_java_proto",
561+
":lite_test_protos_java_proto",
562+
":test_util",
563+
"@maven//:com_google_truth_truth",
564+
"@maven//:junit_junit",
565+
],
566+
)
567+
548568
pkg_files(
549569
name = "dist_files",
550570
srcs = glob([

java/core/src/main/java/com/google/protobuf/GeneratedMessage.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.List;
2626
import java.util.Map;
2727
import java.util.TreeMap;
28+
import java.util.logging.Logger;
2829

2930
/**
3031
* All generated protocol message classes extend this class. This class implements most of the
@@ -35,6 +36,7 @@
3536
*/
3637
public abstract class GeneratedMessage extends AbstractMessage implements Serializable {
3738
private static final long serialVersionUID = 1L;
39+
private static final Logger logger = Logger.getLogger(GeneratedMessage.class.getName());
3840

3941
/**
4042
* For testing. Allows a test to disable the optimization that avoids using field builders for
@@ -310,22 +312,33 @@ public int getSerializedSize() {
310312
return memoizedSize;
311313
}
312314

313-
static final String PRE22_GENCODE_ACKNOWLEGE_PROPERTY =
315+
static final String PRE22_GENCODE_SILENCE_PROPERTY =
314316
"com.google.protobuf.use_unsafe_pre22_gencode";
317+
static final String PRE22_GENCODE_ERROR_PROPERTY =
318+
"com.google.protobuf.error_on_unsafe_pre22_gencode";
319+
315320
static final String PRE22_GENCODE_VULNERABILITY_MESSAGE =
316321
"As of 2022/09/29 (release 21.7) makeExtensionsImmutable should not be called from protobuf"
317322
+ " gencode. If you are seeing this message, your gencode is vulnerable to a denial of"
318323
+ " service attack. You should regenerate your code using protobuf 25.6 or later. Use the"
319324
+ " latest version that meets your needs. However, if you understand the risks and wish"
320325
+ " to continue with vulnerable gencode, you can set the system property"
321-
+ " `-Dcom.google.protobuf.use_unsafe_pre22_gencode` on the command line. See security"
322-
+ " vulnerability:"
326+
+ " `-Dcom.google.protobuf.use_unsafe_pre22_gencode` on the command line to silence this"
327+
+ " warning. You also can set"
328+
+ " `-Dcom.google.protobuf.error_on_unsafe_pre22_gencode` to throw an error instead. See"
329+
+ " security vulnerability:"
323330
+ " https://github.com/protocolbuffers/protobuf/security/advisories/GHSA-h4h5-3hr4-j3g2";
324331

325332
static void warnPre22Gencode() {
326-
if (System.getProperty(PRE22_GENCODE_ACKNOWLEGE_PROPERTY) == null) {
327-
throw new UnsupportedOperationException(PRE22_GENCODE_VULNERABILITY_MESSAGE);
333+
if (System.getProperty(PRE22_GENCODE_SILENCE_PROPERTY) != null) {
334+
return;
335+
}
336+
UnsupportedOperationException exception =
337+
new UnsupportedOperationException(PRE22_GENCODE_VULNERABILITY_MESSAGE);
338+
if (System.getProperty(PRE22_GENCODE_ERROR_PROPERTY) != null) {
339+
throw exception;
328340
}
341+
logger.warning(exception.toString());
329342
}
330343

331344
/** Used by parsing constructors in generated classes. */
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.google.protobuf;
2+
3+
import static com.google.common.truth.Truth.assertThat;
4+
import static org.junit.Assert.assertThrows;
5+
6+
import protobuf_unittest.UnittestProto.TestAllExtensions;
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
import org.junit.runners.JUnit4;
10+
11+
@RunWith(JUnit4.class)
12+
public class GeneratedMessagePre22ErrorTest {
13+
@Test
14+
public void generatedMessage_makeExtensionsImmutableShouldError() {
15+
GeneratedMessageV3 msg =
16+
new GeneratedMessageV3() {
17+
@Override
18+
protected FieldAccessorTable internalGetFieldAccessorTable() {
19+
return null;
20+
}
21+
22+
@Override
23+
protected Message.Builder newBuilderForType(BuilderParent parent) {
24+
return null;
25+
}
26+
27+
@Override
28+
public Message.Builder newBuilderForType() {
29+
return null;
30+
}
31+
32+
@Override
33+
public Message.Builder toBuilder() {
34+
return null;
35+
}
36+
37+
@Override
38+
public Message getDefaultInstanceForType() {
39+
return null;
40+
}
41+
};
42+
Throwable e = assertThrows(UnsupportedOperationException.class, () -> msg.makeExtensionsImmutable());
43+
assertThat(e).hasMessageThat().contains(GeneratedMessage.PRE22_GENCODE_VULNERABILITY_MESSAGE);
44+
}
45+
46+
@Test
47+
public void extendableMessage_makeExtensionsImmutableShouldError() {
48+
GeneratedMessageV3.ExtendableMessage<TestAllExtensions> msg =
49+
TestAllExtensions.newBuilder().build();
50+
Throwable e = assertThrows(UnsupportedOperationException.class, () -> msg.makeExtensionsImmutable());
51+
assertThat(e).hasMessageThat().contains(GeneratedMessage.PRE22_GENCODE_VULNERABILITY_MESSAGE);
52+
}
53+
}

java/core/src/test/java/com/google/protobuf/GeneratedMessagePre22WarningDisabledTest.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11
package com.google.protobuf;
22

3+
import static com.google.common.truth.Truth.assertThat;
4+
35
import protobuf_unittest.UnittestProto.TestAllExtensions;
6+
import java.util.logging.Level;
7+
import java.util.logging.Logger;
48
import org.junit.Test;
59
import org.junit.runner.RunWith;
610
import org.junit.runners.JUnit4;
711

812
@RunWith(JUnit4.class)
913
public class GeneratedMessagePre22WarningDisabledTest {
14+
private TestUtil.TestLogHandler setupLogger() {
15+
TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler();
16+
Logger logger = Logger.getLogger(GeneratedMessage.class.getName());
17+
logger.addHandler(logHandler);
18+
logHandler.setLevel(Level.ALL);
19+
return logHandler;
20+
}
21+
1022
@Test
11-
public void generatedMessage_makeExtensionsImmutableShouldNotThrow() {
23+
public void generatedMessage_makeExtensionsImmutableShouldNotLog() {
24+
TestUtil.TestLogHandler logHandler = setupLogger();
1225
GeneratedMessageV3 msg =
1326
new GeneratedMessageV3() {
1427
@Override
@@ -37,13 +50,16 @@ public Message getDefaultInstanceForType() {
3750
}
3851
};
3952
msg.makeExtensionsImmutable();
53+
assertThat(logHandler.getStoredLogRecords()).isEmpty();
4054
}
4155

4256
@Test
43-
public void extendableMessage_makeExtensionsImmutableShouldNotThrow() {
57+
public void extendableMessage_makeExtensionsImmutableShouldNotLog() {
58+
TestUtil.TestLogHandler logHandler = setupLogger();
4459
GeneratedMessageV3.ExtendableMessage<TestAllExtensions> msg =
4560
TestAllExtensions.newBuilder().build();
4661
msg.makeExtensionsImmutable();
62+
assertThat(logHandler.getStoredLogRecords()).isEmpty();
4763
}
4864
}
4965

java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@
5050
import java.util.Collections;
5151
import java.util.Iterator;
5252
import java.util.List;
53+
import java.util.logging.Level;
54+
import java.util.logging.LogRecord;
55+
import java.util.logging.Logger;
5356
import org.junit.After;
5457
import org.junit.Test;
5558
import org.junit.runner.RunWith;
@@ -1999,9 +2002,19 @@ public void extendableBuilder_mergeFrom_repeatedField_doesNotInvalidateExistingB
19992002
assertThat(builder.getRepeatedField(REPEATED_NESTED_MESSAGE_EXTENSION, 0))
20002003
.isEqualTo(NestedMessage.newBuilder().setBb(100).build());
20012004
}
2005+
2006+
private TestUtil.TestLogHandler setupLogger() {
2007+
TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler();
2008+
Logger logger = Logger.getLogger(GeneratedMessage.class.getName());
2009+
logger.addHandler(logHandler);
2010+
logHandler.setLevel(Level.ALL);
2011+
return logHandler;
2012+
}
2013+
20022014

20032015
@Test
2004-
public void generatedMessage_makeExtensionsImmutableShouldThrow() {
2016+
public void generatedMessage_makeExtensionsImmutableShouldLog() {
2017+
TestUtil.TestLogHandler logHandler = setupLogger();
20052018
GeneratedMessageV3 msg =
20062019
new GeneratedMessageV3() {
20072020
@Override
@@ -2029,27 +2042,24 @@ public Message getDefaultInstanceForType() {
20292042
return null;
20302043
}
20312044
};
2032-
try {
2033-
msg.makeExtensionsImmutable();
2034-
assertWithMessage("Expected UnsupportedOperationException").fail();
2035-
} catch (UnsupportedOperationException e) {
2036-
// Expected
2037-
assertThat(e).hasMessageThat().contains(GeneratedMessage.PRE22_GENCODE_VULNERABILITY_MESSAGE);
2038-
assertThat(e).hasMessageThat().contains(GeneratedMessage.PRE22_GENCODE_ACKNOWLEGE_PROPERTY);
2039-
}
2045+
msg.makeExtensionsImmutable();
2046+
List<LogRecord> logs = logHandler.getStoredLogRecords();
2047+
assertThat(logs).hasSize(1);
2048+
String message = logs.get(0).getMessage();
2049+
assertThat(message).contains(GeneratedMessage.PRE22_GENCODE_VULNERABILITY_MESSAGE);
2050+
assertThat(message).contains(GeneratedMessage.PRE22_GENCODE_SILENCE_PROPERTY);
20402051
}
20412052

20422053
@Test
20432054
public void extendableMessage_makeExtensionsImmutableShouldThrow() {
2055+
TestUtil.TestLogHandler logHandler = setupLogger();
20442056
GeneratedMessageV3.ExtendableMessage<TestAllExtensions> msg =
20452057
TestAllExtensions.getDefaultInstance();
2046-
try {
2047-
msg.makeExtensionsImmutable();
2048-
assertWithMessage("Expected UnsupportedOperationException").fail();
2049-
} catch (UnsupportedOperationException e) {
2050-
// Expected
2051-
assertThat(e).hasMessageThat().contains(GeneratedMessage.PRE22_GENCODE_VULNERABILITY_MESSAGE);
2052-
assertThat(e).hasMessageThat().contains(GeneratedMessage.PRE22_GENCODE_ACKNOWLEGE_PROPERTY);
2053-
}
2058+
msg.makeExtensionsImmutable();
2059+
List<LogRecord> logs = logHandler.getStoredLogRecords();
2060+
assertThat(logs).hasSize(1);
2061+
String message = logs.get(0).getMessage();
2062+
assertThat(message).contains(GeneratedMessage.PRE22_GENCODE_VULNERABILITY_MESSAGE);
2063+
assertThat(message).contains(GeneratedMessage.PRE22_GENCODE_SILENCE_PROPERTY);
20542064
}
20552065
}

0 commit comments

Comments
 (0)