0

I have been troubled by a problem of strlen for a long time, here is the code:

   char stack_protect[1000] = {0};
    char temp[100] = { 0 };
    memset(&temp, 1, 110);
    int len = strlen(temp);
    
    printf("test strlen of temp %d \n", len);
    if (len > 100)
    {
        xxxx;
    }
    else
    {
        xxxx;
    }

   char stack_protect2[1000] = {0};

you can see, I passed a param temp to strlen, and the return value len is surely 110. but the next statements if (len > 100) evaluates to false!

system: linux
CPU architecture: 32 Bit ARM SOC: nt98566

please help me! thank you

something I have test:

  1. if you assign len value to another int variable, things will ok. like below

example:

    char temp[100] = { 0 };
    memset(&temp, 1, 110);
    int len = strlen(temp);
    
    int len1 = len;
    
    if (len1 > 100) ? TRUE!
  1. the every byte of len:
   0x6e, 0x00, 0x00, 0x00
  1. in another soc hisiv300 len:110 if len > 100? TRUE
  • 4
    Using string functions on strings that are not NUL terminated is undefined behaviour. Strictly speaking, an array of characters that isn't NUL terminated isn't technically even a string to begin with. – Marco Aug 26 '23 at 10:48
  • 2
    *"the return value `len` is surely 110"* I'm curious about why do you think so. Do you expect uninitialized memory to always be nulled or `memset` to somehow add a NULL terminator *after* the values it sets? Both are wrong assumptions, to be clear. – Bob__ Aug 26 '23 at 11:30
  • 1
    There is no such thing as a "non zero terminated string". By definition (in C), a "string" is a sequence of non-zero bytes terminated by a single zero byte. You can certainly have an array of characters that are not terminated by a nul byte, but that array is *not* a "string". By definition. – William Pursell Aug 26 '23 at 15:16
  • 1
    [Related](https://stackoverflow.com/questions/72436704/what-are-null-terminated-strings). – n. m. could be an AI Aug 26 '23 at 15:18
  • why I think len is 110: before and after this statement, I declared and initialized an array[1000] with 0. – shunji XIE Aug 27 '23 at 04:08
  • 1
    If the set collection of characters is not nul-terminated -- it's not a C string. Passing it to a `str...()` function results in *Undefined Behavior*. – David C. Rankin Aug 27 '23 at 04:10
  • Please note that in an optimized build those two "stack protect" will be ignored (optimized away), also, in general, you can't assume that those variables are packed, they are likely alligned to some multiple of bytes. – Bob__ Aug 27 '23 at 14:40

1 Answers1

6

memset(&temp , 1, 110); is bad as it attempts to write outside the temp[] array. This is undefined behavior (UB). Anything may happen at this point, in earlier or in later code.

strlen(temp); is also UB as strlen() expects a pointer to a string and array temp is not a string as it lacks a null character.

Do not expect code to behave well when it has UB.
Do not expect code to fail when it has UB.
Do not expect the UB you see today to be the same tomorrow.

Instead, eliminate the UB.

char temp[100] = {0};
//memset(&temp , 1, 110);
memset(temp , 1, 99); // Re-write the first 99, leaving the last as 0
int len = strlen(temp);

I suspect OP's code UB is the writing of len1 by memset(), yet that is only a guess.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 4
    Re “Anything may happen at this point or in later code”: The C standard does not specify what happens at any time, [including before a nominal point at time at which a statement inducing undefined behavior is executed](https://devblogs.microsoft.com/oldnewthing/20140627-00/?p=633). Consider that, if some branch of execution containing `a[i] = Value;` is executed, the compiler is allowed to assume `i` is not out of bounds and thus may optimize the code as if it is in bounds, so it may put `a[i] = Value;` at the beginning of that path of execution. – Eric Postpischil Aug 26 '23 at 11:14
  • 1
    @EricPostpischil Answer amended. – chux - Reinstate Monica Aug 26 '23 at 11:16
  • @EricPostpischil Nice comment. Didn't know it would affect code that comes before the offending code :) – Marco Aug 26 '23 at 21:19