How to Bypass a Standard C++ Function While Mainta

2019-02-28 09:20发布

I am looking for a way to be able to redefine a set of POSIX functions but then end the redefinition with a call to the original function. The idea is that I am trying to create a layer that can restrict what OS API's can be called depending on which "profile" is active. This "profile" determines what set of functions are allowed and any not specified should not be used.

For example, if in one profile I am not allowed to use strcpy, I would like to be able to either cause a compile time error (via static_assert) or print something to the screen saying "strcpy is not allowed in this profile" such as below:

MY_string.h

#include <string.h>

char *strcpy(char *restrict s1, const char *restrict s2)
{
#if defined(PROFILE_PASS_THROUGH)
    printf("strcpy is not allowed in this profile\n");
    return strcpy(s1, s2);
#elif defined(PROFILE_ERROR)
    static_assesrt(0, "strcpy is not allowed in this profile\n");
    return 0;
#else
    return strcpy(s1, s2);
#endif
}

So that way within main.cpp I can use MY_string.h

#define PROFILE_PASS_THROUGH
#include "MY_string.h"

int main()
{
    char temp1[10];
    char temp2[10];
    sprintf(temp2, "Testing");
    if (0 = strcpy(temp1, temp2))
    {
        printf("temp1 is %s\n", temp1);
    }
    return 0;
}

Now I realize that the code I have written above will not compile properly due to the redefinition of strcpy, but is there a way to allow this sort of functionality without playing around with macros or creating my own standard c and c++ libraries?

7条回答
萌系小妹纸
2楼-- · 2019-02-28 09:53

If using some recent GCC (e.g. version 4.7 or newer) you could also write a GCC plugin or a GCC extension in MELT to replace every call to strcpy to your own mystrcpy. This probably will take you some work (perhaps days, not hours) but has the enormous advantage to work inside the compiler, on the GCC compiler's internal representations (Gimple). So it will be done even after inlining, etc. And since you extend the compiler, you can tailor its behavior to what you want.

MELT is a domain specific language to extend GCC. It is designed for such tasks.

查看更多
相关推荐>>
3楼-- · 2019-02-28 09:55

In your MY_String.h:

... blah blah
using mynamespace::strcpy;
#endif // header guard or maybe not there if using pragma

then all strcpys that are not prefixed with std:: will use yours. If you REALLY want to ban them, grep and take a shotgun with you when you find the person who used it.

查看更多
The star\"
4楼-- · 2019-02-28 10:01

Here is how you would you change MY_string.h

#include <cstring>

namespace my_functions{
    char *strcpy(char *s1, const char *s2)
    {
#if defined(PROFILE_PASS_THROUGH)
        printf("strcpy is not allowed in this profile\n");
        return std::strcpy(s1, s2);
#elif defined(PROFILE_ERROR)
        static_assert(0, "strcpy is not allowed in this profile\n");
        return 0;
#else
        return std::strcpy(s1, s2);
#endif
     }

}
using namespace my_functions;

For this to work you cannot include or have using namespace std;

查看更多
叛逆
5楼-- · 2019-02-28 10:10

You cannot avoid these functions to be called.

A C++ program can do anything it wants, it could have some code that loads the strcpy symbol from libc and runs it. If a malicious developer want to call that function, you have no way to avoid it. To do that you'd need to run the C++ code in some special environment (in a sandbox, or virtual machine), but I'm afraid such technology is not available.

If you trust the developers, and you're just looking for a way to remind them not to call certain functions, then there could be some solution.

One solution could be avoiding to #include libc headers (like cstring), and only include your own header files where you only declared the desired functions.

Another solution could be that of looking to the compiled executable in order to find out what functions are called, or to LD_PRELOAD a library that redefines (and thus overrides) standard functions to make them print a warning at runtime.

查看更多
地球回转人心会变
6楼-- · 2019-02-28 10:11

No, cannot be done in C++. What you want is more akin to a LISP (or derivative) language, where you can grab the slot for an existing function and 'override it in place', potentially punting back to the original implementation.

查看更多
混吃等死
7楼-- · 2019-02-28 10:17

Typical way of doing is on Unix is via LD_PRELOAD, example (Unix) below proxies a function call, malloc in particular (full example):

/**
 * malloc() direct call
 */
inline void * libc_malloc(size_t size)
{
  typedef void* (*malloc_func_t)(size_t);
  static malloc_func_t malloc_func = (malloc_func_t) dlsym(RTLD_NEXT, "malloc");

  return malloc_func(size);
}
查看更多
登录 后发表回答