summaryrefslogtreecommitdiffstats
path: root/Source/cmSystemTools.cxx
diff options
context:
space:
mode:
authorDavid Gobbi <david.gobbi@gmail.com>2023-02-20 15:59:11 (GMT)
committerBrad King <brad.king@kitware.com>2023-02-20 17:54:43 (GMT)
commitaa86e8ddfd6b9dc12e54aeb7e5b5c1503c272c42 (patch)
tree0a1b71b1a30b144a97d6f54647f6507b67a1f152 /Source/cmSystemTools.cxx
parent7e730d8f7f7af927a52cd1b7668c64b4c82daa4a (diff)
downloadCMake-aa86e8ddfd6b9dc12e54aeb7e5b5c1503c272c42.zip
CMake-aa86e8ddfd6b9dc12e54aeb7e5b5c1503c272c42.tar.gz
CMake-aa86e8ddfd6b9dc12e54aeb7e5b5c1503c272c42.tar.bz2
Remove component size limit for version comparisons
The VersionCompare() function converted version components to 'unsigned long' prior to comparing them. Any version components too large for 'unsigned long' were treated as equal to ULONG_MAX. This impacted operators like VERSION_GREATER, VERSION_LESS, and VERSION_EQUAL. The new code does not limit the length of the version components for valid comparisons.
Diffstat (limited to 'Source/cmSystemTools.cxx')
-rw-r--r--Source/cmSystemTools.cxx35
1 files changed, 28 insertions, 7 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index f34e35f..3d61270 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -3197,20 +3197,41 @@ bool VersionCompare(cmSystemTools::CompareOp op, const char* lhss,
{
const char* endl = lhss;
const char* endr = rhss;
- unsigned long lhs;
- unsigned long rhs;
while (((*endl >= '0') && (*endl <= '9')) ||
((*endr >= '0') && (*endr <= '9'))) {
- // Do component-wise comparison.
- lhs = strtoul(endl, const_cast<char**>(&endl), 10);
- rhs = strtoul(endr, const_cast<char**>(&endr), 10);
+ // Do component-wise comparison, ignoring leading zeros
+ // (components are treated as integers, not as mantissas)
+ while (*endl == '0') {
+ endl++;
+ }
+ while (*endr == '0') {
+ endr++;
+ }
+
+ const char* beginl = endl;
+ const char* beginr = endr;
+
+ // count significant digits
+ while ((*endl >= '0') && (*endl <= '9')) {
+ endl++;
+ }
+ while ((*endr >= '0') && (*endr <= '9')) {
+ endr++;
+ }
+
+ // compare number of digits first
+ ptrdiff_t r = ((endl - beginl) - (endr - beginr));
+ if (r == 0) {
+ // compare the digits if number of digits is equal
+ r = strncmp(beginl, beginr, endl - beginl);
+ }
- if (lhs < rhs) {
+ if (r < 0) {
// lhs < rhs, so true if operation is LESS
return (op & cmSystemTools::OP_LESS) != 0;
}
- if (lhs > rhs) {
+ if (r > 0) {
// lhs > rhs, so true if operation is GREATER
return (op & cmSystemTools::OP_GREATER) != 0;
}