k-takata/Onigmo — pull request #2 by htz (2012-01-11 02:50:16+00:00)
Title: OnigCaptureTreeNodeでメモリリーク

鬼車時代(数年前)に開発者の方に下記のメールを送りましたが反応がなく、
Onigumoの方にも同メモリリークが残っていましたのでよろしかったらpullして下さい。
history_tree_clearでnode->childsのfreeが抜けているように思います。

下記再現コードでメモリリークが発生し、本修正でメモリリークが起きないことを確認しています。

htz

========================================

鬼車開発者様

いつも鬼車を使わせて頂いております、辻と申します。

最新版の鬼車5.9.2にてメモリリークらしきものを発見したので報告致します。

動作環境は
OS : Windows XP SP2 Cygwin
GCC : $ gcc -v
Reading specs from /usr/lib/gcc/i686-pc-cygwin/3.4.4/specs
Configured with: /gcc/gcc-3.4.4/gcc-3.4.4-1/configure --verbose --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-languages=c,ada,c++,d,f77,java,objc --enable-nls --without-included-gettext --enable-version-specific-runtime-libs --without-x --enable-libgcj --disable-java-awt --with-system-zlib --enable-interpreter --disable-libgcj-debug --enable-threads=posix --enable-java-gc=boehm --disable-win32-registry --enable-sjlj-exceptions --enable-hash-synchronization --enable-libstdcxx-debug : (reconfigured)
Thread model: posix
gcc version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)
です。

再現再現コード
#include
#include
#include
#include "oniguruma.h"

int main() {
/* メモリリークする */
const char *pattern = "\\g

(?@

\\(\\g\\)){0}(?@(?:\\g

)*|){0}";
const char *str = "(((()()(()))(())())())";
/* メモリリークしない */
// const char *pattern = "^test_(.+)$";
// const char *str = "test_ok";

OnigSyntaxType syn;
regex_t* reg;
int r;
OnigErrorInfo einfo;

onig_copy_syntax(&syn, ONIG_SYNTAX_DEFAULT);
onig_set_syntax_op2(&syn, onig_get_syntax_op2(&syn) | ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY);

while (1) {
onig_new(®, (const OnigUChar *)pattern, (const OnigUChar *)pattern + strlen((char *)pattern),
(OnigOptionType)ONIG_OPTION_DEFAULT, ONIG_ENCODING_UTF8, &syn, &einfo);
if (r != ONIG_NORMAL) {
OnigUChar s[ONIG_MAX_ERROR_MESSAGE_LEN];
onig_error_code_to_str(s, r, &einfo);
fprintf(stderr, "error:%s", s);
exit(1);
}
OnigRegion *region = onig_region_new();
if (region == NULL) {
fprintf(stderr, "error:onig_region_new");
}
const OnigUChar *s, *e;
s = (const OnigUChar *)str;
e = s + strlen(str);
r = onig_search(reg, s, e, s, e, region, ONIG_OPTION_NONE);
onig_region_free(region, 1);

onig_free(reg);
}

return 0;
}

history_tree_clearに
xfree(node->childs);
node->childs = (OnigCaptureTreeNode* )0;
を追加する必要がaると思うのですが、
そもそも再現コードが間違っていましたら申し訳ございません。

以上、宜しくお願いします。