1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-30 22:12:55 +01:00

Garmin: Fix crash on large gpx import

This commit is contained in:
José Rebelo 2024-08-17 14:41:30 +01:00
parent 79c2fc21a4
commit 0e985d5461
2 changed files with 23 additions and 5 deletions

View File

@ -128,7 +128,7 @@ public class FitFile {
if (!canGenerateOutput) if (!canGenerateOutput)
throw new IllegalArgumentException("Generation of previously parsed FIT file not supported."); throw new IllegalArgumentException("Generation of previously parsed FIT file not supported.");
MessageWriter temporary = new MessageWriter(); MessageWriter temporary = new MessageWriter(writer.getLimit());
temporary.setByteOrder(ByteOrder.LITTLE_ENDIAN); temporary.setByteOrder(ByteOrder.LITTLE_ENDIAN);
RecordDefinition prevDefinition = null; RecordDefinition prevDefinition = null;
for (final RecordData rd : dataRecords) { for (final RecordData rd : dataRecords) {
@ -147,7 +147,24 @@ public class FitFile {
} }
public byte[] getOutgoingMessage() { public byte[] getOutgoingMessage() {
final MessageWriter writer = new MessageWriter(); // Compute the worst case scenario buffer size for the fit file
// A ~1.6MB gpx file with ~16k points results in a ~320KB buffer, ~150KB of which get actually used
final int dataRecordsSize = dataRecords.stream()
.mapToInt(r -> {
// Worst case scenario, for each data record
// one distinct record definition: 5 bytes + (number of field definitions * 3 + 1)
final List<FieldDefinition> definitions = r.getRecordDefinition().getFieldDefinitions();
final int recordDefinitionOverhead = 5 + (definitions != null ? definitions.size() * 3 + 1 : 0);
// 1 + size of the value holder
final int dataRecordOverhead = 1 + r.valueHolder.limit();
return recordDefinitionOverhead + dataRecordOverhead;
}).sum();
// Final size = 14b header + data records + 2b crc
final MessageWriter writer = new MessageWriter(14 + dataRecordsSize + 2);
this.generateOutgoingDataPayload(writer); this.generateOutgoingDataPayload(writer);
return writer.getBytes(); return writer.getBytes();
} }

View File

@ -57,8 +57,6 @@ public class MessageWriter {
final int size = bytes.length; final int size = bytes.length;
if (size > 255) throw new IllegalArgumentException("Too long string"); if (size > 255) throw new IllegalArgumentException("Too long string");
if (byteBuffer.position() + 1 + size > byteBuffer.capacity())
throw new IllegalStateException();
byteBuffer.put((byte) size); byteBuffer.put((byte) size);
byteBuffer.put(bytes); byteBuffer.put(bytes);
} }
@ -76,12 +74,15 @@ public class MessageWriter {
return byteBuffer.position(); return byteBuffer.position();
} }
public int getLimit() {
return byteBuffer.limit();
}
public void writeBytes(byte[] bytes) { public void writeBytes(byte[] bytes) {
writeBytes(bytes, 0, bytes.length); writeBytes(bytes, 0, bytes.length);
} }
public void writeBytes(byte[] bytes, int offset, int size) { public void writeBytes(byte[] bytes, int offset, int size) {
if (byteBuffer.position() + size > byteBuffer.capacity()) throw new IllegalStateException();
byteBuffer.put(Arrays.copyOfRange(bytes, offset, offset + size)); byteBuffer.put(Arrays.copyOfRange(bytes, offset, offset + size));
} }
} }