Limit string field lengths for network/configuration objects

Change-Id: Ic375854bb697ee21a8fd7b15fccd0b0878212869
diff --git a/core/api/src/main/java/org/onosproject/net/config/Config.java b/core/api/src/main/java/org/onosproject/net/config/Config.java
index c7d821e..eb138b8 100644
--- a/core/api/src/main/java/org/onosproject/net/config/Config.java
+++ b/core/api/src/main/java/org/onosproject/net/config/Config.java
@@ -52,6 +52,7 @@
 
     private static final String TRUE_LITERAL = "true";
     private static final String FALSE_LITERAL = "false";
+    private static final String EMPTY_STRING = "";
 
     protected S subject;
     protected String key;
@@ -440,6 +441,20 @@
     }
 
     /**
+     * Indicates whether the specified field is of a valid length.
+     *
+     * @param field the field to validate
+     * @param maxLength the maximum allowed length of the field
+     * @return true if the field lenth is less than the required length
+     */
+    protected boolean isValidLength(String field, int maxLength) {
+        if (object.path(field).asText(EMPTY_STRING).length() > maxLength) {
+            throw new InvalidFieldException(field, "exceeds maximum length " + maxLength);
+        }
+        return true;
+    }
+
+    /**
      * Returns true if this config contains a field with the given name.
      *
      * @param name the field name
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BandwidthCapacity.java b/core/api/src/main/java/org/onosproject/net/config/basics/BandwidthCapacity.java
index f9f7b3c..e0c43dc 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BandwidthCapacity.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BandwidthCapacity.java
@@ -45,6 +45,9 @@
 
     @Override
     public boolean isValid() {
+        // Validate the capacity
+        capacity();
+
         // Open for extension (adding fields) in the future,
         // must have CAPACITY field.
         return isNumber(CAPACITY, FieldPresence.MANDATORY);
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
index 6fa169e..d193c72 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicDeviceConfig.java
@@ -19,6 +19,8 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.key.DeviceKeyId;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 /**
  * Basic configuration for network infrastructure devices.
  */
@@ -33,12 +35,30 @@
     private static final String SERIAL = "serial";
     private static final String DEVICE_KEY_ID = "deviceKeyId";
 
+    private static final int DRIVER_MAX_LENGTH = 256;
+    private static final int MANUFACTURER_MAX_LENGTH = 256;
+    private static final int HW_VERSION_MAX_LENGTH = 256;
+    private static final int SW_VERSION_MAX_LENGTH = 256;
+    private static final int SERIAL_MAX_LENGTH = 256;
+    private static final int MANAGEMENT_ADDRESS_MAX_LENGTH = 1024;
+
     @Override
     public boolean isValid() {
-        return hasOnlyFields(ALLOWED, NAME, LOC_TYPE, LATITUDE, LONGITUDE,
+        // Validate type/DeviceKeyId
+        type();
+        deviceKeyId();
+
+        return super.isValid()
+                && hasOnlyFields(ALLOWED, NAME, LOC_TYPE, LATITUDE, LONGITUDE,
                 GRID_Y, GRID_X, UI_TYPE, RACK_ADDRESS, OWNER, TYPE, DRIVER,
                 MANUFACTURER, HW_VERSION, SW_VERSION, SERIAL,
-                MANAGEMENT_ADDRESS, DEVICE_KEY_ID);
+                MANAGEMENT_ADDRESS, DEVICE_KEY_ID)
+                && isValidLength(DRIVER, DRIVER_MAX_LENGTH)
+                && isValidLength(MANUFACTURER, MANUFACTURER_MAX_LENGTH)
+                && isValidLength(HW_VERSION, MANUFACTURER_MAX_LENGTH)
+                && isValidLength(SW_VERSION, MANUFACTURER_MAX_LENGTH)
+                && isValidLength(SERIAL, MANUFACTURER_MAX_LENGTH)
+                && isValidLength(MANAGEMENT_ADDRESS, MANAGEMENT_ADDRESS_MAX_LENGTH);
     }
 
     /**
@@ -76,6 +96,8 @@
      * @return self
      */
     public BasicDeviceConfig driver(String driverName) {
+        checkArgument(driverName.length() <= DRIVER_MAX_LENGTH,
+                "driver exceeds maximum length " + DRIVER_MAX_LENGTH);
         return (BasicDeviceConfig) setOrClear(DRIVER, driverName);
     }
 
@@ -95,6 +117,8 @@
      * @return self
      */
     public BasicDeviceConfig manufacturer(String manufacturerName) {
+        checkArgument(manufacturerName.length() <= MANUFACTURER_MAX_LENGTH,
+                "manufacturer exceeds maximum length " + MANUFACTURER_MAX_LENGTH);
         return (BasicDeviceConfig) setOrClear(MANUFACTURER, manufacturerName);
     }
 
@@ -114,6 +138,8 @@
      * @return self
      */
     public BasicDeviceConfig hwVersion(String hwVersion) {
+        checkArgument(hwVersion.length() <= HW_VERSION_MAX_LENGTH,
+                "hwVersion exceeds maximum length " + HW_VERSION_MAX_LENGTH);
         return (BasicDeviceConfig) setOrClear(HW_VERSION, hwVersion);
     }
 
@@ -133,6 +159,8 @@
      * @return self
      */
     public BasicDeviceConfig swVersion(String swVersion) {
+        checkArgument(swVersion.length() <= SW_VERSION_MAX_LENGTH,
+                "swVersion exceeds maximum length " + SW_VERSION_MAX_LENGTH);
         return (BasicDeviceConfig) setOrClear(SW_VERSION, swVersion);
     }
 
@@ -152,6 +180,8 @@
      * @return self
      */
     public BasicDeviceConfig serial(String serial) {
+        checkArgument(serial.length() <= SERIAL_MAX_LENGTH,
+                "serial exceeds maximum length " + SERIAL_MAX_LENGTH);
         return (BasicDeviceConfig) setOrClear(SERIAL, serial);
     }
 
@@ -171,6 +201,8 @@
      * @return self
      */
     public BasicDeviceConfig managementAddress(String managementAddress) {
+        checkArgument(managementAddress.length() <= MANAGEMENT_ADDRESS_MAX_LENGTH,
+                "serialNumber exceeds maximum length " + MANAGEMENT_ADDRESS_MAX_LENGTH);
         return (BasicDeviceConfig) setOrClear(MANAGEMENT_ADDRESS, managementAddress);
     }
 
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
index 1d18e80..8846832 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicElementConfig.java
@@ -76,6 +76,12 @@
     private static final String LOC_TYPE_GEO = "geo";
     private static final String LOC_TYPE_GRID = "grid";
 
+    private static final int NAME_MAX_LENGTH = 256;
+    private static final int UI_TYPE_MAX_LENGTH = 128;
+    private static final int LOC_TYPE_MAX_LENGTH = 32;
+    private static final int RACK_ADDRESS_MAX_LENGTH = 256;
+    private static final int OWNER_MAX_LENGTH = 128;
+
     /**
      * Returns friendly label for the element. If not set, returns the
      * element identifier.
@@ -284,4 +290,12 @@
         return (BasicElementConfig) setOrClear(OWNER, owner);
     }
 
+    @Override
+    public boolean isValid() {
+        return isValidLength(NAME, NAME_MAX_LENGTH)
+                && isValidLength(UI_TYPE, UI_TYPE_MAX_LENGTH)
+                && isValidLength(LOC_TYPE, LOC_TYPE_MAX_LENGTH)
+                && isValidLength(RACK_ADDRESS, RACK_ADDRESS_MAX_LENGTH)
+                && isValidLength(OWNER, OWNER_MAX_LENGTH);
+    }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
index 7e6af79..1fdd320 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
@@ -46,6 +46,9 @@
 
     @Override
     public boolean isValid() {
+        // Validate type/devices
+        type();
+
         return hasOnlyFields(ALLOWED, TYPE, METRIC, LATENCY, BANDWIDTH, IS_DURABLE, IS_BIDIRECTIONAL) &&
                 isBoolean(ALLOWED, OPTIONAL) && isNumber(METRIC, OPTIONAL) &&
                 isNumber(LATENCY, OPTIONAL) && isNumber(BANDWIDTH, OPTIONAL) &&
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java
index 7a0e8d6..da75092 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicRegionConfig.java
@@ -45,11 +45,15 @@
     private static final String LAT_OR_Y = "latOrY";
     private static final String LONG_OR_X = "LongOrX";
 
-
     @Override
     public boolean isValid() {
-        return hasOnlyFields(ALLOWED, NAME, LATITUDE, LONGITUDE, UI_TYPE,
-                             RACK_ADDRESS, OWNER, TYPE, DEVICES, LOC_IN_PEERS);
+        // Validate type/devices
+        type();
+        devices();
+
+        return super.isValid()
+                && hasOnlyFields(ALLOWED, NAME, LATITUDE, LONGITUDE, UI_TYPE,
+                RACK_ADDRESS, OWNER, TYPE, DEVICES, LOC_IN_PEERS);
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java
index 4091f4e..92533a3 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicUiTopoLayoutConfig.java
@@ -54,14 +54,23 @@
     private static final String E_GEOMAP_ALREADY_SET =
             "Can't set sprites when geomap is already set";
 
+    private static final int GEOMAP_MAX_LENGTH = 128;
+    private static final int SPRITES_MAX_LENGTH = 128;
+
     @Override
     public boolean isValid() {
         if (object.has(GEOMAP) && object.has(SPRITES)) {
             throw new InvalidFieldException(GEOMAP, E_GEOMAP_SPRITE);
         }
 
+        // Validate the region and parent
+        region();
+        parent();
+
         return hasOnlyFields(REGION, PARENT, GEOMAP, SPRITES, SCALE,
-                OFFSET_X, OFFSET_Y);
+                OFFSET_X, OFFSET_Y)
+                && isValidLength(GEOMAP, GEOMAP_MAX_LENGTH)
+                && isValidLength(SPRITES, SPRITES_MAX_LENGTH);
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/PortAnnotationConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/PortAnnotationConfig.java
index 7c4b3be..a08b057 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/PortAnnotationConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/PortAnnotationConfig.java
@@ -21,6 +21,7 @@
 import java.util.Map;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.config.BaseConfig;
+import org.onosproject.net.config.InvalidFieldException;
 import org.slf4j.Logger;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -47,8 +48,24 @@
 
     private final Logger log = getLogger(getClass());
 
+    private static final int KEY_MAX_LENGTH = 1024;
+    private static final int VALUE_MAX_LENGTH = 1024;
+
     @Override
     public boolean isValid() {
+        JsonNode jsonNode = object.path(ENTRIES);
+        if (jsonNode.isObject()) {
+            jsonNode.fields().forEachRemaining(entry -> {
+                if (entry.getKey().length() > KEY_MAX_LENGTH) {
+                    throw new InvalidFieldException(entry.getKey(),
+                            entry.getKey() + " exceeds maximum length " + KEY_MAX_LENGTH);
+                }
+                if (entry.getValue().asText("").length() > VALUE_MAX_LENGTH) {
+                    throw new InvalidFieldException(entry.getKey(),
+                            entry.getKey() + " exceeds maximum length " + VALUE_MAX_LENGTH);
+                }
+            });
+        }
         return hasField(ENTRIES) && object.get(ENTRIES).isObject();
     }
 
diff --git a/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java b/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
index 0a4c705..4958a29 100644
--- a/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
@@ -22,6 +22,7 @@
 import java.net.URI;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.net.Device.Type;
 import com.google.common.base.Objects;
@@ -31,6 +32,12 @@
  */
 public class DefaultDeviceDescription extends AbstractDescription
         implements DeviceDescription {
+
+    private static final int MANUFACTURER_MAX_LENGTH = 256;
+    private static final int HW_VERSION_MAX_LENGTH = 256;
+    private static final int SW_VERSION_MAX_LENGTH = 256;
+    private static final int SERIAL_NUMBER_MAX_LENGTH = 256;
+
     private final URI uri;
     private final Type type;
     private final String manufacturer;
@@ -81,6 +88,24 @@
         super(annotations);
         this.uri = checkNotNull(uri, "Device URI cannot be null");
         this.type = checkNotNull(type, "Device type cannot be null");
+
+        if (hwVersion != null) {
+            checkArgument(hwVersion.length() <= HW_VERSION_MAX_LENGTH,
+                    "hwVersion exceeds maximum length " + HW_VERSION_MAX_LENGTH);
+        }
+        if (swVersion != null) {
+            checkArgument(swVersion.length() <= SW_VERSION_MAX_LENGTH,
+                    "swVersion exceeds maximum length " + SW_VERSION_MAX_LENGTH);
+        }
+        if (manufacturer != null) {
+            checkArgument(manufacturer.length() <= MANUFACTURER_MAX_LENGTH,
+                    "manufacturer exceeds maximum length " + MANUFACTURER_MAX_LENGTH);
+        }
+        if (serialNumber != null) {
+            checkArgument(serialNumber.length() <= SERIAL_NUMBER_MAX_LENGTH,
+                    "serialNumber exceeds maximum length " + SERIAL_NUMBER_MAX_LENGTH);
+        }
+
         this.manufacturer = manufacturer;
         this.hwVersion = hwVersion;
         this.swVersion = swVersion;