Don't Overrun Formatting Buffer in 'doub_string_ecl'

We would write outside the allocated buffer, and fail to write the
nul terminator, when presented with inputs of very small size
(denormalized numbers in the order of 1.0e-101 or smaller).  Switch
to using std::snprintf and expand the buffer size to work around
this problem.

While here, also fix a subtle issue in determining whether or not we
should insert the exponent character 'D' into the formatted output.
Since we add one upon formatting the number, we also need to use a
non-symmetric condition for the 'D' character lest we fail to output
correctly formatted versions of

    -2.9440373045442E-100 (=> -0.29440373045442D-99)
    -2.9440373045442E+99  (=> -0.29440373045442+100)
This commit is contained in:
Bård Skaflestad 2020-11-19 10:45:22 +01:00
parent 5338a1dd13
commit cdc1361a03

View File

@ -489,8 +489,8 @@ std::string EclOutput::make_real_string_ix(float value) const
std::string EclOutput::make_doub_string_ecl(double value) const
{
char buffer [21];
std::sprintf (buffer, "%19.13E", value);
char buffer [21 + 1];
std::snprintf (buffer, sizeof buffer, "%19.13E", value);
if (value == 0.0) {
return "0.00000000000000D+00";
@ -507,22 +507,23 @@ std::string EclOutput::make_doub_string_ecl(double value) const
std::string tmpstr(buffer);
int exp = value < 0.0 ? std::stoi(tmpstr.substr(17, 4)) : std::stoi(tmpstr.substr(16, 4));
const bool use_exp_char = (exp >= -100) && (exp < 99);
if (value < 0.0) {
if (std::abs(exp) < 100) {
if (use_exp_char) {
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13) + "D";
} else {
tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13);
}
} else {
if (std::abs(exp) < 100) {
if (use_exp_char) {
tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13) + "D";
} else {
tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13);
}
}
std::sprintf(buffer, "%+03i", exp + 1);
std::snprintf(buffer, sizeof buffer, "%+03i", exp + 1);
tmpstr = tmpstr + buffer;
return tmpstr;
}