Skip to content

Commit

Permalink
Fix AIOOBE when reading more data from a file than indicated by file …
Browse files Browse the repository at this point in the history
…header

git-svn-id: https://josm.openstreetmap.de/osmsvn/applications/editors/josm/plugins@36160 b9d5c4c9-76e1-0310-9c85-f3177eceb1e4
  • Loading branch information
taylor.smock committed Oct 5, 2023
1 parent d963a33 commit dc2819a
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.openstreetmap.josm.plugins.fit.lib.records.internal.FitRecordHeader;
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;

/**
Expand All @@ -47,20 +48,22 @@ private FitReader() {
* exception.
*/
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);
final var fitData = new ArrayList<FitData>();
try {
final var header = readFitHeader(bufferedInputStream);
final var headerSize = bufferedInputStream.bytesRead();
bufferedInputStream.mark(1);
var localMessageHeaders = new FitDefinitionMessage[1];
var developerData = new FitDeveloperFieldDescriptionMessage[0];
long lastTimeStamp = Long.MIN_VALUE;
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);
if (nextRecordHeader instanceof FitRecordNormalHeader normalHeader) {
Expand Down Expand Up @@ -124,7 +127,7 @@ public static FitData[] read(InputStream inputStream, FitReaderOptions... option
}
} catch (FitException fitException) {
handleException(optionsSet, fitException);
} catch (IOException ioException) {
} catch (IllegalArgumentException | IOException ioException) {
handleException(optionsSet, new FitException(ioException));
}
return fitData.toArray(EMPTY_FIT_DATA_ARRAY);
Expand Down Expand Up @@ -198,7 +201,7 @@ static FitDefinitionMessage readNextDefinition(FitRecordNormalHeader normalHeade
final boolean littleEndian = inputStream.read() == 0; // 0 = little endian, 1 == big endian
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));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}

0 comments on commit dc2819a

Please sign in to comment.