3

In C language I have a uint8_t array and, after some logic, I need to cast to string and check if contains some substring like this:

uint8_t data[8] = {0xcb,0xe2,0x3d,0x96,0x55,0xfc,0xcd,0x43};
    
/// some logic
    
if(strstr((const char *)data, "000") != NULL){
    
}

Is if statement correct? it seems to return always true.

3
  • fyi "000" is 4 characters, there is an additional null-terminator Commented Oct 16, 2024 at 6:45
  • 3
    If you're using GNU libc, there's a memmem function that works with byte arrays (pointer + length) rather than NULL-terminated strings, but otherwise does the same thing as strstr Commented Oct 16, 2024 at 21:34
  • @ChrisDodd that's a nice solution (if applicable). Added it to my answer below. Commented Oct 17, 2024 at 6:56

2 Answers 2

5

As you can see in the strstr documentation, the first argument is:

str - pointer to the null-terminated byte string to examine

(emphasis is mine)

In your case data which is passed as an arugment for str is not null-terminated.

The documentation also states that:

The behavior is undefined if either str or substr is not a pointer to a null-terminated byte string.

Your code therefore invokes undefined-bahevior, meaning the standard does not guarantee the result and it's possible that the function will always return true (as well as any other behavior).

A possible solution is to make data 9 bytes and add 0x00, making it null-terminated.

Another solution (as @ChrisDodd commented) is applicable if you are using GNU libc:
Use memmem function. It works similarly to strstr, but accepts buffers length and does not require null-termination.

Sign up to request clarification or add additional context in comments.

Comments

1

All functions prefixed with str in the C standard library assume that you pass a null terminated string to them. If you pass something else, like in this case, you invoke undefined behavior and will get crashes or wrong results etc.

We could cook up our own (naive) function for this easily enough by iterating across the data and comparing it to the search key string with memcmp:

#include <string.h>
#include <stdint.h>

const uint8_t* memstr (const uint8_t* data, const char* key, size_t size)
{
  const uint8_t* result = NULL;
  size_t key_length = strlen(key);
  
  for(size_t i=0; i<size-key_length+1; i++)
  {
    if(memcmp(&data[i], key, key_length) == 0)
    {
      result = &data[i];
      break;
    }
  }
  return result;
}

Here the requirement is that key is a null terminated string but data could be anything. Since key is a string we can call strlen on it. We should only iterate up to the buffer size minus key length amount of bytes. So for example with 8 data bytes and a search key of "000" thats 8-3=5 bytes. But we have to check data indices 0 to 5, so a +1 on the loop condition is needed.

Complete test code:

#include <string.h>
#include <stdint.h>
#include <stdio.h>

const uint8_t* memstr (const uint8_t* data, const char* key, size_t size)
{
  const uint8_t* result = NULL;
  size_t key_length = strlen(key);

  for(size_t i=0; i<size-key_length+1; i++)
  {
    if(memcmp(&data[i], key, key_length) == 0)
    {
      result = &data[i];
      break;
    }
  }
  return result;
}


#define test_memstr(data, key)               \
  found = memstr(data, key, sizeof data);    \
  if(found)                                  \
    printf("\"%.*s\" found at index %tu\n",  \
           strlen(key), found, found-data);  \
  else                                       \
    puts("Not found");

int main (void)
{
  uint8_t data1[8]  = {0xcb,0xe2,0x3d,0x96,0x55,0xfc,0xcd,0x43};
  uint8_t data2[11] = {0x48,0x65,0x6C,0x6C,0x6F,0x20,0x57,0x6F,0x72,0x6C,0x64};
  const uint8_t* found;

  test_memstr(data1, "000");
  test_memstr(data2, "World");
  test_memstr(data2, "Hello");
}

Comments

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.