2

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

Sara Sara
  • 299
  • 1
  • 6
  • 14
  • how your _string_ is represented? Remember, `0` and `'0'` are not the same. – Sourav Ghosh Apr 08 '15 at 14:24
  • 3
    Could you show us your code ? – Thomas Ayoub Apr 08 '15 at 14:24
  • 2
    Is this a string of digits (e.g. `"56 69 56 4F 74 ..."`), or is this an array of `char` with values of `0`? – crashmstr Apr 08 '15 at 14:24
  • 6
    "I think it's confusing it with the `'\0'` !" No confusion. They're the same thing, an ASCII 0 character. – Paul Roub Apr 08 '15 at 14:25
  • 5
    If you don't want to stop at the first 0 (which is what `strlen()` does, and what the length of a string *means*, in C), how do you expect to know when you've reached the end of the string? – Paul Roub Apr 08 '15 at 14:26
  • How did you create the string? – BLUEPIXY Apr 08 '15 at 14:27
  • What is the length you are getting? I'm getting 152, which Is correct ( I counted ). I did `char a[] = "56 69 5........"; printf("%d",strlen(a));` – Arun A S Apr 08 '15 at 14:28
  • So `strlen()` is behaving exactly as expected. You still haven't said how you *want* the end of the string to be determined. – Paul Roub Apr 08 '15 at 14:48
  • @BLUEPIXY actually i don't create the string , it's generated ! – Sara Sara Apr 08 '15 at 14:48
  • Note that C arrays and strings are very primitive compared to most other languages. So especially if you are used to some other language, forget what you know and learn what these things mean in C (or switch to C++, which has higher level arrays, strings and containers, if that is an option). – hyde Apr 08 '15 at 14:49
  • How did you generated the string? `unsigned char Response[269]={0x00};` : all elements are zero. – BLUEPIXY Apr 08 '15 at 14:51
  • @BLUEPIXY from a smart card via a contactless interfaces using Payment terminal – Sara Sara Apr 08 '15 at 14:54
  • 1
    You should store the size of the read data. – BLUEPIXY Apr 08 '15 at 14:56
  • 2
    While this question is naive, I can't imagine why people are *downvoting* it. It's an earnest question from a new user. – Stephen Canon Apr 08 '15 at 15:22
  • 1
    Well excuse me no one was born expert ! @StephenCanon – Sara Sara Apr 08 '15 at 15:24

5 Answers5

4
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.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Thank you for your answer ! I will for sure do as you said and i'll keep you in touch for the result :) – Sara Sara Apr 08 '15 at 15:02
  • Well I've changed `unsigned char` by `char` , but still have the same problem . And the string mentioned above i just wrote it that way so to show you where it stops ! – Sara Sara Apr 08 '15 at 15:08
  • @SaraSara: Knowing where it stops doesn't help if we don't know what it actually looks like. `56 69 56 4F 74 ...` is not a representation of a string. Please update your question to show us the actual code that creates the string. If your array contains bytes with the values `0x56`, `0x69`, `0x56`, etc., then of course `strlen` stops when it encounters the first `0x00`; `0x00` and `'\0'` are exactly the same thing. – Keith Thompson Apr 08 '15 at 15:13
  • The string is created from a card via a contactless interface of a Electronic payment terminal ! – Sara Sara Apr 08 '15 at 15:17
  • @SaraSara: See the last paragraph of my updated answer. – Keith Thompson Apr 08 '15 at 15:24
  • thanks for your answers ! I'll search as you said for "other means" – Sara Sara Apr 08 '15 at 15:27
  • Perhaps the downvoter would care to explain what's wrong with this answer. – Keith Thompson Apr 08 '15 at 17:30
3

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.

Sean
  • 60,939
  • 11
  • 97
  • 136
3

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.

Ed4
  • 2,277
  • 18
  • 18
  • 3
    "*More importantly, `strlen` is **extremely dangerous** ...*" -- I disagree. `strlen` is perfectly safe *if* you can guarantee that the argument points to a valid null-terminated string. It can even be input data if the input was received in a way that guarantees null termination (e.g., `fgets`). – Keith Thompson Apr 08 '15 at 17:29
0

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.

Tom Womack
  • 781
  • 4
  • 10
0

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;
}