Sara Sara
Sara Sara

Reputation: 319

strlen does not return the right length

I'm currently using strlen method to calculate the lenght of this string :

56 69 56 4F 74 65 63 68 32 00 2C 00 00 27 6F 23 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 11 BF 0C 0E 61 0C 4F 07 A0 00 00 00 04 10 10 87 01 01

the main problem is that it always stops when encounter 00 , I think it's confusing it with the '\0' ! so I'm wondering if there's a replacement for this method or is there anything you can suggest to fix this issue .

P.S: I'm not sure if the question is duplicated I searched for the same problem but couldn't find a satisfying answer !

Edited :

my code :

unsigned char Response[269]={0x00};
unsigned char Response_PPSE[269];


for(i=0;i<=strlen(Response);i++)
sprintf(Response_PPSE+(2*i),"%02X",Response[i]);

the strlen calculate the length of this bytes only : 56 69 56 4F 74 65 63 68 32 00

Upvotes: 2

Views: 4353

Answers (5)

In an application i made i created a custom "strlen" method using the following approach in order to correctly count the length even if i have null bytes in the middle of my data:

-We need to use except the char * containing the data, also the malloc'ed size. -I pass the following parameters to the method: first parameter the char * str, second the size of malloc.

-Method works in the opposite way, from the MAX memory addr (memory addr of str + second parameter) to the first memory size, a while loop decrements the max memory address until first memory address reached but this while loop will break in case the first non NULL/0 char reached.

-Finally we return the difference of last MAX memory address and first memory address of char *, +1.

This is the my code:

size_t utils_strlen(const char * str, int max) {
    const char * maxs;
    maxs = str + max;

    while(str<maxs) {
      if(*maxs!=0) break;
      maxs--;
    }

    return(maxs-str)+1;
}

Upvotes: 0

Tom Womack
Tom Womack

Reputation: 791

You mean the length of the array rather than the length of the response, so you want sizeof(Response) rather than strlen(Response) - presumably you know that the response is 269 bytes long because that's what the card protocol defines.

You also need Response_PPSE to be 2*269+1 bytes long, because otherwise your printf statements will run off the end of the array. And you need to set Response_PPSE[2*269]=0 to make it a valid null-terminated string.

Upvotes: 0

Ed4
Ed4

Reputation: 2305

The other answers I've seen so far are dancing around the real problem here. Which is that you need to understand what kind of string you're dealing with.

By historical convention, C represents strings as null terminated character arrays. That is the kind of string that strlen expects. But your "string" contains null bytes. So it is not a null-terminated string, and strlen will not do what you want.

More importantly, strlen is extremely dangerous and should never be used in modern code. It's easy to cause security vulnerabilities with strlen, and the odds are good that if your program is using strlen to examine responses received over the network, your program can be exploited to achieve denial or service or even remote code execution.

A safer alternative is strnlen, if you give it the correct size limit. It's hard to be more precise about the right solution, because in your example the correct answer is just always 269, so there's really no variable-length string to measure.

Upvotes: 3

Keith Thompson
Keith Thompson

Reputation: 263627

unsigned char Response[269]={0x00};

This initializes Response to a sequence of 269 identical values, each of which is zero. Note that 0x00, 0, and '\0' are all the same thing.

strlen(Response)

This is actually invalid, though some compilers may permit it. strlen requires an argument of type char*; Response is an array of unsigned char, which is converted to a pointer of type unsigned char*. The types are not compatible, and there is no implicit conversion. You should have gotten a compile-time warning (if you did, please include the warning in your question).

If we change the definition of Response to:

char Response[269] = {0x00};

then the strlen call becomes valid -- and will return 0. strlen scans for the first '\0' null character -- and you've filled Response with null characters.

At the top of your question, you say you have a string:

56 69 56 4F 74 65 63 68 32 00 2C 00 00 27 6F 23 84 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 11 BF 0C 0E 61 0C 4F 07 A0 00 00 00 04 10 10 87 01 01

That doesn't have anything to do with the code you showed us. It's also ambiguous; is it a string of hex digits and spaces: "56 69 56 ...", or is it something like "\x56\x69\x56..."? If the 56 69 sequence is intended to represent the contents of your array, please update your question to show the actual code that creates it.

Finally:

for(i=0;i<=strlen(Response);i++)
sprintf(Response_PPSE+(2*i),"%02X",Response[i]);

Calling strlen on each iteration of the loop can be quite inefficient. strlen has to scan the entire string each time to determine its length. Once you get the other problems straightened out, you should call strlen once before the loop and use the stored value.

However, you probably don't want to be using strlen in the first place. strlen is applied to strings. A "string" is a sequence of characters terminated by a null character (0, '\0', 0x00). You appear to have a sequence of unsigned characters in which 0x00 is a valid value, not a terminator. Rather than using strlen to compute the length of the array, you need to keep track of the length by some other means.

Upvotes: 3

Sean
Sean

Reputation: 62532

00 and '\0' are the same thing.

It looks like you can an array of data are you're looking to get the length of the array rather than the length of a string. strlen will scan an array up to the first null terminator. There's no equivalent for an arbitrary array, so you need to keep track of it yourself.

Upvotes: 3

Related Questions