использование libpcre в рекурсивных функциях - PullRequest
1 голос
/ 08 февраля 2011

У кого-нибудь есть идеи относительно того, что здесь происходит? У меня есть рекурсивная функция, которая иногда делает вызовы 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 Ответ

2 голосов
/ 08 февраля 2011

Последний параметр здесь как минимум неправильный:

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

sizeof (ovector) дает размер в байтах, но pcre_exec нужно количество дюймов, поэтому измените его на

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, хотя эта часть довольно неясна.

...