【 以下文字轉載自 Firebird 討論區 】
【 原文由 luzi 所發表 】
(先嘆一口气,今天到3:00am以為可以睡覺了的,突然發現這么
一個BUG,一直弄到4:30才總算搞定,赶緊寫下一篇文章准備向所有有
這個BUG的BBS站站長要XO)
一. 首先測試一下你的BBS站有沒有這個問題
(只有版主權限的可以在本版測試)
1. 最好找一個沒設過文摘的版面來測試,比如test,notpad版
然后按文章順序依次將3篇文章收入文摘,(三篇足夠測試了)
即先g第X篇,再g第X+1篇,再g第X+2篇。
2. 好,現在看看文摘模式,應該依次有第X,X+1,X+2篇文章的標題
3. 回到普通模式,取消第X+1篇文章的文摘標記(再按一下g)
4. 現在再看看文摘模式里的文章,顯示的是第X,X+1的標題
這証明你的BBS系統存在這個BUG
二. 哪里來的BUG
(開始我一直以為是我移植老站代碼到新站造成的,對比了半天相關的新舊代碼,
發現沒有什么不同,于是只好怀疑FB系統的原始代碼了,只是不敢相信這個一個
常用的功能居然存在BUG)
1. 先看看bbs.c里的刪除文摘的函數int dele_digest(dname,direc)
它調用下面這個語句去搜索digest_name(文摘的文件名)在目錄文件new_dir里
的位置,返回相關的fileheader結构給fh,其中cmpfilename是用來比較讀取
到的fileheader->filename与digest_name是否匹配的函數。
search_record(new_dir, &fh, sizeof(fh), cmpfilename, digest_name);
2. 再看看search_record()函數,它每讀取一個fileheader結构就調用
if((*fptr)(farg,rptr)) 去比較异同,在dele_digest的調用中
即等同于調用 comfilename(digest_name,&fh);
3. 再看看comfilename函數
int cmpfilename(struct fileheader *fhdr)
{
if(!strncmp(fhdr->filename,currfile,STRLEN)) return 1 ;
return 0 ;
}
天!居然和第2步調用的接口不一樣。
首先digest_name的定義是 char[STRLEN],而不是srtuct fileheader;
不過好在struct fileheader里的第一個item就是char filename[STRLEN];
在這個函數里歪打正著沒有內存指針錯誤。
但是它比較的卻是digest_name和currentfile,faint..
4. 隙艘艘currentfile岆妦繫陲陲ㄛ涴ヷ岆珨跺擁講﹝
珨眻梑善郔輪珨棒跤currentfile董硉腔華源ㄛ婓dele_digest滲杅爵ㄛ
撈覃蚚search_record()ゴㄛヷ岆珨曆賑儉腔strcpy(currfile,digest_name);
埻懂涴跺comfilename腔賦彆箝隅峈淩ㄛ稱稱ㄛ垀眕search_record殿隙腔硉
嗣圉岆菴珨沭暮翹腔硉﹝
5. 涴繫珨懂ㄛ渣昫憩岆....(嬪賸ㄛ擱腕迡賸 :( )
゙. 賤樵BUG
郔疑腔源楊絞」岆赻撩迡珨跺comfilename腔滲杅懂巠茼search_record()腔覃蚚徽
饒繫饒珨曆strcpy(currentfile,digest_name)岆祥岆憩羶蚚賸儸ˋ
no,no,no,遜岆衄蚚腔ㄛ狟醱delete_file滲杅猁蚚善坳﹝
鍚俋艘賸comfilename腔埭鎢珩憩眭耋徽ㄛ坳掀誕腔岆strncmp(str1,str2,STRLEN)
奧祥奀strcmp()ㄛ垀眕斕郔疑蚚strncpy(currentfile,str,STRLEN);
參bbs.c爵饒虳垀衄蚚strcpy(currentfile,str)腔逄曆飲蜊傖strncpy勘﹝
祥徹疑砓憩岆dele_digest滲杅爵腔猁蜊ㄛ梗腔滲杅飲蚚勤賸ㄛ裞裞
扂忒芛腔FireBird 2.5X, 2.66M唳腔埭鎢飲衄涴跺BUGㄛ砑斛岆珨跺橾BUG(崋繫芼」
砑お賸奠隱眅)
修正FireBird 2.X 刪除文摘功能的BUG
一、在bbs.c里添加下面這段函數代碼
int
cmpdigestfilename(digest_name,fhdr)
char *digest_name;
struct fileheader *fhdr ;
{
if(!strcmp(fhdr->filename,digest_name))
return 1 ;
return 0 ;
} /* comapare file names for dele_digest function. Luzi 99.3.30 */
二、然后用下面的代碼替換掉原來bbs.c里的dele_digest函數
int
dele_digest(dname,direc) /* updated bye Luzi 99.3.30 */
char *dname;
char *direc;
{
char digest_name[STRLEN];
char new_dir[STRLEN];
char buf[STRLEN];
char *ptr;
struct fileheader fh;
int pos;
strncpy(digest_name,dname,STRLEN);
strcpy(new_dir,direc);
digest_name[0]='G';
ptr = strrchr(new_dir, '/') + 1;
strcpy(ptr, DIGEST_DIR);
strncpy(buf,currfile,STRLEN);
strncpy(currfile,digest_name,STRLEN);
pos=search_record(new_dir, &fh, sizeof(fh), cmpdigestfilename, digest_name);
if(pos<=0)
{
return;
}
delete_file(new_dir,sizeof(struct fileheader),pos,cmpfilename);
strncpy(currfile,buf,STRLEN);
*ptr='\0';
sprintf(buf,"%s%s",new_dir,digest_name);
unlink(buf);
return;
}
--
※ 來源:‧大紅花的國度 MSIA.pine.ncu.edu.tw‧[FROM: 202.96.134.135]
--
※ 轉載:‧大紅花的國度 MSIA.pine.ncu.edu.tw‧[FROM: 202.96.134.135]