mirror of
https://github.com/lua/lua
synced 2025-03-31 10:02:52 +03:00
Bug: read overflow in 'l_strcmp'
Equality according to 'strcoll' does not imply that strings have the same length.
This commit is contained in:
parent
9be74ccc21
commit
f623b96932
38
lvm.c
38
lvm.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user