1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-09-06 21:07:59 +00:00

Fix dangling pointer and overflow risk in sci2for function

This commit is contained in:
Carles Fernandez
2025-08-08 19:12:00 +02:00
parent 3ba5a3217c
commit c8555b38af

View File

@@ -40,9 +40,9 @@
#include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/local_time/local_time.hpp> #include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/time_zone_base.hpp> #include <boost/date_time/time_zone_base.hpp>
#include <algorithm> // for min and max #include <algorithm> // for min and max, swap
#include <array> #include <array>
#include <cmath> // for floor #include <cmath> // for floor, abs
#include <exception> #include <exception>
#include <iostream> // for cout #include <iostream> // for cout
#include <ostream> #include <ostream>
@@ -549,91 +549,63 @@ std::string& sci2for(std::string& aStr,
std::string::size_type expLen, std::string::size_type expLen,
bool checkSwitch) bool checkSwitch)
{ {
std::string::size_type idx = aStr.find('.', startPos); const auto dotIdx = aStr.find('.', startPos);
int expAdd = 0; if (dotIdx == std::string::npos || dotIdx <= startPos || dotIdx >= (startPos + length - expLen - 1))
std::string exp;
int64_t iexp;
// If checkSwitch is false, always redo the exponential. Otherwise,
// set it to false.
bool redoexp = !checkSwitch;
// Check for decimal place within specified boundaries
if ((idx <= 0) || (idx >= (startPos + length - expLen - 1)))
{ {
// Error: no decimal point in string // Invalid position for decimal point
return aStr; return aStr;
} }
// Here, account for the possibility that there are bool redoExp = !checkSwitch;
// no numbers to the left of the decimal, but do not int expAdd = 0;
// account for the possibility of non-scientific
// notation (more than one digit to the left of the // Swap digit before '.' if exists, e.g., "1.234E5" -> ".1234E6"
// decimal) if (dotIdx > startPos)
if (idx > startPos)
{ {
redoexp = true; redoExp = true;
// Swap digit and decimal. std::swap(aStr[dotIdx], aStr[dotIdx - 1]);
aStr[idx] = aStr[idx - 1];
aStr[idx - 1] = '.';
// Only add one to the exponent if the number is non-zero
if (asDouble(aStr.substr(startPos, length)) != 0.0) if (asDouble(aStr.substr(startPos, length)) != 0.0)
{ {
expAdd = 1; expAdd = 1;
} }
} }
idx = aStr.find('e', startPos); // Find exponent marker ('e' or 'E')
if (idx == std::string::npos) auto expIdx = aStr.find('e', startPos);
if (expIdx == std::string::npos)
{ {
idx = aStr.find('E', startPos); expIdx = aStr.find('E', startPos);
if (idx == std::string::npos) if (expIdx == std::string::npos)
{ {
// Error: no 'e' or 'E' in string"; // No exponent found; not a scientific notation
return aStr;
} }
} }
// Change the exponent character to D normally, or E of checkSwitch is false. // Replace exponent letter: 'D' for Fortran-style, or 'E' if checkSwitch is false
if (checkSwitch) aStr[expIdx] = checkSwitch ? 'D' : 'E';
if (redoExp)
{ {
aStr[idx] = 'D'; std::string expStr = aStr.substr(expIdx + 1);
} int64_t expVal = asInt(expStr) + expAdd;
else
{ // Replace exponent part
aStr[idx] = 'E'; aStr.erase(expIdx + 1);
aStr += (expVal < 0) ? "-" : "+";
aStr += rightJustify(asString(std::abs(expVal)), expLen, '0');
} }
// Change the exponent itself // Ensure leading space for positive values starting with '.'
if (redoexp) if (aStr[startPos] == '.')
{ {
exp = aStr.substr(idx + 1, std::string::npos); aStr.insert(startPos, 1, ' ');
iexp = asInt(exp);
iexp += expAdd;
aStr.erase(idx + 1);
if (iexp < 0)
{
aStr += "-";
iexp -= iexp * 2;
}
else
{
aStr += "+";
} }
aStr += rightJustify(asString(iexp), expLen, '0'); // If checkSwitch is false, always insert a leading 0 before the decimal
} if (!checkSwitch && aStr[startPos + 1] == '.')
// if the number is positive, append a space
// (if it's negative, there's a leading '-'
if (aStr[0] == '.')
{ {
aStr.insert(static_cast<std::string::size_type>(0), 1, ' '); aStr.insert(startPos + 1, 1, '0');
}
// If checkSwitch is false, add on one leading zero to the string
if (!checkSwitch)
{
aStr.insert(static_cast<std::string::size_type>(1), 1, '0');
} }
return aStr; return aStr;