avoid numeric overflow in version comparison (Thayne Harbaugh<tharbaug@liberate.com>).
CVS patchset: 3112 CVS date: 1999/06/30 14:18:05
This commit is contained in:
parent
79ba901dfe
commit
c9ba6cba9c
1
CHANGES
1
CHANGES
|
@ -19,6 +19,7 @@
|
|||
- fix: false fingerprint stat cache hit -- "the tetex problem" (#2727).
|
||||
- fix: bsearch needs macro table sorted after undefine. (#3713).
|
||||
- fix: --checksig segfault with odd pgp output (e.g. w/o ~/.pgp) (#3720)
|
||||
- avoid numeric overflow in version comparison (Thayne Harbaugh<tharbaug@liberate.com>).
|
||||
|
||||
3.0 -> 3.0.1
|
||||
- fix: %verifyscript resurrected (Shing-Gene Yung).
|
||||
|
|
45
lib/misc.c
45
lib/misc.c
|
@ -61,14 +61,18 @@ int rpmfileexists(const char * filespec) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* compare alpha and numeric segments of two versions */
|
||||
/* return 1: a is newer than b */
|
||||
/* 0: a and b are the same version */
|
||||
/* -1: b is newer than a */
|
||||
int rpmvercmp(const char * a, const char * b) {
|
||||
int num1, num2;
|
||||
char oldch1, oldch2;
|
||||
char * str1, * str2;
|
||||
char * one, * two;
|
||||
int rc;
|
||||
int isnum;
|
||||
|
||||
/* easy comparison to see if versions are identical */
|
||||
if (!strcmp(a, b)) return 0;
|
||||
|
||||
str1 = alloca(strlen(a) + 1);
|
||||
|
@ -80,6 +84,7 @@ int rpmvercmp(const char * a, const char * b) {
|
|||
one = str1;
|
||||
two = str2;
|
||||
|
||||
/* loop through each version segment of str1 and str2 and compare them */
|
||||
while (*one && *two) {
|
||||
while (*one && !isalnum(*one)) one++;
|
||||
while (*two && !isalnum(*two)) two++;
|
||||
|
@ -87,6 +92,9 @@ int rpmvercmp(const char * a, const char * b) {
|
|||
str1 = one;
|
||||
str2 = two;
|
||||
|
||||
/* grab first completely alpha or completely numeric segment */
|
||||
/* leave one and two pointing to the start of the alpha or numeric */
|
||||
/* segment and walk str1 and str2 to end of segment */
|
||||
if (isdigit(*str1)) {
|
||||
while (*str1 && isdigit(*str1)) str1++;
|
||||
while (*str2 && isdigit(*str2)) str2++;
|
||||
|
@ -97,35 +105,52 @@ int rpmvercmp(const char * a, const char * b) {
|
|||
isnum = 0;
|
||||
}
|
||||
|
||||
/* save character at the end of the alpha or numeric segment */
|
||||
/* so that they can be restored after the comparison */
|
||||
oldch1 = *str1;
|
||||
*str1 = '\0';
|
||||
oldch2 = *str2;
|
||||
*str2 = '\0';
|
||||
|
||||
/* take care of the case where the two version segments are */
|
||||
/* different types: one numeric and one alpha */
|
||||
if (one == str1) return -1; /* arbitrary */
|
||||
if (two == str2) return -1;
|
||||
|
||||
if (isnum) {
|
||||
num1 = atoi(one);
|
||||
num2 = atoi(two);
|
||||
/* this used to be done by converting the digit segments */
|
||||
/* to ints using atoi() - it's changed because long */
|
||||
/* digit segments can overflow an int - this should fix that. */
|
||||
|
||||
/* throw away any leading zeros - it's a number, right? */
|
||||
while (*one == '0') one++;
|
||||
while (*two == '0') two++;
|
||||
|
||||
if (num1 < num2)
|
||||
return -1;
|
||||
else if (num1 > num2)
|
||||
return 1;
|
||||
} else {
|
||||
rc = strcmp(one, two);
|
||||
if (rc) return rc;
|
||||
/* whichever number has more digits wins */
|
||||
if (strlen(one) > strlen(two)) return 1;
|
||||
if (strlen(two) > strlen(one)) return -1;
|
||||
}
|
||||
|
||||
/* strcmp will return which one is greater - even if the two */
|
||||
/* segments are alpha or if they are numeric. don't return */
|
||||
/* if they are equal because there might be more segments to */
|
||||
/* compare */
|
||||
rc = strcmp(one, two);
|
||||
if (rc) return rc;
|
||||
|
||||
/* restore character that was replaced by null above */
|
||||
*str1 = oldch1;
|
||||
one = str1;
|
||||
*str2 = oldch2;
|
||||
two = str2;
|
||||
}
|
||||
|
||||
/* this catches the case where all numeric and alpha segments have */
|
||||
/* compared identically but the segment sepparating characters were */
|
||||
/* different */
|
||||
if ((!*one) && (!*two)) return 0;
|
||||
|
||||
/* whichever version still has characters left over wins */
|
||||
if (!*one) return -1; else return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue