diff --git a/core/src/main/java/google/registry/model/eppcommon/Address.java b/core/src/main/java/google/registry/model/eppcommon/Address.java
index ddb98101ca0..95502d2cdcf 100644
--- a/core/src/main/java/google/registry/model/eppcommon/Address.java
+++ b/core/src/main/java/google/registry/model/eppcommon/Address.java
@@ -49,6 +49,10 @@
* also matches the "addrType" type from Mark and Signed Mark Objects Mapping.
*
+ *
The lengths of the fields are limited to match the constraints defined in XSD schemas like
+ * {@code rde-registrar.xsd}. Specifically, {@code zip} is limited to 16 characters and {@code
+ * city}, {@code state}, and each {@code street} line are limited to 255 characters.
+ *
* @see google.registry.model.mark.MarkAddress
* @see google.registry.model.registrar.RegistrarAddress
*/
@@ -169,11 +173,20 @@ public void validateState() {
street == null || (!street.isEmpty() && street.size() <= 3),
"Street address must have [1-3] lines: %s",
street);
- //noinspection ConstantConditions
+ if (street != null) {
+ checkArgument(
+ street.stream().noneMatch(String::isEmpty),
+ "Street address cannot contain empty string: %s",
+ street);
+ checkArgument(
+ street.stream().allMatch(s -> s.length() <= 255),
+ "Street address lines cannot be longer than 255 characters");
+ }
checkArgument(
- street == null || street.stream().noneMatch(String::isEmpty),
- "Street address cannot contain empty string: %s",
- street);
+ city == null || city.length() <= 255, "City cannot be longer than 255 characters");
+ checkArgument(
+ state == null || state.length() <= 255, "State cannot be longer than 255 characters");
+ checkArgument(zip == null || zip.length() <= 16, "Zip cannot be longer than 16 characters");
checkArgument(
countryCode == null || countryCode.length() == 2,
"Country code should be a 2 character string");
@@ -196,9 +209,9 @@ public T build() {
public Builder setStreet(ImmutableList street) {
getInstance().street = street;
- getInstance().streetLine1 = street.get(0);
- getInstance().streetLine2 = street.size() >= 2 ? street.get(1) : null;
- getInstance().streetLine3 = street.size() == 3 ? street.get(2) : null;
+ getInstance().streetLine1 = (street != null && street.size() >= 1) ? street.get(0) : null;
+ getInstance().streetLine2 = (street != null && street.size() >= 2) ? street.get(1) : null;
+ getInstance().streetLine3 = (street != null && street.size() == 3) ? street.get(2) : null;
return this;
}
diff --git a/core/src/test/java/google/registry/model/eppcommon/AddressTest.java b/core/src/test/java/google/registry/model/eppcommon/AddressTest.java
index f9c92818c98..6aa7446cb12 100644
--- a/core/src/test/java/google/registry/model/eppcommon/AddressTest.java
+++ b/core/src/test/java/google/registry/model/eppcommon/AddressTest.java
@@ -109,6 +109,32 @@ void testFailure_emptyStreetLine() {
assertThrows(IllegalArgumentException.class, () -> createAddress("line1", "", "line3"));
}
+ @Test
+ void testFailure_streetLineTooLong() {
+ assertThrows(IllegalArgumentException.class, () -> createAddress("a".repeat(256)));
+ }
+
+ @Test
+ void testFailure_cityTooLong() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> createAddress("line1").asBuilder().setCity("a".repeat(256)).build());
+ }
+
+ @Test
+ void testFailure_stateTooLong() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> createAddress("line1").asBuilder().setState("a".repeat(256)).build());
+ }
+
+ @Test
+ void testFailure_zipTooLong() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> createAddress("line1").asBuilder().setZip("12345678901234567").build());
+ }
+
@Test
void testSuccess_pojoToAndFromXml() throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(TestEntity.class);
diff --git a/core/src/test/java/google/registry/ui/server/console/settings/RdapRegistrarFieldsActionTest.java b/core/src/test/java/google/registry/ui/server/console/settings/RdapRegistrarFieldsActionTest.java
index c3284b379e4..5b260d50916 100644
--- a/core/src/test/java/google/registry/ui/server/console/settings/RdapRegistrarFieldsActionTest.java
+++ b/core/src/test/java/google/registry/ui/server/console/settings/RdapRegistrarFieldsActionTest.java
@@ -19,6 +19,7 @@
import static google.registry.testing.DatabaseHelper.loadSingleton;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
@@ -67,7 +68,8 @@ public class RdapRegistrarFieldsActionTest extends ConsoleActionBaseTestCase {
"url",
"\"http://my.fake.url\"",
"localizedAddress",
- "{\"street\": [\"123 Example Boulevard\"], \"city\": \"Williamsburg\", \"state\":"
+ "{\"street\": [\"123 Example Boulevard\"], \"city\":"
+ + " \"Williamsburg\", \"state\":"
+ " \"NY\", \"zip\": \"11201\", \"countryCode\": \"US\"}"));
@Test
@@ -132,6 +134,17 @@ void testFailure_noAccessToRegistrar() throws Exception {
assertThat(DatabaseHelper.loadByEntity(newRegistrar)).isEqualTo(newRegistrar);
}
+ @Test
+ void testFailure_zipTooLong() throws Exception {
+ uiRegistrarMap.put(
+ "localizedAddress",
+ "{\"street\": [\"123 Fake St\"], \"city\": \"Fakeville\", \"state\":"
+ + " \"NL\", \"zip\": \"12345678901234567\", \"countryCode\": \"CA\"}");
+ IllegalArgumentException exception =
+ assertThrows(IllegalArgumentException.class, this::createAction);
+ assertThat(exception).hasMessageThat().contains("Zip cannot be longer than 16 characters");
+ }
+
private RdapRegistrarFieldsAction createAction() throws IOException {
return createAction(fteUser);
}