3

I need something between strstr and memcmp for checking if an array exists in a range of memory.

Example what I want to achieve:

BYTE a[] = { 0x01, 0x02, 0x03, 0x04 };
BYTE b[] = { 0x02, 0x03 };
if (mem_in_mem(a, b, 4 * sizeof(BYTE)) == 0) {
    printf("b is in memory range of a\n");
}

Any ideas how I can something like that? (Should work with windows)

18
  • 1
    You could write that function, sure. Why not memcmp and advance a character each time until you've checked the whole buffer? Commented Mar 7, 2017 at 20:31
  • 3
    Unfortunately, the proposed mem_in_mem function is not told the length of the (Sub)Array it is supposed to match. Commented Mar 7, 2017 at 20:37
  • 1
    Optimise by checking the first byte before committing to an expensive function call to memcmp. Commented Mar 7, 2017 at 20:39
  • 1
    At looks like perhaps you want to implement the KMP algorithm. Any way around, though, the function needs a way to know the boundaries of both the target array and the test array. Commented Mar 7, 2017 at 20:39
  • 1
    @immibis in your library, perhaps, but it still requires a function call which can be avoided if the simple test fails. Commented Mar 7, 2017 at 20:43

1 Answer 1

4

The function mem_in_mem should take the size of both arrays. Here is a simplistic implementation:

#include <string.h>

void *mem_in_mem(const void *haystack, size_t n1, const void *needle, size_t n2) {
    const unsigned char *p1 = haystack;
    const unsigned char *p2 = needle;

    if (n2 == 0)
        return (void*)p1;
    if (n2 > n1)
        return NULL;

    const unsigned char *p3 = p1 + n1 - n2 + 1;
    for (const unsigned char *p = p1; (p = memchr(p, *p2, p3 - p)) != NULL; p++) {
        if (!memcmp(p, p2, n2))
            return (void*)p;
    }
    return NULL;
}

You would invoke it this way:

BYTE a[] = { 0x01, 0x02, 0x03, 0x04 };
BYTE b[] = { 0x02, 0x03 };
if (mem_in_mem(a, sizeof a, b, sizeof b)) {
    printf("b is in memory range of a\n");
}
Sign up to request clarification or add additional context in comments.

2 Comments

Just as int *ptr = malloc(8); does not need a cast, neither does return (void*)p; Perhaps window's C is picky?
Ah, I see the need for the cast, to discard the const!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.