2019年C#项目中的十大bug

图片1

向所有错误爱好者致以问候。 新年快到了,因此该是对即将到来的一年进行评估的时候了。 按照传统,对PVS-Studio团队在2019年开放C#项目中发现的最有趣的错误进行评级。 准备好了吗 然后开始吧。

第十名:“让所有人困惑”


V3066传递给“ AdjustCellBorderStyle”方法的参数的可能错误顺序:“ isFirstDisplayedRow”和“ isFirstDisplayedColumn”。 DataGridViewComboBoxCell.cs 1934

protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { .... dgvabsEffective = AdjustCellBorderStyle( DataGridView.AdvancedCellBorderStyle, dgvabsPlaceholder, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedRow, // <= isFirstDisplayedColumn); // <= .... } 

文章“ WinForms:错误,Holmes ”中的错误 。 分析器指出,当将参数传递给方法时,最后两个参数被反转。 让我们看一下AdjustCellBorderStyle声明

 public virtual DataGridViewAdvancedBorderStyle AdjustCellBorderStyle( DataGridViewAdvancedBorderStyledataGridViewAdvancedBorderStyleInput, DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { .... } 

看来分析仪是正确的。 通常,某些参数是故意以相反的顺序传递的,例如为了交换某些变量。 但是看起来情况并非如此。 首先, 布尔类型变量令人困惑。 其次,方法的名称也很常见:没有“交换”或“反向”。 此外,犯这样的错误并不难:人们通常对行/列对的顺序有不同的认识。

第九名:“无限临近”


V3110'TryValidateModel '方法内可能进行的无限递归。 PrefixedModuleUpdater.cs 48

 public bool TryValidateModel(object model, string prefix) { return TryValidateModel(model, Prefix(prefix)); } 

文章“ 在Orchard CMS代码中搜索和分析错误”中的错误 。 犯了一个错误,该错误导致无限递归。 要了解如何发生此错误,您需要查看TryValidateModel方法的重载:

 public bool TryValidateModel(object model) { return _updateModel.TryValidateModel(model); } 

在第一种情况下,可能需要使用以下形式的调用:

 public bool TryValidateModel(object model, string prefix) { return _updateModel.TryValidateModel(model, Prefix(prefix)); } 

因为_updateModel类型为IUpdateModel ,所以已编译的代码,并且当前类还实现​​了IUpdateModel接口。

第八名:“尝试,找到”


V3091实证分析。 字符串文字中可能存在拼写错误:“管理组ID”。 “ Id”一词可疑。 Constants.cs 36

 public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id"; // <= public const string Recurse = "Recursively list the children of the management group"; public const string ParentId = "Parent Id of the management group"; public const string GroupName = "Management Group Id"; // <= public const string DisplayName = "Display Name of the management group"; public const string Expand = "Expand the output to list the children of the management group"; public const string Force = "Force the action and skip confirmations"; public const string InputObject = "Input Object from the Get call"; public const string ParentObject = "Parent Object"; } 

该错误来自“ Azure PowerShell:”基本无害 。”分析人员怀疑GroupName常量已使用错误字符串初始化。可能应该出现类似“ Management Group Name”的字样 。很难判断此错误的严重性,但这种情况非常罕见,并且很难发现。

第七名:“只是被忽略”


V3078重复调用'OrderBy'方法后,原始排序顺序将丢失。 使用“ ThenBy”方法保留原始排序。 GridModel.Selection.cs 107

 internal partial class GridModel { private void BuildCellSelectionRegions(....) { .... this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .OrderBy(c => c.RowItemInfo.LayoutInfo.Line)); } } 

文章“ 检查Telerik UI以使UWP熟悉PVS-Studio ”中的错误。 由于对已排序的集合重用了OrderBy ,因此先前排序的结果将丢失。 您必须使用ThenBy

 this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line)); 

这些错误是由于粗心或无知造成的。 我认为应该归咎于复制粘贴。

第六名:“代码已记录在案,”他们说


V3009这种方法总是返回一个相同的'true'值,这很奇怪。 MaskedTextProvider.cs 1529

 public bool Remove(out int testPosition, out MaskedTextResultHint resultHint) { .... if (lastAssignedPos == INVALID_INDEX) { .... return true; // nothing to remove. } .... return true; } 

文章“ 使用PVS-Studio静态分析器验证.NET Core库的源代码 ”中的错误。 该方法将始终返回true 。 是的,这是一个错误,但是还有其他事情很好奇。 该方法附有详细的注释:

从格式化的字符串中删除最后一个字符。 (删除虚拟字符串中的最后一个字符)。 退出时,out参数包含实际执行操作的位置。 此位置相对于测试字符串。 MaskedTextResultHint输出参数可提供有关操作结果的更多信息。 成功 返回 true 否则 返回 false

专注于最后一句话。 但是谁读过这些评论? 但是严重的是,例如在重构或调试时,这种错误很容易蔓延。 当方法的结果始终为true时 ,我们想检查该选项,那么,我们忘记了返回所有内容。

第五名:“立即索引我!”


V3102通过循环内的常量索引可疑访问“ seq”对象的元素。 XmlQueryRuntime.cs 738

 public bool MatchesXmlType(IList<XPathItem> seq, ....) { .... for (int i = 0; i < seq.Count; i++) { if (!CreateXmlType(seq[0]).IsSubtypeOf(....)) return false; } return true; } 

文章“ 使用PVS-Studio静态分析器验证.NET Core库的源代码 ”中的错误。 在遍历seq集合时, for循环在所有迭代中错误地仅使用对其第一个元素的访问(索引0而不是i )。

第四名:“仅仅一美元,还不够”


V3138字符串文字包含潜在的内插表达式。 考虑检查:e。 SSPIHandleCache.cs 42

 internal static void CacheCredential(SafeFreeCredentials newHandle) { try { .... } catch (Exception e) { if (!ExceptionCheck.IsFatal(e)) { NetEventSource.Fail(null, "Attempted to throw: {e}"); } } } 

文章“ 使用PVS-Studio静态分析器验证.NET Core库的源代码 ”中的错误。 似乎插入了字符串“尝试抛出:{e}” 。 由于缺少$字符,因此e异常的字符串表示形式不会替换为该字符串。 结果,该字符串将“按原样”使用。

第三名:“没有出路”


V3008 [CWE-563]连续两次为“ this.linker.s3.region”变量分配值。 也许这是一个错误。 检查行:116,114。AWSSDK.DynamoDBv2.Net45 S3Link.cs 116

 public string Region { get { .... } set { if (String.IsNullOrEmpty(value)) { this.linker.s3.region = "us-east-1"; } this.linker.s3.region = value; } } 

文章“ 寻找适用于.NET的Amazon Web Services SDK的源代码中的错误中的错误 。 在if块的主体中​​, return被跳过。 结果, this.linker.s3.region变量始终获取 ,包括空字符串和null

第二名:“变得有秩序!”


V3070在初始化“ LOCALE_USER_DEFAULT”变量时使用未初始化的变量“ LANG_USER_DEFAULT”。 NativeMethods.cs 890

 internal static class NativeMethods { .... public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); .... } 

文章“ WinForms:错误,Holmes ”中的错误 。 类字段的初始化顺序混合在一起。 要计算LOCALE_USER_DEFAULT字段的值,请使用LANG_USER_DEFAULT字段,该字段尚未初始化且值为0。代码中的其他任何地方均未使用LANG_USER_DEFAULT变量。 为了理解此错误导致的原因,编写了一个测试程序,其中包含WinForms代码中的方法。 为简单起见,一些实际常量被替换为其实际值:

 internal static class NativeMethods { public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(0x00, 0x01); public static int MAKELANGID(int primary, int sub) { return ((((ushort)(sub)) << 10) | (ushort)(primary)); } public static int MAKELCID(int lgid) { return MAKELCID(lgid, 0x0); } public static int MAKELCID(int lgid, int sort) { return ((0xFFFF & lgid) | (((0x000f) & sort) << 16)); } } class Program { static void Main() { System.Console.WriteLine(NativeMethods.LOCALE_USER_DEFAULT); } } 

启动后,控制台上将显示以下内容:0。现在,我们将通过交换LOCALE_USER_DEFAULTLANG_USER_DEFAULT字段的声明来更正错误。 程序的结果格式如下:1024。

第一名:“信任,但要验证”


与第一名总是很难的。 必须有一些非同寻常且非常有趣的东西。 最初,我为本文选择了20多个有趣的错误,但其中没有什么值得一提的。 然后我想起了我的同事谢尔盖·瓦西里耶夫(Sergey Vasiliev)的一篇文章,该文章致力于一个错误。 该错误的妙处在于它直接影响了我们分析仪的运行。 怎么了 从文章“ PVS-Studio如何在... PVS-Studio中使用的库中发现错误的历史 ”的标题中已经很清楚了。 同样,懒惰并没有被消除。 :)在这里,我完全感到as愧,将不对错误进行描述,但建议您按照本文的链接查找更多信息。 我保证-值得。 而且文章简短。

结论


我希望这些错误是有趣的,但是这篇文章并不累。 提醒您,您随时可以下载 PVS-Studio分析仪,以自己和第三方项目搜索错误,以取悦自己,朋友和同事。 让错误更少,更多时间自我完善! :)

你看过吗 恭喜您迈上了新的台阶! 在我们博客的以下文章中,重点介绍了2019年JavaC ++项目的最佳bug。

图片2




如果您想与讲英语的读者分享这篇文章,请使用以下链接:Sergey Khrenov。 2019年在C#项目中发现的十大错误

Source: https://habr.com/ru/post/zh-CN481178/


All Articles