8272594: Better record of recordings

Reviewed-by: evergizova
Backport-of: 44d9bf6d4afac7b17273b0de1189f3487c1a22f7
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/ParserFactory.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/ParserFactory.java
index 4064e88..d4e3610 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/ParserFactory.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/ParserFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -263,6 +263,7 @@
         @Override
         public Object parse(RecordingInput input) throws IOException {
             final int size = input.readInt();
+            input.require(size, "Array size %d exceeds available data" );
             final Object[] array = new Object[size];
             for (int i = 0; i < size; i++) {
                 array[i] = elementParser.parse(input);
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java
index 481e370..6847189 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataReader.java
@@ -49,6 +49,7 @@
 import jdk.jfr.SettingDescriptor;
 import jdk.jfr.ValueDescriptor;
 import jdk.jfr.internal.MetadataDescriptor.Element;
+import jdk.jfr.internal.consumer.RecordingInput;
 
 /**
  * Parses metadata.
@@ -64,6 +65,7 @@
     public MetadataReader(DataInput input) throws IOException {
         this.input = input;
         int size = input.readInt();
+        ((RecordingInput)input).require(size, "Metadata string pool size %d exceeds available data" );
         this.pool = new ArrayList<>(size);
         for (int i = 0; i < size; i++) {
             this.pool.add(input.readUTF());
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java
index b766894..01adcfe 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInput.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -256,6 +256,7 @@
             return "";
         }
         int size = readInt();
+        require(size, "String size %d exceeds available data");
         if (encoding == STRING_ENCODING_CHAR_ARRAY) {
             char[] c = new char[size];
             for (int i = 0; i < size; i++) {
@@ -336,4 +337,13 @@
         int b8 = readByte(); // read last byte raw
         return ret + (((long) (b8 & 0XFF)) << 56);
     }
+
+    // Purpose of this method is to prevent OOM by sanity check
+    // the minimum required number of bytes against what is available in
+    // segment/chunk/file
+    public void require(int minimumBytes, String errorMessage) throws IOException {
+        if (position + minimumBytes > size) {
+            throw new IOException(String.format(errorMessage, minimumBytes));
+        }
+    }
 }