ransomweaver
ransomweaver

Reputation: 492

Need to replace use of strcpy_s in C code used in iPhone project

I have a C SDK I need to use in an iPhone project, and the example code was written for use with Visual Studio. It includes use of strcpy_s, which is a Microsoft-only string function.

file_header.header_size = FIT_FILE_HDR_SIZE;
strcpy_s((FIT_UINT8 *)&file_header.data_type, sizeof(".FIT"), ".FIT");  << problem!

I've tried changing to strcpy and strncpy like so

strncpy((FIT_UINT8 *)&file_header.data_type, ".FIT", sizeof(".FIT"));

But I get this warning:

warning: pointer targets in passing argument 1 of 'builtin_strncpy_chk' differ in signedness

warning: pointer targets in passing argument 1 of '__inline_strncpy_chk' differ in signedness

warning: call to builtin_strncpy_chk will always overflow destination buffer

The struct file_header is this:

typedef struct
{
   FIT_UINT8 header_size; // FIT_FILE_HDR_SIZE (size of this structure)
   FIT_UINT8 protocol_version; // FIT_PROTOCOL_VERSION
   FIT_UINT16 profile_version; // FIT_PROFILE_VERSION
   FIT_UINT32 data_size; // Does not include file header or crc.  Little endian format.
   FIT_UINT8 data_type[4]; // ".FIT"
} FIT_FILE_HDR;

FIT_UINT8 is typedef Unsigned char.

So we can see that it is given an length of 4 in the typedef, and the strcpy_s takes the data_type by reference and copys ".FIT" to it. Where am I going wrong with strncpy? If you haven't guessed by now I'm not much of a C programmer :)

Edit: this does not give me an error, but it is correct?

strncpy((void *)&file_header.data_type, ".FIT", sizeof(file_header.data_type));

Upvotes: 0

Views: 2312

Answers (2)

Stephen Canon
Stephen Canon

Reputation: 106247

With any "safe string" operations, the size should almost always be the size of the destination buffer; if you use the size of the source string, you might as well call memcpy.

If you want C99 conformance:

strncpy(file_header.data_type, ".FIT", sizeof file_header.data_type);

However, strlcpy (a BSDism, available in iOS) is preferred by many, because it guarantees that the destination will be nul-terminated:

strlcpy(file_header.data_type, ".FIT", sizeof file_header.data_type);

Note, however that the nul-terminated string ".FIT" doesn't actually fit in the allotted space, as it requires 5 characters (1 for the trailing nul). If you use strlcpy, you will see that the resulting string is just ".FI" because strlcpy guarantees nul-termination, and truncates your string if necessary.

If you require nul-termination then, you probably want to increase the size of the data_type array to 5. As caf correctly points out, this looks like a file header, in which case nul-termination is probably not required; in that case strncpy is preferred; I might even use memcpy, and avoid giving a future developer the idea that the field is a string.

Upvotes: 1

AndersK
AndersK

Reputation: 36102

Don't use

sizeof(".FIT")

use

strlen(".FIT")

Upvotes: 1

Related Questions