Skip to content

Commit 9333582

Browse files
authored
Verify blob version for cached model (#32940)
### Details: - Add c++ struct to store openvino build version. Add a build number parser. - Parse compiled blob version and compare it with runtime version - Add tests ### Tickets: - CVS-176170 - CVS-176185
1 parent d01919d commit 9333582

File tree

4 files changed

+599
-5
lines changed

4 files changed

+599
-5
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Copyright (C) 2018-2026 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
#pragma once
5+
6+
#include <limits>
7+
#include <regex>
8+
#include <sstream>
9+
#include <stdexcept>
10+
#include <string>
11+
#include <string_view>
12+
13+
#include "openvino/core/except.hpp"
14+
15+
namespace ov::util {
16+
/**
17+
* @brief Represents OpenVINO version with major, minor, patch, tweak, and build numbers.
18+
*
19+
* This structure parses and stores version information following the pattern:
20+
* MAJOR.MINOR.PATCH[.TWEAK]-BUILD-...
21+
* or a standalone build number.
22+
*
23+
* The version components can be compared using standard comparison operators.
24+
*/
25+
struct Version {
26+
size_t major = 0;
27+
size_t minor = 0;
28+
size_t patch = 0;
29+
size_t tweak = 0;
30+
size_t build = 0;
31+
32+
explicit Version(const char* version_str) {
33+
// Pattern: MAJOR.MINOR.PATCH[.TWEAK]-BUILD-...
34+
std::regex full_pattern(R"(^([0-9]+)\.([0-9]+)\.([0-9]+)(?:\.([0-9]+))?\-([0-9]+)\-.*)");
35+
std::regex build_only_pattern(R"(^[0-9]+$)");
36+
std::cmatch match;
37+
38+
if (std::regex_match(version_str, match, full_pattern)) {
39+
major = std::stoi(match[1].str());
40+
minor = std::stoi(match[2].str());
41+
patch = std::stoi(match[3].str());
42+
43+
// match[4] is the entire optional group (\.TWEAK), match[5] is TWEAK
44+
// the 4th version number is not used in OpenVINO, but used in OpenVINO extensions
45+
if (match[4].matched) {
46+
tweak = std::stoi(match[4].str());
47+
}
48+
49+
build = std::stoi(match[5].str());
50+
} else if (std::regex_match(version_str, build_only_pattern)) {
51+
// Parse as just a build number
52+
build = std::stoi(version_str);
53+
} else {
54+
OPENVINO_THROW("Failed to parse version: ", version_str);
55+
}
56+
}
57+
58+
explicit Version(std::string_view version_str) : Version(version_str.data()) {}
59+
60+
// Comparison operators
61+
bool operator==(const Version& other) const {
62+
return std::tie(major, minor, patch, tweak, build) ==
63+
std::tie(other.major, other.minor, other.patch, other.tweak, other.build);
64+
}
65+
66+
bool operator!=(const Version& other) const {
67+
return !(*this == other);
68+
}
69+
70+
bool operator<(const Version& other) const {
71+
return std::tie(major, minor, patch, tweak, build) <
72+
std::tie(other.major, other.minor, other.patch, other.tweak, other.build);
73+
}
74+
75+
bool operator>(const Version& other) const {
76+
return other < *this;
77+
}
78+
79+
bool operator<=(const Version& other) const {
80+
return !(other < *this);
81+
}
82+
83+
bool operator>=(const Version& other) const {
84+
return !(*this < other);
85+
}
86+
};
87+
88+
/**
89+
* @brief Policy for determining version compatibility between two versions.
90+
*
91+
* This structure defines the maximum allowed difference for each version component.
92+
* By default, all differences are allowed.
93+
*/
94+
struct VersionCompatibilityPolicy {
95+
size_t max_major_diff = std::numeric_limits<size_t>::max();
96+
size_t max_minor_diff = std::numeric_limits<size_t>::max();
97+
size_t max_patch_diff = std::numeric_limits<size_t>::max();
98+
size_t max_tweak_diff = std::numeric_limits<size_t>::max();
99+
size_t max_build_diff = std::numeric_limits<size_t>::max();
100+
};
101+
102+
/**
103+
* @brief Checks if two versions are compatible based on the given policy.
104+
*
105+
* This function determines whether an older version is compatible with a newer version
106+
* by checking if the difference in each version component (major, minor, patch, tweak, build)
107+
* is within the limits specified by the compatibility policy.
108+
*
109+
* @param older_version The older version to check compatibility for.
110+
* @param newer_version The newer version to compare against.
111+
* @param policy The compatibility policy defining maximum allowed differences for each version component.
112+
* Default policy allows all differences.
113+
* @return true if the versions are compatible according to the policy, false otherwise.
114+
* Returns false if older_version is actually greater than newer_version.
115+
*/
116+
inline bool is_version_compatible(const Version& older_version,
117+
const Version& newer_version,
118+
const VersionCompatibilityPolicy& policy = {}) {
119+
if (older_version > newer_version) {
120+
return false;
121+
}
122+
123+
// Check each version component against policy
124+
if (newer_version.major - older_version.major > policy.max_major_diff) {
125+
return false;
126+
}
127+
128+
if (newer_version.minor - older_version.minor > policy.max_minor_diff) {
129+
return false;
130+
}
131+
132+
if (newer_version.patch - older_version.patch > policy.max_patch_diff) {
133+
return false;
134+
}
135+
136+
if (newer_version.tweak - older_version.tweak > policy.max_tweak_diff) {
137+
return false;
138+
}
139+
140+
if (newer_version.build - older_version.build > policy.max_build_diff) {
141+
return false;
142+
}
143+
144+
return true;
145+
}
146+
} // namespace ov::util

0 commit comments

Comments
 (0)