View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002101 | unreal | ircd | public | 2004-09-30 11:50 | 2004-10-07 20:53 |
Reporter | Flop | Assigned To | syzop | ||
Priority | normal | Severity | crash | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | ALL | OS | ALL | OS Version | ALL |
Product Version | 3.2.1 | ||||
Fixed in Version | 3.2.2 | ||||
Summary | 0002101: badword "#" crash the IRCd | ||||
Description | This badword entry always freez and crash the IRCd server after a rehash or few seconds after a restart: badword channel { word "#*"; replace <spam>; }; | ||||
Tags | No tags attached. | ||||
3rd party modules | |||||
|
Confirmed on latest CVS [.144]. |
|
Now that is fun :p. 243 while (regexec(&this_word->expr, ptr, MAX_MATCH, pmatch,0) != REG_NOMATCH) (gdb) 245 if (pmatch[0].rm_so == -1) (gdb) 247 cleaned = 1; (gdb) 248 matchlen += pmatch[0].rm_eo - pmatch[0].rm_so; (gdb) p pmatch[0].rm_eo $1 = 0 (gdb) p pmatch[0].rm_so $2 = 0 (gdb) p matchlen $3 = 0 (gdb) n 249 strlncat(buf, ptr, sizeof buf, pmatch[0].rm_so); (gdb) p matchlen $4 = 0 (gdb) x/s buf 0xbfffe370: "<spam><spam><spam><spam><spam><spam><spam><spam><spam><spam> (gdb) x/s ptr 0x80cd220 <cleanstr.0>: "haha" (gdb) n 250 if (this_word->replace) (gdb) 251 strlcat(buf, this_word->replace, sizeof buf); (gdb) 254 ptr += pmatch[0].rm_eo; /* Set pointer after the match pos */ (gdb) 255 memset(&pmatch, 0, sizeof(pmatch)); (gdb) 243 while (regexec(&this_word->expr, ptr, MAX_MATCH, pmatch,0) != REG_NOMATCH) (gdb) 245 if (pmatch[0].rm_so == -1) (gdb) 247 cleaned = 1; (gdb) 248 matchlen += pmatch[0].rm_eo - pmatch[0].rm_so; (gdb) p matchlen $5 = 0 (gdb) p pmatch[0].rm_eo $6 = 0 (gdb) p pmatch[0].rm_so $7 = 0 (gdb) n 249 strlncat(buf, ptr, sizeof buf, pmatch[0].rm_so); (gdb) x/s buf 0xbfffe370: "<spam><spam><spam><spam><spam><spam><spam><spam><spam><spam><spam><spam><spam><spam><spam><spam><spam>"... (gdb) x/s ptr 0x80cd220 <cleanstr.0>: "haha" (gdb) n 250 if (this_word->replace) (gdb) 251 strlcat(buf, this_word->replace, sizeof buf); (gdb) p *this_word $8 = {prev = 0x819e3a8, next = 0x8183798, flag = {temporary = 0, permanent = 0}, word = 0x819e5f8 "#*", replace = 0x819ee90 "<spam>", type = 8, action = 1 '\001', expr = {re_nsub = 0, value = 0x819ee18}} (gdb) n 254 ptr += pmatch[0].rm_eo; /* Set pointer after the match pos */ (gdb) p ptr $9 = 0x80cd220 "haha" (gdb) n 255 memset(&pmatch, 0, sizeof(pmatch)); (gdb) p ptr $10 = 0x80cd220 "haha" (gdb) p strlen(buf) $11 = 4095 (gdb) n 243 while (regexec(&this_word->expr, ptr, MAX_MATCH, pmatch,0) != REG_NOMATCH) (gdb) 245 if (pmatch[0].rm_so == -1) (gdb) 247 cleaned = 1; (gdb) 248 matchlen += pmatch[0].rm_eo - pmatch[0].rm_so; (gdb) 249 strlncat(buf, ptr, sizeof buf, pmatch[0].rm_so); (gdb) 250 if (this_word->replace) (gdb) 251 strlcat(buf, this_word->replace, sizeof buf); (gdb) 254 ptr += pmatch[0].rm_eo; /* Set pointer after the match pos */ (gdb) 255 memset(&pmatch, 0, sizeof(pmatch)); (gdb) 243 while (regexec(&this_word->expr, ptr, MAX_MATCH, pmatch,0) != REG_NOMATCH) (gdb) 245 if (pmatch[0].rm_so == -1) (gdb) 247 cleaned = 1; (gdb) 248 matchlen += pmatch[0].rm_eo - pmatch[0].rm_so; (gdb) 249 strlncat(buf, ptr, sizeof buf, pmatch[0].rm_so); (gdb) 250 if (this_word->replace) (gdb) 251 strlcat(buf, this_word->replace, sizeof buf); (gdb) 254 ptr += pmatch[0].rm_eo; /* Set pointer after the match pos */ (gdb) 255 memset(&pmatch, 0, sizeof(pmatch)); (gdb) 243 while (regexec(&this_word->expr, ptr, MAX_MATCH, pmatch,0) != REG_NOMATCH) (gdb) 245 if (pmatch[0].rm_so == -1) (gdb) 247 cleaned = 1; (gdb) 248 matchlen += pmatch[0].rm_eo - pmatch[0].rm_so; (gdb) 249 strlncat(buf, ptr, sizeof buf, pmatch[0].rm_so); (gdb) [etc...] edited on: 2004-10-01 19:30 |
|
codemastr: should we perhaps break if pmatch[0].rm_eo is 0 or something? Or is there (also) a bug somewhere else (TRE?)? ;) |
|
I have no idea :P |
|
héhéhé ;-) |
|
Ok, first this has nothing to do with #. It has to do with empty matches. #* means "match 0 or more #." So, indeed, text like "abc" does match #*. But what part matches it? Well that's obvious, the "empty" part of it (none of the text). So how do you show this? By returning an empty string as the match text. You determine the length of the string by doing pmatch[0].rm_eo - pmatch[0].rm_so. In this case it is 0, so indeed the string is empty. So basically, I think TRE is working exactly as it is designed to work. I tested with the FreeBSD regex library and it did the same thing. I think the solution is pretty easy. Just detect these empty strings. Unfortunately, I'm not quite sure how to do this. I tried as you suggested, breaking when pmatch[0].rm_eo is 0. This doesn't work. For example, if I type "# #" it got changed to "<spam> #" rather than "<spam> <spam>" as it should have. So maybe you have a better idea? |
|
Ok, now I'm even more confused than when I started. I figured, since I don't quite know how to handle this, let's see how other people handle it. PHP: echo ereg_replace("#*", "@", "# #"); result was "@@ @@" Same result when using preg_replace. sed: echo # #|sed -e "s/#*/@/g" result was "@@ @" mIRC: //echo $regsub(# #,/#*/g,@,%var) result was "@@ @@" I tried a few other things, it seems the consensus was "@@ @@." Why sed was different, I have no idea. And I still don't understand why @@ @@ is the correct output, but it seems to be... |
|
Fixed in CVS [.149]: - Fix for "match-all regex" in badword *::word causing the IRCd to hang (0002101). We now (as decided per our discussion): - check if such a regex matches everything (=error) - if somehow rm_eo - rm_so == 0 then we break to prevent looping |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-09-30 11:50 | Flop | New Issue | |
2004-09-30 14:22 | syzop | View Status | public => private |
2004-09-30 14:38 | syzop | Note Added: 0007831 | |
2004-09-30 14:38 | syzop | Status | new => confirmed |
2004-09-30 14:42 | syzop | Note Added: 0007832 | |
2004-09-30 14:48 | syzop | Note Added: 0007833 | |
2004-09-30 15:08 |
|
Note Added: 0007834 | |
2004-09-30 15:31 | Flop | Note Added: 0007835 | |
2004-10-01 19:28 |
|
Note Added: 0007842 | |
2004-10-01 19:30 |
|
Note Edited: 0007832 | |
2004-10-02 00:14 |
|
Note Added: 0007844 | |
2004-10-07 20:46 | syzop | View Status | private => public |
2004-10-07 20:53 | syzop | Status | confirmed => resolved |
2004-10-07 20:53 | syzop | Resolution | open => fixed |
2004-10-07 20:53 | syzop | Assigned To | => syzop |
2004-10-07 20:53 | syzop | Note Added: 0007903 | |
2004-10-07 20:53 | syzop | Fixed in Version | => 3.2.2 |