zoukankan      html  css  js  c++  java
  • 从.Net框架Bug的提交到修复代码成功合并到.NET CoreFX主线

    从发现.NET Framework中SmtpClient的Bug并拿出解决方案,然后给微软开发者社区提交Bug开始,总共耗时一个多月,对Bug修复的代码最终被采纳,现已合并到.NET Core Libraries (CoreFX)主线中。

    修复记录https://github.com/dotnet/corefx/commit/94b1f1eae84fd4823cfa2bbdde6fc87c46b57908

    虽然对Bug修复实际生效的代码只有20个字符,但意义重大,这个Bug不遇上一点事没有,遇上了不对框架开刀是非常棘手的,而且备受折磨也稍微有点难摸得清头脑。

    相关详情见我的另外一篇博客《记录一次.Net框架Bug发现和提交过程:.Net Framework和.Net Core均受影响

    问题描述

    我们用SmtpClientSendAsyncSendMailAsync异步方法发送邮件,并且要求使用DeliveryFormat = SmtpDeliveryFormat.SevenBit 格式来编码中文内容,本来预期是邮件内容中带中文的SubjectAttachments file name 都会进行Base64编码。

    但实际结果是:如果邮件服务器支持SMTPUTF8扩展,那么异步发送SevenBit邮件并不会进行Base64编码,同步方法没有此问题。

    问题根源

    原因是在SmtpClient.SendMailCallback方法中,message.BeginSend allowUnicode参数直接使用的ServerSupportsEai,而不是统一的IsUnicodeSupported()

     private void SendMailCallback(IAsyncResult result)
     { 
        ......
         _message.BeginSend(_writer, DeliveryMethod != SmtpDeliveryMethod.Network, 
             ServerSupportsEai, new AsyncCallback(SendMessageCallback), result.AsyncState); 
        ......
     } 
    

    ServerSupportsEai改成IsUnicodeSupported()问题解决。就这20个字符的改动~

    另外附对现有带Bug的.Net框架修复方法

    比如使用的.NET Framework 4.7.2,纯天然原生自带此Bug,我们可以用我们的代码修复它。

    最开始测试时以为此方法无效,没想到是Hook错了地方,换到最深层次调用地方,一抓一个准。

    使用DotNetDetour库对.Net框架内方法进行Hook,找出SmtpClient.ServerSupportsEai最结果最终是从SmtpConnection.ServerSupportsEai得来的,也许是C#编译后把整个调用过程都优化掉了,变成了取值的地方直接调用的SmtpConnection中的方法,导致Hook前面的方法都是不会被执行,Hook SmtpConnection.ServerSupportsEai一抓一个准。

    附上Hook代码:

    public class Hook : IMethodMonitor {
    	public bool ServerSupportsEai {
    		[Monitor("System.Net.Mail", "SmtpConnection")]
    		get {
    			Console.WriteLine("Hook");
    			return !true?org():false;//什么情况下要Hook? AsyncLocal和CallContext上下文为什么在这里传不进来?
    		}
    	}
    	[Original]
    	public bool org() {
    		return false;
    	}
    }
    

    另外引出了另外一个折磨人Bug,异步环境下,ServerSupportsEai的调用栈中上下文怎么会丢失?难道哪里使用了类似ThreadPool.UnsafeXXX这种效果?我们没法通过CallContext(AsyncLocal)给Hook代码传参数,只能写死,不管调用方要不要修改返回值,都只能得到修改后的结果,尴尬不尴尬。

  • 相关阅读:
    Spring Boot
    Spring Boot – Jetty配置
    如何使ESLint在Visual Studio 2019和2017中工作: 2019 v16和2017> = v15.8
    CentOS 7 安装 Nginx
    HTTPS-使用Certbot自动配置Let’s Encrypt证书
    centos7升级内核到最新版本
    [C#.net]Connection Timeout和Command Timeout
    Redis中切换db
    Redis 模糊查询删除操作
    [Abp vNext 源码分析]
  • 原文地址:https://www.cnblogs.com/xiangyuecn/p/10122764.html
Copyright © 2011-2022 走看看