Skip to content

Poco::Dynamic::Var conversion to floating point does not handle precision checks correctly for negative numbers. #4886

@MduPlessis-1

Description

@MduPlessis-1

Describe the bug
When converting a negative integer to a floating point value, a Poco::RangeException is trown for values that do not lose precision when converted to float/double. This seems to be a bug in Dynamic/VarHolder.h::numValDigits, called from isPrecisionLost in the same file:

template <typename T, std::enable_if_t<std::is_integral_v<T>, bool> = true>
static constexpr int numValDigits(const T& value)
{
	using U = std::make_unsigned_t<T>;
	if (value == 0) return 0;
	int digitCount = 0;
	U locVal = value; // to prevent sign preservation
	while (locVal >>= 1) ++digitCount;
	return digitCount;
}

The line U locVal = value; // to prevent sign preservation assigns the two's compliment value to locVal, and as such does not return the correct number of significant digits.

To Reproduce

#include "Poco/Dynamic/Var.h"

int main(void)
{
  Poco::Dynamic::Var value = (int64_t)-10;
  double             answer = value.convert<double>();
  return (0);
}

Running this code results in:

terminate called after throwing an instance of 'Poco::RangeException'
  what():  Out of range

Expected behavior
The value stored in the Poco:Dynamic::Var should be converted to the equivalent double value if the original value fits within a double without precision loss and not throw an unnecessary exception. In the above example, -10 should be stored in the answer variable.

Logs
n/a

Screenshots
n/a

Please add relevant environment information:

  • OS: Debian 12 (more specifically the vscode Debian c++ development container mcr.microsoft.com/vscode/devcontainers/cpp:1.2.7-debian-12)
  • POCO Version: 1.14.1

Additional context
n/a

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

Done

Relationships

None yet

Development

No branches or pull requests

Issue actions