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:
@@ -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;
|
||||||
|
Reference in New Issue
Block a user