Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert current strcpy to strcpy_s?

Tags:

c

string

strcpy

I have large project having strcpy used everywhere. I am thinking to use strcpy_s instead of strcpy. I think almost 10,000 times I have used strcpy. It's so cumbersome to change every strcpy. Is there any efficient way for conversion?

like image 551
sonu gupta Avatar asked May 03 '17 09:05

sonu gupta


2 Answers

You really shouldn't do this without inspecting since the point of tightening up buffer management is lost if it's not done intelligently.

Since the nature of the destination buffer (static or heap allocation, for instance) is very important when it comes to the proper arguments for strcpy_s(), and that information of course is not present in the existing strcpy() call, you must add it in any way. This requires a human.

Often a call like strcpy(dest, src); can be transformed into strcpy_s(dest, sizeof dest, src);, but if dest is heap-allocated this will just be the size of the pointer rather than the pointed-at buffer which of course is wrong.

like image 145
unwind Avatar answered Oct 13 '22 22:10

unwind


Given that you have provide an additional parameter that can't be deduced (size_t destsz) that is required to be accurate to benefit from the change you've got a real problem.

An application with 10,000 uses of strcpy() sounds insane but you are where you are.

First If your time/resources are limited then all I can suggest is a bit of risk assessment. Which calls are copying external data (from a file, the operating system, the user, a port or socket, etc.). Focus on making sure those don't overwrite and you'll be reducing risk more effectively.

Second If you've got any standard variable names and standard 'max sizes' you might be able to do a bit of global search and replace.

Say if you use filename a lot and filenames are up to 255 characters (plus NUL) on your platform you can replace strcpy(filename, with (say) strcpy_s(filename,FILENAME_MAX_SZ.

If the code is 'all over the place' you've got a lot of work cut out.

Replacing strcpy(v, with strcpy_s(v,SIZE_MAX (use regular expressions) is a superficial bodge that doesn't actually gain you anything except for potentially sneaking under your organisations code quality script. I did not tell you to do this! ;)

Third If you want to take a stroll in the world of C11 _Generic you can try something like:

#define __STDC_WANT_LIB_EXT1__

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

int strcpy_s(char *dest,size_t destsz,const char *src){
    if(strlen(src)>=destsz){
        return 1;
    }
    strcpy(dest,src);
    return 0;
}

char *d_strcpy(char *dest,const char *src){
#ifndef NDEBUG
 fprintf(stdout,"unsafe copy of %s\n",src);
#endif
    return strcpy(dest,src);
}


#define strcpy(dest,src) _Generic (dest,\
    char[100] : strcpy_s(dest,sizeof dest,src),\
    char*: d_strcpy(dest,src)\
    )

int main(void) {
    char a[100]={'A','B','\0'};
    char *b=malloc(10*sizeof(char));

    strcpy(a,"XXX");
    strcpy(b,"XYX");

    printf("%s %s\n",a,b);

    free(b);
    return 0;
}

Unfortunately you do need to specify the array size so need to be using probably a limited list of 'max sizes' and while this should work on Clang (untested) it fails on GCC because they don't agree how to resolve the controlling type! See Document: N1930 (controlling expression of _Generic)

Happy hunting.

like image 26
Persixty Avatar answered Oct 13 '22 20:10

Persixty