Improve NormalizedNodeInputStreamReader defensiveness 88/80888/2
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 15 Mar 2019 11:20:24 +0000 (12:20 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 15 Mar 2019 11:28:57 +0000 (12:28 +0100)
If face of corrupted streams, for example due to CONTROLLER-1752,
we can end up interpreting unknown bytes as null strings, potentially
corrupting data.

This patch uses explicit type dispatch and detects wrong string
value types, as well as rejecting unknown string value codes.

Change-Id: Ic2e7887bc1d32a1dc7a364d1bff195752edd762d
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/datastore/node/utils/stream/NormalizedNodeInputStreamReader.java

index 428a578e808950a0d445708be7b74579529f65ed..0ea2fe7f97d530842e1bfd5aa4fc0309a10bb425 100755 (executable)
@@ -254,16 +254,24 @@ public class NormalizedNodeInputStreamReader implements NormalizedNodeDataInput
 
 
     private String readCodedString() throws IOException {
 
 
     private String readCodedString() throws IOException {
-        byte valueType = input.readByte();
-        if (valueType == TokenTypes.IS_CODE_VALUE) {
-            return codedStringMap.get(input.readInt());
-        } else if (valueType == TokenTypes.IS_STRING_VALUE) {
-            String value = input.readUTF().intern();
-            codedStringMap.put(codedStringMap.size(), value);
-            return value;
+        final byte valueType = input.readByte();
+        switch (valueType) {
+            case TokenTypes.IS_NULL_VALUE:
+                return null;
+            case TokenTypes.IS_CODE_VALUE:
+                final int code = input.readInt();
+                final String lookup = codedStringMap.get(code);
+                if (lookup == null) {
+                    throw new IOException("String code " + code + " was not found");
+                }
+                return lookup;
+            case TokenTypes.IS_STRING_VALUE:
+                final String value = input.readUTF().intern();
+                codedStringMap.put(codedStringMap.size(), value);
+                return value;
+            default:
+                throw new IOException("Unhandled string value type " + valueType);
         }
         }
-
-        return null;
     }
 
     private Set<QName> readQNameSet() throws IOException {
     }
 
     private Set<QName> readQNameSet() throws IOException {