Reduce burden of base64 validation
@@ -1337,12 +1337,22 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
if (type.equals("base64Binary")) {
- try {
- byte[] b = Base64.getDecoder().decode(StringUtils.deleteWhitespace(e.primitiveValue()));
- } catch (IllegalArgumentException ex) {
- rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, "The value (snip) is not a valid Base64 value: "+ex.getMessage());
+ String encoded = e.primitiveValue();
+ if (isNotBlank(encoded)) {
+ /*
+ * Note: Regex comes from: https://stackoverflow.com/questions/8571501/how-to-check-whether-the-string-is-base64-encoded-or-not
+ *
+ * Technically this is not bulletproof as some invalid base64 won't be caught,
+ * but I think it's good enough. The original code used Java8 Base64 decoder
+ * but I've replaced it with a regex for 2 reasons:
+ * 1. This code will run on any version of Java
+ * 2. This code doesn't actually decode, which is much easier on memory use for big payloads
+ */
+ if (!encoded.matches("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$")) {
+ String value = encoded.length() < 100 ? encoded : "(snip)";
+ rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, "The value \"{0}\" is not a valid Base64 value", value);
+ }
}
-
}
if (type.equals("integer") || type.equals("unsignedInt") || type.equals("positiveInt")) {
if (rule(errors, IssueType.INVALID, e.line(), e.col(), path, Utilities.isInteger(e.primitiveValue()), "The value '" + e.primitiveValue() + "' is not a valid integer")) {
