9

setattrそしてgetattr、私のプログラミングスタイルに入りました(主に科学的なもので、Pythonに関する私の知識は独学です)。

場合によってはセキュリティ上の問題につながる可能性があるため、潜在的な危険を継承することを考慮するexecと、同じ議論が有効であると見なされるかどうか疑問に思っていました. (私はいくつかの情報を含むこの質問を見つけました-議論はあまり説得力がありませんが。)evalsetattrgetattr

私の知る限り、setattrあまり気にせずに使用できますが、正直なところ、Python の知識を十分に信頼していません。間違っている場合は、使用する習慣を取り除きたいと思います。setattr.

どんな入力でも大歓迎です!

4

1 に答える 1

12

まず、既存のセキュリティ ホールへのアクセスが確実に容易になる可能性があります。

たとえば、、、、SQL クエリ、または文字列の書式設定などを介して構築された URL を実行するコードがあるとしexecます。また、書式設定コマンドまたはコンテキストなどevalに渡す、たとえば、locals()またはフィルタリングするとします。を使用すると、明らかにセキュリティ ホールが広がり、コードを攻撃する方法を見つけるのがはるかに簡単になります。これらの関数に何を渡そうとしているのかわからないからです。__dict__evalsetattr

しかし、他に危険なことを何もしなければどうでしょうか? setattrじゃあ安全?

それほど悪くはありませんが、それでも安全ではありません。あなたが設定している属性の名前に影響を与えることができれば、たとえば、オブジェクトに必要なメソッドを置き換えることができます。

たとえば、最初に古い値が呼び出し可能でないか、メソッド型記述子ではないかなどをチェックすることで、これを防ぐことができます。eval同じように、関数を呼び出したり、SQL パラメーターに引用符やセミコロンを入れたりする人から保護することができます。これは、他のケースと事実上同じです。そもそもドアを開けないよりも、開いているドアへの不正な道をすべて閉じようとする方がはるかに困難です。

名前がユーザーに影響を与える可能性のあるものに由来しない場合はどうなりますか?

では、なぜ を使用しているのsetattrでしょうか。setattrリテラルで呼び出す正当な理由はありません。

とにかく、目前の問題を解決するためのより良い方法がしばしばあると Lattyware が言ったとき、彼はほぼ間違いなく読みやすさ、保守性、慣用性について話していました。しかし、これらのより良い方法を使用することの副作用は、多くの場合、セキュリティへの影響を回避できることです。

90% の確率で、解決策はdictオブジェクトの代わりに a を使用することです。Javascript とは異なり、Python では同じものではなく、同じように使用することを意図していません。Adictにはメソッド、継承、または組み込みの特殊な名前がないため、それらについて心配する必要はありません。d['foo']の代わりに言うことができる、より便利な構文もありますsetattr(o, 'foo')。そして、それはおそらくより効率的です。等々。しかし、最終的に a を使用する理由dictは概念上の理由です。adictは値の名前付きコレクションです。クラス インスタンスはモデル空間オブジェクトの表現であり、それらは同じものではありません。

では、なぜsetattr存在するのでしょうか。

im_funcやにアクセスできるfunc_closure、 や のようなモジュールを持っている、他のメソッドと同じように特別なメソッドを扱う、tracebackさらに言えばやなど、他の低レベルの機能と同じ基本的な理由で存在します。impexeceval

まず、これらの低レベルのツールから高レベルのものを構築できます。たとえば、 をビルドするには、 またはcollections.namedtupleのいずれかが必要execですsetattr

第 2 に、コンパイル時にコードを変更する (または表示することさえできない) ため、実行時にコードにモンキー パッチを適用する必要があり、そのためには次のようなツールsetattrが不可欠です。

このsetattr機能は、よく似たものevalで、Javascript、Tcl、またはその他のいくつかの言語から来た人々によって悪用されることがよくあります。しかし、それが永久に使用できる限り、それを言語から除外したくはありません。(TOOWTDI を文字どおりに解釈して、プログラムを 1 つだけ作成できるようにしないでください。)

しかし、それは、可能な限りこのようなものを使用する必要があるという意味ではありません. mylist.__getitem__(slice(1, 10, 2))の代わりに書くことはありませんmylist[1:10:2]__getitem__場合によっては、オブジェクトを直接呼び出したりslice、明示的にビルドしたりできることが、コードの残りの部分をより Pythonic にするための基盤となる場合や、コードの残りの部分への感染を回避するための回避策をローカライズするための方法となる場合があります。それ以外の場合は、より明確で簡単な方法があります。

于 2012-12-21T00:05:08.010 に答える