Skip to content

Commit 9eaae9e

Browse files
committed
Guard ypoo elliptical FTMS parsing against short packets
1 parent 784f67a commit 9eaae9e

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

src/devices/ypooelliptical/ypooelliptical.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,25 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
304304
lastPacket = newvalue;
305305
}
306306

307+
if (lastPacket.length() < 3) {
308+
qDebug() << "packet malformed: too short for FTMS flags" << lastPacket.length();
309+
return;
310+
}
311+
312+
auto ensurePacketBytes = [&](int needed, const char *field) {
313+
if (index + needed > lastPacket.length()) {
314+
qDebug() << "packet malformed while parsing" << field << "index" << index << "needed" << needed << "len" << lastPacket.length();
315+
return false;
316+
}
317+
return true;
318+
};
319+
307320
int index = 0;
308321
Flags.word_flags = (lastPacket.at(2) << 16) | (lastPacket.at(1) << 8) | lastPacket.at(0);
309322
index += 3;
310323

311324
if (!Flags.moreData) {
325+
if (!ensurePacketBytes(2, "instantaneousSpeed")) return;
312326
// For TRUE_ELLIPTICAL, skip instantaneous speed (will use avgSpeed instead)
313327
if(!TRUE_ELLIPTICAL && (E35 || SCH_590E || SCH_411_510E || KETTLER || CARDIOPOWER_EEGO || MYELLIPTICAL || SKANDIKA || DOMYOS || FEIER || MX_AS || FTMS || SOLE_E25)) {
314328
Speed = ((double)(((uint16_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
@@ -321,6 +335,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
321335

322336
// this particular device, seems to send the actual speed here
323337
if (Flags.avgSpeed) {
338+
if (!ensurePacketBytes(2, "avgSpeed")) return;
324339
double avgSpeed = ((double)(((uint16_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
325340
(uint16_t)((uint8_t)lastPacket.at(index)))) /
326341
100.0;
@@ -341,6 +356,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
341356
}
342357

343358
if (Flags.totDistance) {
359+
if (!ensurePacketBytes(3, "totDistance")) return;
344360
if(!E35 && !SCH_590E && !SCH_411_510E && !KETTLER && !CARDIOPOWER_EEGO && !MYELLIPTICAL && !SKANDIKA && !DOMYOS && !FEIER && !MX_AS && !TRUE_ELLIPTICAL && !FTMS && !SOLE_E25) {
345361
Distance = ((double)((((uint32_t)((uint8_t)lastPacket.at(index + 2)) << 16) |
346362
(uint32_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
@@ -359,6 +375,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
359375
emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value()));
360376

361377
if (Flags.stepCount) {
378+
if (!ensurePacketBytes(4, "stepCount")) return;
362379
if (settings.value(QZSettings::cadence_sensor_name, QZSettings::default_cadence_sensor_name)
363380
.toString()
364381
.startsWith(QStringLiteral("Disabled"))) {
@@ -389,6 +406,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
389406
}
390407

391408
if (Flags.strideCount) {
409+
if (!ensurePacketBytes(2, "strideCount")) return;
392410
// Read current stride count (cumulative total)
393411
uint16_t currentStrideCount = ((uint16_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
394412
(uint16_t)((uint8_t)lastPacket.at(index));
@@ -444,6 +462,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
444462
}
445463

446464
if (Flags.rampAngle) {
465+
if (!ensurePacketBytes(4, "rampAngle")) return;
447466
// Read Inclination (first field)
448467
Inclination = (((double)(((uint16_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
449468
(uint16_t)((uint8_t)lastPacket.at(index))))) / 10.0;
@@ -460,6 +479,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
460479
}
461480

462481
if (Flags.resistanceLvl) {
482+
if (!ensurePacketBytes(2, "resistanceLvl")) return;
463483
Resistance = ((double)(((uint16_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
464484
(uint16_t)((uint8_t)lastPacket.at(index))));
465485

@@ -495,6 +515,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
495515
}
496516

497517
if (Flags.instantPower) {
518+
if (!ensurePacketBytes(2, "instantPower")) return;
498519
if (settings.value(QZSettings::power_sensor_name, QZSettings::default_power_sensor_name)
499520
.toString()
500521
.startsWith(QStringLiteral("Disabled"))) {
@@ -515,15 +536,15 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
515536

516537
emit debug(QStringLiteral("Current Watt: ") + QString::number(m_watt.value()));
517538

518-
if (Flags.avgPower && lastPacket.length() > index + 1 && !E35 && !SCH_590E && !SCH_411_510E && !KETTLER && !CARDIOPOWER_EEGO && !MYELLIPTICAL && !SKANDIKA && !DOMYOS && !FEIER && !MX_AS && !FTMS && !SOLE_E25) { // E35 has a bug about this
539+
if (Flags.avgPower && ensurePacketBytes(2, "avgPower") && !E35 && !SCH_590E && !SCH_411_510E && !KETTLER && !CARDIOPOWER_EEGO && !MYELLIPTICAL && !SKANDIKA && !DOMYOS && !FEIER && !MX_AS && !FTMS && !SOLE_E25) { // E35 has a bug about this
519540
double avgPower;
520541
avgPower = ((double)(((uint16_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
521542
(uint16_t)((uint8_t)lastPacket.at(index))));
522543
emit debug(QStringLiteral("Current Average Watt: ") + QString::number(avgPower));
523544
index += 2;
524545
}
525546

526-
if (Flags.expEnergy && lastPacket.length() > index + 1) {
547+
if (Flags.expEnergy && ensurePacketBytes(5, "expEnergy")) {
527548
/*KCal = ((double)(((uint16_t)((uint8_t)lastPacket.at(index + 1)) << 8) |
528549
(uint16_t)((uint8_t)lastPacket.at(index))));*/
529550
index += 2;
@@ -555,7 +576,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
555576
if (SCH_411_510E && lastPacket.length() > 23) {
556577
heartRate((uint8_t)lastPacket.at(23));
557578
emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value()));
558-
} else if (Flags.heartRate && !disable_hr_frommachinery && lastPacket.length() > index) {
579+
} else if (Flags.heartRate && !disable_hr_frommachinery && ensurePacketBytes(1, "heartRate")) {
559580
uint8_t hrValue = (uint8_t)lastPacket.at(index);
560581
// 0xFF means heart rate not available/invalid in FTMS
561582
if(hrValue != 0xFF) {
@@ -571,6 +592,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara
571592
}
572593

573594
if (Flags.metabolicEq) {
595+
if (!ensurePacketBytes(1, "metabolicEq")) return;
574596
// FTMS metabolic equivalent is uint8 with 0.1 resolution
575597
if(E35 || SCH_590E || SCH_411_510E || KETTLER || CARDIOPOWER_EEGO || MYELLIPTICAL || SKANDIKA || DOMYOS || FEIER || MX_AS || TRUE_ELLIPTICAL || FTMS) {
576598
uint8_t metabolicValue = (uint8_t)lastPacket.at(index);

0 commit comments

Comments
 (0)