@@ -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