Go1.13标准库http包重大bug
2019年11月21日,golang的官方github仓库提交了一个https://github.com/golang/go/issues/35750,该issue指出如果初始化 http.Server 结构体时指定了一个非空的 ConnContext 成员函数,且如果在该函数内使用了 context.Value 方法写入数据到上下文并返回,则 Context 将会以链表的方式泄漏。
据官方开发人员表示,该bug于1.13版本引进,目前已经在1.13.5修复。
ConnContext
<blockquote>ConnContext optionally specifies a function that modifies the context used for a new connection c.
</blockquote>ConnContext是用于更改新连接的context而设置的一个方法。然而,它把新context赋值给了被所有连接共享的一个变量。
代码如下:
<pre><code class="lang-go hljs"><span class="token keyword">type</span> Server <span class="token keyword">struct</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token comment">// ConnContext optionally specifies a function that modifies</span> <span class="token comment">// the context used for a new connection c. The provided ctx</span> <span class="token comment">// is derived from the base context and has a ServerContextKey</span> <span class="token comment">// value.</span> ConnContext <span class="token keyword">func</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> c net<span class="token punctuation">.</span>Conn<span class="token punctuation">)</span> context<span class="token punctuation">.</span>Context <span class="token operator">...</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>srv <span class="token operator">*</span>Server<span class="token punctuation">)</span> <span class="token function">Serve</span><span class="token punctuation">(</span>l net<span class="token punctuation">.</span>Listener<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> <span class="token operator">...</span> baseCtx <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">...</span> ctx <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithValue</span><span class="token punctuation">(</span>baseCtx<span class="token punctuation">,</span> ServerContextKey<span class="token punctuation">,</span> srv<span class="token punctuation">)</span> <span class="token keyword">for</span> <span class="token punctuation">{</span> rw<span class="token punctuation">,</span> e <span class="token operator">:=</span> l<span class="token punctuation">.</span><span class="token function">Accept</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">...</span> <span class="token keyword">if</span> cc <span class="token operator">:=</span> srv<span class="token punctuation">.</span>ConnContext<span class="token punctuation">;</span> cc <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> ctx <span class="token operator">=</span> <span class="token function">cc</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> rw<span class="token punctuation">)</span> <span class="token keyword">if</span> ctx <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"ConnContext returned nil"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token operator">...</span> <span class="token keyword">go</span> c<span class="token punctuation">.</span><span class="token function">serve</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre>问题出在<code>ctx = cc(ctx, rw)</code>,这一行错误的将<code>cc</code>方法生成的新context赋值给了全局的<code>ctx</code>变量。
修复方式
pull request diff 如下:
总结
通过此bug来看,对于开源代码,在使用之前还是应该了解其实现细节,即使是github的明星项目(甚至go官方sdk)都不能盲目相信。
参考来源:
<ol><li>https://github.com/golang/go/issues/35750</li><li>https://go-review.googlesource.com/c/go/ /208318/</li></ol> 到此这篇关于“Go1.13标准库http包重大bug”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!您可能感兴趣的文章:
Go1.13标准库http包重大bug
Go 语言十年而立,Go2 蓄势待发
Go Modules与GOPROXY 配置
Python新手常见问题八:标准库模块命名
Golang实践-error
php第三方库有哪些?
为什么要Web标准化,有何价值?
IE6下溢出多余文字解决方案Iebug
对话jQuery之父John Resig
GO 依赖管理工具go Modules(官方推荐)