[解決済み] 構造体を比較するときに、なぜこのアサートはフォーマット例外を投げるのですか?
質問
2つのオブジェクトが等しいことを証明したい。
System.Drawing.Size
構造体の等価性を主張しようとしていますが、期待される主張の失敗ではなく、フォーマット例外が発生します。
[TestMethod]
public void AssertStructs()
{
var struct1 = new Size(0, 0);
var struct2 = new Size(1, 1);
//This throws a format exception, "System.FormatException: Input string was not in a correct format."
Assert.AreEqual(struct1, struct2, "Failed. Expected {0}, actually it is {1}", struct1, struct2);
//This assert fails properly, "Failed. Expected {Width=0, Height=0}, actually it is {Width=1, Height=1}".
Assert.AreEqual(struct1, struct2, "Failed. Expected " + struct1 + ", actually it is " + struct2);
}
これは意図された動作なのでしょうか?私はここで何か間違ったことをしているのでしょうか?
どのように解決するのですか?
わかりました。そう、これはバグなのです。
問題は、2つのレベルの
string.Format
が行われていることです。
は 第一 のレベルの書式は、次のようなものです。
string template = string.Format("Expected: {0}; Actual: {1}; Message: {2}",
expected, actual, message);
次に
string.Format
を、指定されたパラメータと一緒に使います。
string finalMessage = string.Format(template, parameters);
(明らかに文化が提供されていますし いくつかの のようなサニタイズがあります...しかし、十分ではありません)。
文字列に変換された後、期待値と実際の値そのものが中括弧で終わっていなければ、これは問題ないように見えます。
Size
. 例えば、最初のサイズは以下のように変換されます。
{Width=0, Height=0}
ということで、2段目の書式は以下のような感じです。
string.Format("Expected: {Width=0, Height=0}; Actual: {Width=1, Height=1 }; " +
"Message = Failed expected {0} actually is {1}", struct1, struct2);
...で、これが失敗している。痛そう。
実際、期待される部分と実際の部分に私たちのパラメータを使うようにフォーマットを騙すことで、本当に簡単にこれを証明することができます。
var x = "{0}";
var y = "{1}";
Assert.AreEqual<object>(x, y, "What a surprise!", "foo", "bar");
という結果になります。
Assert.AreEqual failed. Expected:<foo>. Actual:<bar>. What a surprise!
明らかに壊れています。
foo
を期待していなかったし、実際の値も
bar
!
基本的に、これは SQL インジェクション攻撃のようなものですが、より恐ろしくない文脈で
string.Format
.
回避策として
string.Format
を使うことができます。これによって、実際の値/期待される値でフォーマットした結果に対して、第2レベルのフォーマットが実行されるのを避けることができます。
関連
-
[解決済み】C#で四捨五入する方法
-
解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C# [解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C#.
-
[解決済み】HRESULTからの例外:0x800A03ECエラー
-
[解決済み】5.7.57 SMTP - MAIL FROMエラー時に匿名メールを送信するためにクライアントが認証されない
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み】URLから画像をダウンロードする方法
-
[解決済み】.NETのforeachループでコレクションがNULLの場合、NullRefExceptionが投げられるのはなぜですか?
-
[解決済み] 新しいExceptionを投げても、finally blockは実行されるのでしょうか?
-
[解決済み] intを無効なenum値にキャストすると例外が発生しないのはなぜですか?
-
[解決済み] この文字列拡張メソッドはなぜ例外を投げないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] エンティティタイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】WebForms UnobtrusiveValidationModeは、jqueryのScriptResourceMappingを必要とする
-
[解決済み] 'SubSonic.Schema .DatabaseColumn' 型のオブジェクトをシリアライズする際に、循環参照が検出されました。
-
[解決済み】Sequence contains no matching element(シーケンスにマッチする要素がない
-
[解決済み】ORA-01008: すべての変数がバインドされていません。これらはバインドされています。
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み】C# - パスに不正な文字がある場合
-
[解決済み】Linq 構文 - 複数列の選択
-
[解決済み] ...基礎となる接続は閉じられました。予期しないエラーが受信で発生しました
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない