- 主题:报告ucache.c的一个bug
[症状]
版面u查询网友,输入archmagi,按空格,列出匹配的使用者列表,
没有以该字符串开头的用户。
重新查询网友。输入全称archmagi,回车。这个用户是存在的。
也就是说,匹配用户这项功能有问题。
[原因]
查看libBBS/ucache.c里的u_namecomplete函数。有这样一段:
if (len >= ksz) {
tagv[ksz] = 0;
hash = ucache_hash(tagv) - 1;
for (n = 0; n < UCACHE_HASHBSIZE; n++) {
num = reg_ushm->hashhead[(hash + n % UCACHE_HASHBSIZE)
% UCACHE_HASHSIZE + 1];
while (num) {
if (!strncasecmp(uidshm->passwd[num - 1].userid,
tag, len)) {
strcpy(buf[(*pnum)++], uidshm->passwd[num - 1].userid);
}
num = reg_ushm->next[num - 1];
}
}
}
关键的部分是上面这段里的第三行:ucache_hash(tagv) - 1;
调试表明,对于archmagi,上面的tagv="arc",ucache_hash("arc")=171667。
而 ucache_hash("archmagi")=172041,UCACHE_HASHBSIZE=374。
也就是说,(hash + n % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1
最多只能达到 (171667-1+373)%330000+1=172040,因此archmagi的hash值
不会被探测到,也就找不出这个用户。
[解决方法]
观察ucache_hash函数。根据我的理解,给定userid以后,这个函数先在
hashtable里找前几个字母的bucket number(这是否就是UCACHE_HASHBSIZE
中B的含义?),找到以后赋值给 n1:
n1 = (n1 * UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
我的理解是,把这个userid放到n1这个bucket里,不知道对不对。
最后加一是为了避免 n1=0 从而与无效userid混淆。
然后计算剩余userid的hash值,我的理解是这是该userid在该bucket中的一个
偏移量(n2)。最后赋值给 n1:
n1 = (n1 + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
最后加一也是为了避免返回值为0。
那么这里就出现了一个情况:相同前缀的字符串不一定在一个bucket里,因为
上面两处加了两次1。对于例中archmagi的情况,后面五个字符的hash值正好
是373,于是 H(archmagi)==H(arc)+374, 因此它们不在同一个bucket
中了。这就导致了u_namecomplete没法在arc的bucket里找到archmagi。
我想了一个解决方法是,把
n1 = (n1 + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
改成
n1 = ((n1 - 1) + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
这样就避免了加两次1的毛病。
这个解决方法能够解决archmagi的问题。但是其副作用我尚不清楚。还待前辈指教。
--
FROM 59.66.199.*
很好。。。极类似的patch很久以前已经给过了:p
不过没仔细研究打这个patch是否要完全停共享内存,所以一直没打...
【 在 dvlt (-: :-) 的大作中提到: 】
: [症状]
: 版面u查询网友,输入archmagi,按空格,列出匹配的使用者列表,
: 没有以该字符串开头的用户。
: ...................
--
FROM 61.182.213.*
这个是去年11月我写过的一段:貌似和你的一样也!
上面的第二句话应该改成:
n1 = (n1 - 1 + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
这个bug导致的问题是使用smthbbs的站上有大概1/374的id是不可以通过id补全看到的
【 在 dvlt (-: :-) 的大作中提到: 】
: 那么这里就出现了一个情况:相同前缀的字符串不一定在一个bucket里,因为
: 上面两处加了两次1。对于例中archmagi的情况,后面五个字符的hash值正好
: 是373,于是 H(archmagi)==H(arc)+374, 因此它们不在同一个bucket
: 中了。这就导致了u_namecomplete没法在arc的bucket里找到archmagi。
: 我想了一个解决方法是,把
: n1 = (n1 + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
: 改成
: n1 = ((n1 - 1) + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
: 这样就避免了加两次1的毛病。
: 这个解决方法能够解决archmagi的问题。但是其副作用我尚不清楚。还待前辈指教。
--
FROM 61.182.213.*
同志们,这个 fix 已经被提交进 svn,跟进请注意重启站点
【 在 atppp (Big Mouse) 的大作中提到: 】
: 标 题: Re: 报告ucache.c的一个bug
: 发信站: 水木社区 (Fri Nov 4 17:57:47 2005), 转信
:
: 这个是去年11月我写过的一段:貌似和你的一样也!
:
: 上面的第二句话应该改成:
:
: n1 = (n1 - 1 + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
:
: 这个bug导致的问题是使用smthbbs的站上有大概1/374的id是不可以通过id补全看到的
:
: 【 在 dvlt (-: :-) 的大作中提到: 】
: : 那么这里就出现了一个情况:相同前缀的字符串不一定在一个bucket里,因为
: : 上面两处加了两次1。对于例中archmagi的情况,后面五个字符的hash值正好
: : 是373,于是 H(archmagi)==H(arc)+374, 因此它们不在同一个bucket
: : 中了。这就导致了u_namecomplete没法在arc的bucket里找到archmagi。
: : 我想了一个解决方法是,把
: : n1 = (n1 + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
: : 改成
: : n1 = ((n1 - 1) + n2 % UCACHE_HASHBSIZE) % UCACHE_HASHSIZE + 1;
: : 这样就避免了加两次1的毛病。
: : 这个解决方法能够解决archmagi的问题。但是其副作用我尚不清楚。还待前辈指教。
:
:
: --
: 水木社区凉粉证 0242 号
: ┏^ǒ^*★*^ǒ^*☆*^ǒ^*★*^ǒ^*☆*^ǒ^ ┓
: ┃╭の╮┏┯┓┏┯┓ ┏┯┓┏┯┓ ╬ ┃
: ┃ ╲╱ ┠最┨┠爱┨ ┠靓┨┠颖┨╭║╮┃
: ┃┗恋┛┗┷┛┗┷┛ ┗┷┛┗┷┛ ╲╱ ┃
: ┗^ǒ^*★*^ǒ^*☆*^ǒ^*★*^ǒ^*☆*^ǒ^ ┛
:
:
: ※ 来源:·水木社区 newsmth.net·[FROM: 61.182.213.*]
--
FROM 221.218.129.*
难怪!遇到过这个情况。。
u不到人。
【 在 fancyrabbit (fancy★gradu-fku-ation) 的大作中提到: 】
: 同志们,这个 fix 已经被提交进 svn,跟进请注意重启站点
--
FROM 211.99.222.*
好古老啊。。admire
【 在 fancyrabbit (fancy★gradu-fku-ation) 的大作中提到: 】
: 同志们,这个 fix 已经被提交进 svn,跟进请注意重启站点
--
FROM 211.151.248.*