Skip to content

Conversation

@om4rrr
Copy link

@om4rrr om4rrr commented Jan 6, 2026

Fix

This PR makes arithmetic conversions in ov::Any safe by rejecting invalid integral casts that previously produced silent wraparound or truncation.

  • When the stored value is a signed integral and the target type is an unsigned integral, ov::Any::as<T>() now throws if the value is negative (e.g., -1 can no longer become 4294967295).
  • For integral-to-integral conversions, ov::Any::as<T>() now performs range checks using std::numeric_limits<T> and throws ov::Exception if the value does not fit in the requested type.
  • Conversions where the stored type already matches the requested type, and the existing string-parsing path for readable types, are unchanged.

Tests

  • Verified manually with a small standalone program that ov::Any{-1}.as<uint32_t>() now throws instead of returning a wrapped unsigned value.
  • Added regression test in src/core/tests/any.cpp (AnyTests.AnyAsUnsignedRejectsNegative) to ensure negative signed values don’t silently wrap when converted to unsigned (e.g., -1 -> 4294967295).
  • Ran: ov_core_unit_tests --gtest_filter='*AnyAsUnsignedRejectsNegative*'

Copilot AI review requested due to automatic review settings January 6, 2026 15:28
@om4rrr om4rrr requested a review from a team as a code owner January 6, 2026 15:28
@github-actions github-actions bot added category: Core OpenVINO Core (aka ngraph) category: CPP API OpenVINO CPP API bindings labels Jan 6, 2026
@sys-openvino-ci sys-openvino-ci added the ExternalPR External contributor label Jan 6, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances type safety in ov::Any conversions by adding validation for integral type conversions that could result in data loss or unexpected wraparound. The changes prevent silent errors like converting -1 to 4294967295 when casting from signed to unsigned types.

  • Adds range checking for signed-to-unsigned and unsigned-to-signed integral conversions
  • Rejects negative signed values when converting to unsigned types
  • Validates that values fit within target type's numeric limits before conversion

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1017 to +1024
if (std::is_signed<T>::value) {
if (value > static_cast<unsigned long long>(std::numeric_limits<T>::max())) {
OPENVINO_THROW("Bad cast (out of range) from ", value, " to: ", typeid(T).name());
}
} else {
if (value > static_cast<unsigned long long>(std::numeric_limits<T>::max())) {
OPENVINO_THROW("Bad cast (out of range) from ", value, " to: ", typeid(T).name());
}
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if-else branches for signed vs unsigned target types perform identical checks. Both branches check if the value exceeds the maximum limit of the target type. These branches can be consolidated into a single check that applies to both signed and unsigned target types, reducing code duplication.

Suggested change
if (std::is_signed<T>::value) {
if (value > static_cast<unsigned long long>(std::numeric_limits<T>::max())) {
OPENVINO_THROW("Bad cast (out of range) from ", value, " to: ", typeid(T).name());
}
} else {
if (value > static_cast<unsigned long long>(std::numeric_limits<T>::max())) {
OPENVINO_THROW("Bad cast (out of range) from ", value, " to: ", typeid(T).name());
}
if (value > static_cast<unsigned long long>(std::numeric_limits<T>::max())) {
OPENVINO_THROW("Bad cast (out of range) from ", value, " to: ", typeid(T).name());

Copilot uses AI. Check for mistakes.
if (std::is_integral<T>::value) {
if (std::is_unsigned<T>::value) {
if (value < 0) {
OPENVINO_THROW("Bad cast from signed negative value to unsigned: ", value);
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message format is inconsistent with the other error messages in this function. Other range check failures use the format "Bad cast (out of range) from VALUE to: TYPE" (lines 1003, 1008, 1019, 1023), but this message uses a different format. Consider using the consistent format: "Bad cast (out of range) from [value] to: [type]" for uniformity.

Suggested change
OPENVINO_THROW("Bad cast from signed negative value to unsigned: ", value);
OPENVINO_THROW("Bad cast (out of range) from ", value, " to: ", typeid(T).name());

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: Core OpenVINO Core (aka ngraph) category: CPP API OpenVINO CPP API bindings ExternalPR External contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants