関数に渡されたパラメーター(const char * arguments)が定数リテラルまたは変数であったかどうかを検出する簡単な方法はありますか?
パラメータが定数リテラルの場合にアクセス違反の例外をスローするIsBadWritePtr呼び出しで満たされたコードのエラーを修正しようとしています。
これはひどいデザインの愚かさでしたが、今では厄介な振る舞いを変えることは許されていません。
関数に渡されたパラメーター(const char * arguments)が定数リテラルまたは変数であったかどうかを検出する簡単な方法はありますか?
パラメータが定数リテラルの場合にアクセス違反の例外をスローするIsBadWritePtr呼び出しで満たされたコードのエラーを修正しようとしています。
これはひどいデザインの愚かさでしたが、今では厄介な振る舞いを変えることは許されていません。
文字列リテラルによりよく一致する別のオーバーロードを追加できます。これは実際には科学ではなく、単なるヒューリスティックです。
void f(const char* p); // potential literal
void f(char *p); // pointer to non-const
別のアイデアは、リテラルが実際には配列であることを利用することです。
template <int N>
void f(const char (&_)[N]); // potential literal
リテラルとリテラルではなく、他の機能のいくつかを完全に検出しないことに注意してください。const char* p = createANewString(); f(p);
に解決されf(const char*)
、const char x[] = { 'A', 'b', 'c', '\0' };
テンプレートに解決されます。どちらもリテラルではありませんが、おそらくどちらも変更したくないでしょう。
その変更を行うと、各オーバーロードが呼び出される場所を簡単に見つけることができます。
const char*
これはすべて、main関数が引数を内部的に変更するかのように受け取らないこと、および下位互換性のためにコンパイラが非ポインタを受け取る関数の呼び出しを許可しているために直面している問題を前提として機能します。文字通りのconst..。
少なくともハッカーを使わずにそれを検出する方法はないと思います。
インターフェイスはconst char *
関数の責任を負うため、渡された文字列を変更しないことです。単に正しくないため、実装を変更する必要があります。
VirtualQuery
アドレスが書き込み可能、読み取り専用、またはアクセス不能であるかどうかを検出するために使用できます。返された構造体のメンバーState
とメンバーを調べて、メモリにアクセスでき、必要なアクセス権があるかどうかを確認します。Protect
MEMORY_BASIC_INFORMATION
非常にハックな方法の1つは、ポインターが.rdataセグメントにあるかどうかを確認することです。
ビルド後に使用dumpbin /headers
して、.rdataセクションのオフセットと長さを取得するか、PEヘッダーを自分で解析します。当然、これはツールチェーン固有であり、一般的には悪い考えです。また、コードがDLLと相互運用する必要がある場合は、いくつかの実行可能ファイルといくつかの.rdataセグメントをチェックする必要があります。