Index: /applications/editors/josm/plugins/FIT/src/main/java/org/openstreetmap/josm/plugins/fit/lib/FitReader.java
===================================================================
--- /applications/editors/josm/plugins/FIT/src/main/java/org/openstreetmap/josm/plugins/fit/lib/FitReader.java	(revision 36159)
+++ /applications/editors/josm/plugins/FIT/src/main/java/org/openstreetmap/josm/plugins/fit/lib/FitReader.java	(revision 36160)
@@ -27,4 +27,5 @@
 import org.openstreetmap.josm.plugins.fit.lib.records.internal.FitRecordNormalHeader;
 import org.openstreetmap.josm.plugins.fit.lib.records.internal.IField;
+import org.openstreetmap.josm.plugins.fit.lib.utils.CountingInputStream;
 import org.openstreetmap.josm.plugins.fit.lib.utils.NumberUtils;
 
@@ -48,6 +49,6 @@
      */
     public static FitData[] read(InputStream inputStream, FitReaderOptions... options) throws FitException {
-        final var bufferedInputStream = inputStream.markSupported() ? inputStream
-                : new BufferedInputStream(inputStream);
+        final var bufferedInputStream = new CountingInputStream(
+                inputStream.markSupported() ? inputStream : new BufferedInputStream(inputStream));
         final var optionsSet = options.length == 0 ? EnumSet.noneOf(FitReaderOptions.class)
                 : EnumSet.of(options[0], options);
@@ -55,4 +56,5 @@
         try {
             final var header = readFitHeader(bufferedInputStream);
+            final var headerSize = bufferedInputStream.bytesRead();
             bufferedInputStream.mark(1);
             var localMessageHeaders = new FitDefinitionMessage[1];
@@ -61,5 +63,6 @@
             var offsetAddition = 0;
             byte lastOffset = 0;
-            while (bufferedInputStream.read() != -1) {
+            while (bufferedInputStream.read() != -1
+                    && bufferedInputStream.bytesRead() < header.dataSize() - headerSize) {
                 bufferedInputStream.reset();
                 final var nextRecordHeader = readNextRecordHeader(bufferedInputStream);
@@ -125,5 +128,5 @@
         } catch (FitException fitException) {
             handleException(optionsSet, fitException);
-        } catch (IOException ioException) {
+        } catch (IllegalArgumentException | IOException ioException) {
             handleException(optionsSet, new FitException(ioException));
         }
@@ -199,5 +202,5 @@
         final var globalMessageNumber = NumberUtils.decodeInt(2, littleEndian, inputStream);
         final int numberOfFields = inputStream.read();
-        final var fitFields = new ArrayList<FitField>(numberOfFields);
+        final var fitFields = new ArrayList<FitField>(Math.max(0, numberOfFields));
         for (var i = 0; i < numberOfFields; i++) {
             fitFields.add(readNextField(inputStream));
Index: /applications/editors/josm/plugins/FIT/src/main/java/org/openstreetmap/josm/plugins/fit/lib/utils/CountingInputStream.java
===================================================================
--- /applications/editors/josm/plugins/FIT/src/main/java/org/openstreetmap/josm/plugins/fit/lib/utils/CountingInputStream.java	(revision 36160)
+++ /applications/editors/josm/plugins/FIT/src/main/java/org/openstreetmap/josm/plugins/fit/lib/utils/CountingInputStream.java	(revision 36160)
@@ -0,0 +1,121 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.fit.lib.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Count the bytes read from a stream
+ */
+public class CountingInputStream extends InputStream {
+    private final InputStream inputStream;
+    private long bytesRead;
+    private long mark;
+
+    /**
+     * Create a new {@link CountingInputStream}
+     * @param inputStream The stream to count bytes read from
+     */
+    public CountingInputStream(InputStream inputStream) {
+        this.inputStream = inputStream;
+    }
+
+    @Override
+    public int read() throws IOException {
+        final var read = this.inputStream.read();
+        if (read != -1) {
+            bytesRead++;
+        }
+        return read;
+    }
+
+    /**
+     * Get the number of bytes read
+     * @return The bytes read
+     */
+    public long bytesRead() {
+        return this.bytesRead;
+    }
+
+    @Override
+    public int read(byte[] bytes) throws IOException {
+        final int read = this.inputStream.read(bytes);
+        if (read != -1) {
+            this.bytesRead += read;
+        }
+        return read;
+    }
+
+    @Override
+    public int read(byte[] bytes, int off, int len) throws IOException {
+        final int read = this.inputStream.read(bytes, off, len);
+        if (read != -1) {
+            this.bytesRead += read;
+        }
+        return read;
+    }
+
+    @Override
+    public byte[] readAllBytes() throws IOException {
+        final var allBytes = this.inputStream.readAllBytes();
+        this.bytesRead += allBytes.length;
+        return allBytes;
+    }
+
+    @Override
+    public byte[] readNBytes(int len) throws IOException {
+        final var nBytes = this.inputStream.readNBytes(len);
+        this.bytesRead += nBytes.length;
+        return nBytes;
+    }
+
+    @Override
+    public int readNBytes(byte[] b, int off, int len) throws IOException {
+        final var read = this.inputStream.readNBytes(b, off, len);
+        if (read != -1) {
+            this.bytesRead += read;
+        }
+        return read;
+    }
+
+    @Override
+    public long skip(long n) throws IOException {
+        final var read = this.inputStream.skip(n);
+        this.bytesRead += read;
+        return read;
+    }
+
+    @Override
+    public void skipNBytes(long n) throws IOException {
+        this.inputStream.skipNBytes(n);
+        this.bytesRead += n; // This might not be accurate...
+    }
+
+    @Override
+    public int available() throws IOException {
+        return this.inputStream.available();
+    }
+
+    @Override
+    public void close() throws IOException {
+        super.close();
+        this.inputStream.close();
+    }
+
+    @Override
+    public void mark(int readlimit) {
+        this.inputStream.mark(readlimit);
+        this.mark = this.bytesRead;
+    }
+
+    @Override
+    public void reset() throws IOException {
+        this.inputStream.reset();
+        this.bytesRead = this.mark;
+    }
+
+    @Override
+    public boolean markSupported() {
+        return this.inputStream.markSupported();
+    }
+}
