2020幎にCプロゞェクトで芋぀かったトップ10゚ラヌ

image1.png


最埌に、このような困難な2020幎が終わりに近づいおいたす。぀たり、株匏を取埗するずきです。今幎、PVS-Studioチヌムは、オヌプン゜ヌスプロゞェクトでアナラむザヌによっお発芋されたさたざたなバグを扱った倚くの蚘事を䜜成したした。2020幎にCプロゞェクトで芋぀かったTOP゚ラヌで、それらの䞭で最も興味深いものをここで芋るこずができたす。ハッピヌビュヌむング



トップがどのように圢成されたか



このリストには、私の意芋では、同僚ず私が2020幎の蚘事で曞いた最も興味深いトリガヌが含たれおいたす。重芁な遞択基準は、察応するコヌドフラグメントで実際に間違いがあったずいう確信床でした。そしおもちろん、堎所を遞択したり配眮したりする際には、トリガヌの「面癜さ」が考慮されたしたが、これはすでに私の䞻芳的な意芋です。コメントでい぀でも挑戊できたす。



PVS-Studioメッセヌゞず、コヌド譊告が発行されたプロゞェクトの䞡方の芳点から、トップをできるだけ倚様化しようずしたした。このリストには、8぀の怜蚌枈みプロゞェクトの゜ヌスに関する怜出が含たれおいたす。同時に、蚺断ルヌルが繰り返されるこずはほずんどありたせん。ここで2回䌚うこずができるのは、 V3022ず V3106いいえ、私はそれらを䜜成したせんでしたが、明らかに、これらは私のお気に入りです。したがっお、ここでは倚様性が保蚌されおいたす:)。



さあ、始めたしょうトップ10



10䜍-新しい叀いラむセンス



私たちのトップの回答は、RavenDBプロゞェクトが䟋ずしお䜿甚されたLinuxおよびmacOSのCプロゞェクトのチェックに関する1人の非垞に優れた人物による蚘事から始たりたす 。



private static void UpdateEnvironmentVariableLicenseString(....)
{
  ....
  if (ValidateLicense(newLicense, rsaParameters, oldLicense) == false)
    return;
  ....
}
      
      





アナラむザヌの譊告 V3066「ValidateLicense」メ゜ッドに枡される匕数の順序が正しくない可胜性がありたす「newLicense」および「oldLicense」。 LicenseHelper.cs177Raven.Server



どうやら、ここで䜕が問題になっおいるのでしょうか。コヌドは非垞にうたくコンパむルされたす。なぜアナラむザヌは、最初にoldLicenseを転送し、次にnewLicenseを転送する必芁がある ず 刀断したのですかあなたはそれを掚枬したしたねValidateLicense宣蚀を芋おみたしょう 



private static bool ValidateLicense(License oldLicense, 
                                    RSAParameters rsaParameters, 
                                    License newLicense)
      
      





うわヌ、それは本圓です-最初に、叀いものがパラメヌタにあり、それから-新しいラむセンス。さお、あなたのこの動的分析はこれを捕らえるこずができたすか:)



いずれにせよ、トリガヌは興味深いものです。順序はそれほど重芁ではないかもしれたせんが、そのようなフラグメントを再確認する方が良いでしょう、同意したすか



9䜍-「FirstOrDefault」ず予期しない「null」



9䜍は今幎の初めに曞かれた蚘事「Playin "osu"、間違いを忘れないでください」からの返答でした 



public ScoreInfo CreateScoreInfo(RulesetStore rulesets)
{
  var ruleset = rulesets.GetRuleset(OnlineRulesetID);

  var mods = Mods != null ? ruleset.CreateInstance() 
                                   .GetAllMods().Where(....)
                                   .ToArray() : Array.Empty<Mod>();
  ....
}
      
      





゚ラヌが衚瀺されたすかそしお圌女はそうですアナラむザヌは䜕ず蚀っおいたすか



アナラむザヌの譊告 V3146 [CWE-476]「ルヌルセット」のnull逆参照の可胜性。 'FirstOrDefault'は、デフォルトのnull倀を返すこずができたす。 APILegacyScoreInfo.cs 24



はい、はい、繰り返したすが、必芁なすべおの情報を䞀床に提䟛したせんでした。実際、このコヌドには疑わしいものは䜕も衚瀺されたせん。結局のずころ、 アナラむザヌが教えおくれるFirstOrDefaultは、GetRulesetメ゜ッドの定矩に含たれおいたす 。



public RulesetInfo GetRuleset(int id) => 
  AvailableRulesets.FirstOrDefault(....);
      
      





ひどいビゞネス適切なものが芋぀かった堎合、メ゜ッドはRulesetInfoを返し たす。そうでなければ萜ち着いおnullを返し たす。そしお、それは呌び出しの結果が䜿甚される堎所ですでに撃ちたす。この堎合、ruleset.CreateInstanceを呌び出すずき 。



疑問が生じる可胜性がありたすnullがない堎合はどうなり たすかコレクションに垞に特定の芁玠がある堎合はどうなりたすか開発者がこれに぀いお確信しおいる堎合は、FirstOrDefaultの代わりにFirstを䜿甚しおみ たせん か



8䜍-Pythonからこんにちは



最初の3぀からの最埌のトリガヌは、RunUOプロゞェクトコヌドに察しお発行されたした。確認方法に関する蚘事は2月に曞かれたもので、こちらから入手でき たす。



芋぀かったフラグメントは非垞に疑わしいものですが、それが間違いであるかどうかを確実に刀断するこずは困難です。



public override void OnCast()
{
  if ( Core.AOS )
  {
    damage = m.Hits / 2;

    if ( !m.Player )
      damage = Math.Max( Math.Min( damage, 100 ), 15 );
      damage += Utility.RandomMinMax( 0, 15 );
  }
  else { .... }
}
      
      





アナラむザヌの譊告 V3043コヌドの操䜜ロゞックがそのフォヌマットに察応しおいたせん。ステヌトメントは右にむンデントされおいたすが、垞に実行されたす。䞭括匧が欠萜しおいる可胜性がありたす。地震.cs57



そうです-それはむンデントに぀いおです行の 損傷+ = Utility.RandomMinMax0、15は、m.Playerが falseの堎合にのみ実行されるべきだったよう です。..。同様に、むンデントが矎しさのためだけでなく、アプリケヌションのロゞックを定矩するためのPythonコヌドも機胜したす。しかし、Cコンパむラはこの問題に関しお異なる意芋を持っおいたす開発者の意芋はどうでしたか



䞀般に、この状況では、2぀のオプションがありたす。ここでは䞭括匧が実際に欠萜しおいお、すべおが正しく機胜しおいないか、すべおが正しく機胜しおいたすが、時間の経過ずずもに、これを間違いず芋なしお「修正」する人が必ずいるでしょう。



たぶん私は間違っおいお、そのようなこずを曞いおも倧䞈倫な堎合が本圓にありたす。あなたがこれらを知っおいるならば、コメントを曞いおください-私はそのような堎合に぀いお知りたいず思いたす。



7䜍-パヌフェクトたたはパヌフェクト-それが問題です



譊告を堎所に配垃するこずはたすたす困難になっおおり、osuに関する蚘事からこのリストの2番目のアラヌムに移っおい たす ..。



゚ラヌが衚瀺されるたでどのくらいかかりたすか



protected override void CheckForResult(....)
{
  ....
  ApplyResult(r =>
  {
    if (   holdNote.hasBroken
        && (result == HitResult.Perfect || result == HitResult.Perfect))
      result = HitResult.Good;
    ....
  });
}
      
      





アナラむザヌの譊告 V3001「||」の巊偎ず右偎に同䞀のサブ匏「result == HitResult.Perfect」がありたす。オペレヌタヌ。DrawableHoldNote.cs 266



それほど倚くはない ず思いたすが、PVS-Studioの譊告を読む必芁があるだけです。静的分析を䜿甚する開発者は通垞これを行いたす:)。䞊の前の堎所に぀いお議論するこずもできたすが、ここでは間違いが明らかです。HitResult列挙のどの特定の芁玠を2番目のPerfectの代わりにたあ、たたは最初の代わりにここで䜿甚すべきか を蚀うのは難しい ですが、結局、䜕かが明らかに間違っお曞かれおいたした。さお、それは倧䞈倫です-゚ラヌが芋぀かりたした、それはそれが簡単に修正できるこずを意味したす。



6䜍-nullではない合栌



6䜍は、Open XMLSDKプロゞェクトからのコヌドに察する非垞にクヌルな応答でした。それをチェックするこずに関する蚘事はここで読むこずができ たす。



開発者は、盎接割り圓おられた堎合でもnullを返さないプロパティを実装したいず考えおいたした 。そしお、どのような状況でもnullが曞き蟌たれないこずを確信できるのは本圓に玠晎らしい こずです。これがたったく状況ではないのは残念です



internal string RawOuterXml
{
  get => _rawOuterXml;

  set
  {
    if (string.IsNullOrEmpty(value))
    {
      _rawOuterXml = string.Empty;
    }

    _rawOuterXml = value;
  }
}
      
      





パヌサヌ譊告 V3008'_rawOuterXml '倉数には2回連続しお倀が割り圓おられたす。おそらくこれは間違いです。チェック行164、161。OpenXmlElement.cs 164 _rawOuterXmlには、nullかどうかに関係なく、 倀が蚘録さ



れるこずが わかりたす。このコヌドを泚意深く芋るず、nullがこのプロパティに曞き蟌たれるこずは決しおないず思うかもしれたせん -結局のずころ、チェックがありたすそうだずすれば、ツリヌの䞋にはギフトではなく、予期しない NullReferenceExceptionがありたす:(



5䜍-内郚にアレむがあるアレむからのショット



2020幎の䞊䜍5぀のトリガヌは、私が個人的にテストしたTensorFlow.NETプロゞェクトのアナラむザヌによっお発行されたした。リンクをクリックするず、 このプロゞェクトのチェックに関する蚘事を読むこずができたすああ、私はそこにいるみんなにたくさん䌚いたした。



ちなみに、実際のCプロゞェクトからの興味深い゚ラヌの䟋を芋たい堎合は、私のtwitterを賌読するこずをお勧めしたす 。そこで、奜奇心をそそるトリガヌず興味深いコヌドフラグメントを投皿する予定ですが、残念ながら、その倚くは蚘事に含たれたせん。お䌚いできおうれしいです :)



さお、トリガヌに移りたしょう



public TensorShape(int[][] dims)
{
  if(dims.Length == 1)
  {
    switch (dims[0].Length)
    {
      case 0: shape = new Shape(new int[0]); break;
      case 1: shape = Shape.Vector((int)dims[0][0]); break;
      case 2: shape = Shape.Matrix(dims[0][0], dims[1][2]); break; // <=
      default: shape = new Shape(dims[0]); break;
    }
  }
  else
  {
    throw new NotImplementedException("TensorShape int[][] dims");
  }
}
      
      





アナラむザヌの譊告 V3106むンデックスが範囲倖である可胜性がありたす。 「1」むンデックスは「dims」の境界を超えおいたす。 TensorShape.cs 107



実際、このトリガヌをどこに眮くかを遞択するのは非垞に興味深いので非垞に困難でしたが、他の人はこの点でそれほど遅れおいたせん。それで、ここで䜕が起こっおいるのかを理解したしょう。



内のアレむの数堎合 薄暗くなりが1に等しくない堎合、䟋倖NotImplementedExceptionのタむプである スロヌ。そしお、薄暗い堎合はどうなりたすか 正確に1぀の配列この「配列内の配列」内の芁玠の数がチェックされたす。 2の堎合に䜕が起こるかに泚意しおください。Shape.Matrixコンストラクタヌぞの匕数の1぀ずしお 、予期せず、dims [1] [2]が枡され たす。芚えおおきたしょう-dims配列にはいく぀の芁玠がありたした か



そうです、ちょうど1぀です-チェックしたばかりです 1぀の芁玠のみを含む配列から2番目の芁玠を取埗しようずするず、IndexOutOfRangeException䟋倖がスロヌされたす 。明らかに間違いです。しかし、それを修正する明癜な方法はありたすか



最初に頭に浮かぶのは倉化です dims [1] [2]から dims [0] [2]。゚ラヌはなくなりたすかどんなに再び同じ䟋倖がありたす。しかし今回は、この堎合、dims [0]の芁玠数が2に等しいずいう事実に関連したす 。開発者は、むンデックスに2぀の゚ラヌを続けお䜜成したしたかたたは、他の倉数をそこで䜿甚する必芁がありたすか誰が知っおいるか...アナラむザヌの仕事は間違いを芋぀けるこずであり、それを䜜った人たたは圌の同僚はそれを修正する必芁がありたす。



4䜍-存圚しないオブゞェクトのプロパティ



OpenRAチェックに関する蚘事から別のトリガヌがこのトップに入りたした 。おそらくそれはもっず䟡倀があるかもしれたせんが、運呜の意志によっお、このトリガヌは4䜍でした。たあ、それもかなり良いです今回、PVS-Studioが怜出できた゚ラヌを芋おみたしょう。



public ConnectionSwitchModLogic(....)
{
  ....
  var logo = panel.GetOrNull<RGBASpriteWidget>("MOD_ICON");
  if (logo != null)
  {
    logo.GetSprite = () =>
    {
      ....
    };
  }

  if (logo != null && mod.Icon == null)                    // <=
  {
    // Hide the logo and center just the text
    if (title != null)
      title.Bounds.X = logo.Bounds.Left;

    if (version != null)
      version.Bounds.X = logo.Bounds.X;
    width -= logo.Bounds.Width;
  }
  else
  {
    // Add an equal logo margin on the right of the text
    width += logo.Bounds.Width;                           // <=
  }
  ....
}
      
      





アナラむザヌの譊告 V3125'logo 'オブゞェクトは、nullに察しお怜蚌された埌に䜿甚されたした。チェックラむン236、222。ConnectionLogic.cs 236



ここで䜕に泚意を払う必芁がありたすかさお、初心者にずっお、 ロゎにはおそらくnullが含たれおいる可胜性があり たす。これは、定数チェックず、ロゎに曞き蟌たれた倀を返すGetOrNullメ゜ッドの名前の䞡方によっお瀺唆され たす 。もしそうなら、GetOrNullが実際にnullを返した 堎合に䜕が起こるかを考えおみたしょう 。最初はすべおが順調ですが、次に状態がチェックされたす ロゎ= null && mod.Icon == null。ご想像のずおり、結果はelse -branchおよび...に遷移し たす。nullが曞き蟌たれおいる倉数の Boundsプロパティにアクセスしようずする ず、-bdysh NullReferenceExceptionがドアをノックしおいたす。



3䜍-Schrödingerの芁玠



最埌に、ファむナリストの䞊䜍3䜍に入りたす。 2020幎の䞊䜍3぀のバグは、Nethermindプロゞェクトで芋぀かりたした。その怜蚌に぀いお、興味をそそるタむトル「1行のコヌド、たたはPVS-Studio CforLinuxを䜿甚したNethermindのチェック」で蚘事が曞かれたした 。゚ラヌは非垞に単玔ですが、特にプロゞェクトのサむズを考えるず、人間の目には芋えたせん。このトリガヌはその堎所に倀するず思いたすか



public ReceiptsMessage Deserialize(byte[] bytes)
{
  if (bytes.Length == 0 && bytes[0] == Rlp.OfEmptySequence[0])
    return new ReceiptsMessage(null);
    ....
}
      
      





アナラむザヌの譊告 V3106むンデックスが範囲倖である可胜性がありたす。 「0」むンデックスは「バむト」の境界を超えおいたす。 Nethermind.Network ReceiptsMessageSerializer.cs 50



おそらく、空のボックスで最初のものを取埗できるのはすばらしい こずですが、ここでは、そのような芁求によっおIndexOutOfRangeExceptionがスロヌされるだけ です。たった1぀の些现なこず-オペレヌタヌの小さな間違いであり、アプリケヌションはすでに正しく機胜しおいないか、クラッシュするこずさえありたす。



もちろん、「&&」の代わりに「||」を䜿甚する必芁がありたす。このような論理゚ラヌは、特に耇雑な蚭蚈では珍しいこずではありたせん。したがっお、自動モヌドでそのような瞬間をチェックするこずは非垞に䟿利です。



2䜍-2未満、3以䞊



次に、RavenDBプロゞェクトのコヌドにもう1぀のトリガヌを蚭定したした。怜蚌の結果に぀いおは、察応する蚘事でだけでなく読むこずができるこずを思い出させお ください。



さお、今歓迎したす-2020幎のトップ2の間違い



private OrderByField ExtractOrderByFromMethod(....)
{
  ....
  if (me.Arguments.Count < 2 && me.Arguments.Count > 3)
    throw new InvalidQueryException(....);
  ....
}
      
      





アナラむザヌの譊告 V3022匏 'me.Arguments.Count <2 && me.Arguments.Count> 3'は垞にfalseです。おそらく '||'ここでは挔算子を䜿甚する必芁がありたす。 QueryMetadata.cs861Raven.Server先ほど



、予期しない䟋倖がスロヌされた瞬間を確認したしたが、逆に、予期された䟋倖がスロヌされるこずはありたせん。そうでなければ、誰かが2未満、3



を超える数を思い぀いた堎合でも、それは砎棄され たす。同意しない堎合でも驚くこずではありたせんが、このトリガヌは以前のすべおのトリガヌよりも本圓に気に入っおいたす。はい、゚ラヌは非垞に単玔です。゚ラヌを修正するには、挔算子を倉曎するだけです。ちなみに、これはコンストラクタヌに枡されるメッセヌゞによっおも瀺唆されおいたす InvalidQueryException "無効なORDERBY'spatial.distancefrom、to、roundFactor '呌び出し、2〜3個の匕数が必芁、取埗" + me.Arguments.Count。



私は同意したす。これは基本的な芋萜ずしですが、少なくずもPVS-Studioを䜿甚しお芋぀かるたで、誰も気づいたり修正したりしたせんでした。これは、プログラマヌがどれほど経隓を積んでいおも、残念ながら人間であるこずを思い出させおくれたす。そしお、人々は、資栌に関係なく、さたざたな理由でそのような愚かな間違いさえ芋逃す可胜性がありたす。゚ラヌがすぐに発生する堎合もあれば、誀ったORDERBY呌び出しに関するメッセヌゞがナヌザヌに衚瀺されない理由を長い間掚枬できる堎合もありたす。



1䜍-+ 100コヌドの安党性の芋積もり



やった、やった、やった私たちは぀いにトリガヌにたどり着きたした。それは私が最も興味深く、面癜く、かっこいいなどを芋぀けたした。これは、ONLYOFFICEプロゞェクトのコヌドに察しお発行されたものであり、その分析は、今幎の最新蚘事の1぀である「ONLYOFFICEコミュニティサヌバヌバグがセキュリティ問題にどのように寄䞎するか」に 関連付けられおいたす。



さお、私はあなたにArgumentExceptionに぀いおの最も悲しい話を提瀺したす 、それは決しお投げられたせん



public void SetCredentials(string userName, string password, string domain)
{
  if (string.IsNullOrEmpty(userName))
  {
    throw new ArgumentException("Empty user name.", "userName");
  }
  if (string.IsNullOrEmpty("password"))
  {
    throw new ArgumentException("Empty password.", "password");
  }

  CredentialsUserName = userName;
  CredentialsUserPassword = password;
  CredentialsDomain = domain;
}
      
      





アナラむザヌの譊告 V3022匏 'string.IsNullOrEmpty "password"'は垞にfalseです。 SmtpSettings.cs 104



どの゚ラヌをどの堎所に配眮するかを遞択するのは非垞に困難でしたが、最初からこのトリガヌがすべおのリヌダヌでした。最も単玔なマむナヌなタむプミス-そしおコヌドはすでに正しく機胜しおいたせん。 IDEでの匷調衚瀺も、レビュヌも、叀き良き垞識も圹に立ちたせんでした。小さくおシンプルで矎しく曞かれた関数です。そしおここでも、PVS-Studioは専門家が芋逃しおいたものを芋぀けるこずができたした。



い぀ものように、悪魔は现郚にありたす。そのような詳现がすべお自動的に怜玢されたら玠晎らしいず思いたせんかもちろんそうでしょうそしお、開発者に静的アナラむザヌではできないこずをさせたしょう。圌は新しく矎しく安党なアプリケヌションを䜜成したす。倉数をチェックするずきに䜙分な匕甚笊を付けるかどうかを考えずに䜜成したす。



結論



2020幎の蚘事で10の興味深い間違いを芋぀けるのは簡単でした。しかし、それらを堎所に配垃するこずはかなりの䜜業であるこずが刀明したした。䞀方では、䞀郚のトリガヌは、高床なアナラむザヌメカニズムの動䜜をより適切に反映しおいたす。䞀方で、いく぀かの間違いはある皋床おかしいように芋えたす。提瀺された䜍眮の倚くは逆にするこずができたす-たずえば、トップ2ずトップ3。



それずも、このリストに他のポゞティブな点があるはずだず思いたすか実際、リンクをたどるこずで独自のトップを䜜成するこずもできたす 蚘事のリストに移動し、あなたの意芋で最もおいしいトリガヌを芋぀けたす。この堎合、コメントで2020幎のトップを捚おおください、私はそれを倧いに喜んで読みたす。リストを私のものよりも面癜くするこずができたすか



もちろん、譊告の「面癜さ」の問題はずにかく䞻芳的です。私の意芋では、応答を評䟡するための䞻な基準は、PVS-Studioからの譊告を芋たプログラマヌが、察応するコヌドの䜕かを倉曎するかどうかです。このリストは、フラグメントのトリガヌから䜜成されたものであり、私の意芋では、開発者が静的分析を䜿甚した方が芋栄えが良くなりたす。その䞊、あなた自身たたは他のいく぀かのプロゞェクトをチェックするこずによっおPVS-Studioを詊すこずに問題はありたせん。あなたはただリンクをたどる必芁がありたす 、そこに必芁なバヌゞョンのアナラむザヌをダりンロヌドし、小さなフォヌムに蚘入しおトラむアルキヌをリク゚ストしたす。



さお、これですべおです。ご枅聎ありがずうございたした。たたお䌚いしたしょう





この蚘事を英語を話す聎衆ず共有したい堎合は、翻蚳リンクを䜿甚しおくださいNikitaLipilin。 2020幎にCプロゞェクトで芋぀かったトップ10のバグ。



All Articles