Skip to content

Commit

Permalink
Bug: read overflow in 'l_strcmp'
Browse files Browse the repository at this point in the history
Equality according to 'strcoll' does not imply that strings have
the same length.
  • Loading branch information
roberto-ieru committed Jun 14, 2023
1 parent 9be74cc commit f623b96
Showing 1 changed file with 20 additions and 18 deletions.
38 changes: 20 additions & 18 deletions lvm.c
Expand Up @@ -366,30 +366,32 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,


/*
** Compare two strings 'ls' x 'rs', returning an integer less-equal-
** -greater than zero if 'ls' is less-equal-greater than 'rs'.
** Compare two strings 'ts1' x 'ts2', returning an integer less-equal-
** -greater than zero if 'ts1' is less-equal-greater than 'ts2'.
** The code is a little tricky because it allows '\0' in the strings
** and it uses 'strcoll' (to respect locales) for each segments
** of the strings.
** and it uses 'strcoll' (to respect locales) for each segment
** of the strings. Note that segments can compare equal but still
** have different lengths.
*/
static int l_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
size_t ll = tsslen(ls);
const char *r = getstr(rs);
size_t lr = tsslen(rs);
static int l_strcmp (const TString *ts1, const TString *ts2) {
const char *s1 = getstr(ts1);
size_t rl1 = tsslen(ts1); /* real length */
const char *s2 = getstr(ts2);
size_t rl2 = tsslen(ts2);
for (;;) { /* for each segment */
int temp = strcoll(l, r);
int temp = strcoll(s1, s2);
if (temp != 0) /* not equal? */
return temp; /* done */
else { /* strings are equal up to a '\0' */
size_t len = strlen(l); /* index of first '\0' in both strings */
if (len == lr) /* 'rs' is finished? */
return (len == ll) ? 0 : 1; /* check 'ls' */
else if (len == ll) /* 'ls' is finished? */
return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */
/* both strings longer than 'len'; go on comparing after the '\0' */
len++;
l += len; ll -= len; r += len; lr -= len;
size_t zl1 = strlen(s1); /* index of first '\0' in 's1' */
size_t zl2 = strlen(s2); /* index of first '\0' in 's2' */
if (zl2 == rl2) /* 's2' is finished? */
return (zl1 == rl1) ? 0 : 1; /* check 's1' */
else if (zl1 == rl1) /* 's1' is finished? */
return -1; /* 's1' is less than 's2' ('s2' is not finished) */
/* both strings longer than 'zl'; go on comparing after the '\0' */
zl1++; zl2++;
s1 += zl1; rl1 -= zl1; s2 += zl2; rl2 -= zl2;
}
}
}
Expand Down

0 comments on commit f623b96

Please sign in to comment.