在递归函数中使用libpcre

时间:2011-02-08 18:19:12

标签: c recursion pcre valgrind

任何人都对这里发生的事情有任何想法?我有一个递归函数,有时会调用pcre来匹配正在构建的字符串中的模式。如果在用于匹配的模式中没有括号(转义括号也可以正常工作),它可以正常工作,但是如果我使用诸如([az])之类的模式,当最深的递归函数尝试时,valgrind会给出以下错误返回(使用模式\([az] \)工作正常):

编辑:我写了一个非递归版本,工作正常; libpcre是否有可能在存在括号时使用递归,并且在我的例程中以某种方式弄乱了前一个函数的地址?

==4712== 1 errors in context 1 of 1:
==4712== Jump to the invalid address stated on the next line
==4712==    at 0xFFFFFFFF: ???
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B646: ??? 
==4712==    by 0x40B483: ??? 
==4712==  Address 0xffffffff is not stack'd, malloc'd or (recently) free'd   

linked_list_t *_GetExistingKeysByPattern(linked_list_t *keys,
                                         session_t *session)
{
    char *cKey;
    linked_list_t *existingKeys = ListNew(NULL);
    ListIterSet(keys);
    while (cKey = ListIterNext(keys))
    {   //cKey could be SOFTWARE\\something\\([0-9]\.1) for example
        char keyPath[512];
        keyPath[0] = '\0';
        _GetExistingKeysByPatternHelper(cKey, keyPath, existingKeys, session);
    }
    return existingKeys;
}


void _GetExistingKeysByPatternHelper(char *patternStart,
                                     char *keyPath,
                                     linked_list_t *existing,
                                     session_t *session)
{
    char *ptr, currentKeyPath[512];
    unsigned short endOfPattern = 0;
    char *patternStartCopy = strdup(patternStart);

    if (ptr = strstr(patternStartCopy, "\\\\"))
        *ptr = '\0';
    else
        endOfPattern = 1;

    snprintf(currentKeyPath,
             512,
             "%s%s%s",
             keyPath,
             keyPath[0] == '\0' ? "" : "\\",
             patternStartCopy[0]=='^'?patternStartCopy+1:patternStartCopy);

    if (OpenRegistryEntry(session, currentKeyPath))
    {
        if (!endOfPattern)
            _GetExistingKeysByPatternHelper(ptr + 2,
                                            currentKeyPath,
                                            existing,
                                            session);
        else
            ListInsert(existing, (void *) strdup(currentKeyPath));
    }
    else if (keyPath[0] != '\0')
    {
        // Potential pattern
        if (OpenRegistryEntry(session, keyPath))
        {
            char *subKey;
            unsigned short i = 0;
            while (subKey = EnumerateRegistry(session, i++))
            {
                if (PatternEval(subKey, patternStartCopy, 1))
                {
                    char keyPathCopy[512];
                    snprintf(keyPathCopy,
                             512,
                             "%s\\%s",
                             keyPath,
                             subKey);

                    if (!endOfPattern)
                    {
                        _GetExistingKeysByPatternHelper(ptr + 2,
                                                        keyPathCopy,
                                                        existing,
                                                        session);
                        OpenRegistryEntry(session, keyPath);
                    }
                    else
                        ListInsert(existing, (void *) strdup(keyPathCopy));
                }
                free(subKey);
            }
        }
    }
    free(patternStartCopy);
}

unsigned short PatternEval(char *str, char *pattern, unsigned short carrot)
{
    unsigned short res = 0;
    const char *error;
    int erroroffset, rc, i;
    pcre *re;
    int ovector[100];
    char *tmp;
    if (carrot)
    {
        if (*pattern == '^') pattern++;
        tmp = (char *) malloc (strlen(pattern) + 2);
        sprintf(tmp, "^%s", pattern);
    }
    else
        tmp = pattern;

    if(re = pcre_compile(tmp, PCRE_CASELESS, &error, &erroroffset, 0))
    {
        if ((rc = pcre_exec(re, 0, str, strlen(str), 0, 0, ovector, sizeof(ovector))) >= 0)
            res = 1;
        pcre_free(re);
    }
    else
        printf("pcre_compile failed (offset %d), %s\n",erroroffset,error);

    if (carrot)
        free(tmp);

    return res;
}

1 个答案:

答案 0 :(得分:2)

这里的最后一个参数至少是错误的:

 pcre_exec(re, 0, str, strlen(str), 0, 0, ovector, sizeof(ovector))

sizeof(ovector)以字节为单位给出大小,但是pcre_exec需要int的数量,因此将其更改为

pcre_exec(re, 0, str, strlen(str), 0, 0, ovector, sizeof(ovector)/sizeof(ovector[0]))

文档还说明了

 ovecsize     Number of elements in the vector (a multiple of 3)

暗示大小应该是3的倍数,尽管这部分还不太清楚。