code review c – memmem en Windows

Pregunta:

Recientemente, estaba memmem una aplicación que usa memmem de Linux a Windows. Si bien memmem está disponible como función de biblioteca en Linux, MSDN / Windows no lo ofrece. Podría haber usado strstr pero luego tiene un prototipo muy diferente y solo espera cadenas terminadas en nulo como argumentos. Buscando en Google, descubrí algunas implementaciones de memmem pero ninguna parecía imitar realmente memmem .

Por lo tanto, escribí uno de los míos:

void *memmem(const void *haystack_start, size_t haystack_len, const void *needle_start, size_t needle_len)
{

    const unsigned char *haystack = (const unsigned char *) haystack_start;
    const unsigned char *needle = (const unsigned char *) needle_start;
    const unsigned char *h = NULL;
    const unsigned char *n = NULL;
    size_t x = needle_len;

    /* The first occurrence of the empty string is deemed to occur at
    the beginning of the string.  */
    if (needle_len == 0)
        return (void *) haystack_start;

    /* Sanity check, otherwise the loop might search through the whole
        memory.  */
     if (haystack_len < needle_len)
       return NULL;

    for (; *haystack && haystack_len--; haystack++) {

        x = needle_len;
        n = needle;
        h = haystack;

        if (haystack_len < needle_len)
            break;

        if ((*haystack != *needle) || ( *haystack + needle_len != *needle + needle_len))
            continue;

        for (; x ; h++ , n++) {
            x--;

            if (*h != *n) 
                break;

           if (x == 0)
            return (void *)haystack;
        }
    }

    return NULL;
}

El código funciona, pero mi pregunta es: ¿podría hacerse de manera más eficiente o más rápida?

Espero que uno de los increíbles trucos aquí también tenga la amabilidad de señalar si esta implementación tiene una vulnerabilidad que quizás no haya notado.

Respuesta:

  1. Tu escribiste:

     for (; *haystack && haystack_len--; haystack++) { x = needle_len; n = needle; h = haystack; if (haystack_len < needle_len) break;

    Una mejor forma sería:

     for (; --haystack_len >= needle_len; haystack++) { x = needle_len; n = needle; h = haystack;

    El *haystack es en realidad un error, ya que evita la búsqueda si hay cero bytes en el rango.

  2. Creo que es una mala idea tener la segunda cláusula en:

     if ((*haystack != *needle) || ( *haystack + needle_len != *needle + needle_len))

    porque podrías romper el caché. Mantenga el acceso a los datos local. Comprobar el último carácter es una complejidad innecesaria.

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım