-
Notifications
You must be signed in to change notification settings - Fork 7.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: luogu route parse error #14170
Merged
Merged
fix: luogu route parse error #14170
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Successfully generated as following: http://localhost:1200/luogu/daily - Success ✔️<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
>
<channel>
<title><![CDATA[洛谷日报]]></title>
<link>https://www.luogu.com.cn/discuss/47327</link>
<atom:link href="http://localhost:1200/luogu/daily" rel="self" type="application/rss+xml" />
<description><![CDATA[洛谷日报 - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)]]></description>
<generator>RSSHub</generator>
<webMaster>i@diygod.me (DIYgod)</webMaster>
<language>zh-cn</language>
<lastBuildDate>Wed, 03 Jan 2024 06:53:22 GMT</lastBuildDate>
<ttl>5</ttl>
<item>
<title><![CDATA[讨论 【日报#463】基于CYaRon的数据制造流程漫谈 - Luogu Spilopelia]]></title>
<description><![CDATA[<h1>写在前面</h1>
<p>本文旨在介绍基于 CYaRon 的信息学题目数据构造工作流,希望能帮助大家更加方便快捷地造出更强<del>更毒瘤</del>的测试数据,<del>避免因为出锅或强度不够而被喷烂</del>。</p>
<p>所有的引用材料已在文末附上,为避免有时 Github 因为一些奇奇怪怪的原因无法访问的情况,笔者找到了一份官方文档的民间镜像。在此感谢原作者 @czj_is_a_rookie。</p>
<h1>CYaRon 简介</h1>
<p>CYaRon 是由洛谷开发的基于 Python 的开源软件(但我们称之为轮子),用于便捷地生成 OI 题目的测试数据(并且在大多数情况下强度不低)。</p>
<p>其官方英文解释为 <strong>C</strong>YaRon <strong>Y</strong>et <strong>A</strong>nother <strong>R</strong>andom <strong>O</strong>lympic-i<strong>N</strong>formatics test data generator,<del>但又有谁会信呢明明就是一个二次元含量100%的名字诶</del>。<del>并且怎么又是递归缩写……</del></p>
<h1>CYaRon 入门</h1>
<blockquote>
<p>学会读文档是一个优秀程序员的基本素质——沃兹基·硕德</p>
</blockquote>
<p>官方文档给的非常详细,列举了大量实例,方便您快速入门。</p>
<h2>安装</h2>
<p>首先您要确保您的计算机上有 Python 环境,推荐至少为 Python 3,笔者电脑上是 <code>Python 3.9.2</code>,以下内容将以此版本为准。如果您没有 Python 开发环境或版本过低,请于 <a href="https://www.python.org/">Python官网</a> 下载。注意在安装时勾选“添加到环境变量”一项。</p>
<p>随后,打开命令行,运行以下命令:</p>
<pre><code>pip install cyaron</code></pre>
<p>等待进度条读完,下载完成!</p>
<p>笔者安装的 CYaRon 版本为 <code>0.4.3</code>,以下介绍将以此版本为准。</p>
<h2>编辑</h2>
<p>这里推荐使用 Visual Studio Code 作为您的 Python 编辑器,详情参见 <a href="https://www.luogu.com.cn/blog/GNAQ/VSC-guide">日报#12</a>,此处不再赘述。请注意您可能需要下载名为 $\text{Python}$ 的 VSCode 扩展插件,否则 Python 程序将无法正常被语法高亮。</p>
<h2>编写数据生成器</h2>
<p>在写一个完整的数据生成器之前,首先你得有一个标程。</p>
<p><del>但是如果没有的话也没关系,只是不能生成输出文件而已</del>。</p>
<p>首先,编译标程,得到一个可执行文件。请注意这个可执行文件的路径,以后会用到。</p>
<blockquote>
<p>如果您的计算机上有多个版本的 C/C++ 编译器,建议使用<strong>最新版</strong>的<strong>稳定版本</strong>或与比赛环境<strong>尽可能类似的</strong>编译器版本,避免因为编译器问题导致标程行为不符合预期从而使数据出锅。<strong>尽量不要碰那些 Profilling 版本的编译器,不然出锅都不知道怎么出的</strong>。同理,尽量不要给标程添加大于 <code>-O2</code> 的编译器优化,避免标程运行结果不理想。最后请确保您与标程提供者能够畅通联系<del>以便随时补锅</del>,并请 ta 确保标程中没有 UB。</p>
</blockquote>
<p>别问我怎么知道的。<code>MinGW-w64 GCC 10.3.0 64-bit Profiling</code> 版本的编译器有锅,随机抽风。</p>
<p>之后,新建一个 Python 文件,在第一行写下</p>
<pre><code class="language-python">from cyaron import *</code></pre>
<p>之后,您就可以调用 CYaRon 提供的所有函数了。</p>
<p>这是我目前正在参与出题的一道题目的数据生成器部分:</p>
<pre><code class="language-python">from cyaron import *
for id in range(1, 21):
test_data = IO(file_prefix="tree_", data_id=id)</code></pre>
<p>这样的话生成的数据组们长这个样子:</p>
<p><img src="https://s1.ax1x.com/2022/11/28/zULlxf.md.png" alt="zULlxf.md.png" referrerpolicy="no-referrer"></p>
<p>以此类推,一共有 $20$ 组数据。</p>
<p>在没有特殊指定 <code>input_suffix</code> 和 <code>output_suffix</code> 之前输入文件后缀名默认为 <code>.in</code>,输出文件后缀名默认为 <code>out</code>。当然您可以通过在函数中指定这两个变量来修改测试用例的后缀名。</p>
<p>如果您不想生成输出样例,可以在函数中指定 <code>disable_output=True</code>。</p>
<p>接下来可以根据题目需求编写您的数据生成器了。请记住您的所有问题基本都能在文档里得到解决。<del>如果文档里没有的话就手写吧。</del></p>
<p>最后,使用 <code>test_data.output_gen()</code> 来生成输出样例(如果 <code>disable_output</code> 为 <code>False</code>)。此函数的参数为标程<strong>编译出来的可执行文件</strong>的地址。<strong>不要往括号里放一个 <code>.cpp</code> 之类的东西,出锅都不知道怎么出的,还贼难 debug(因为你压根想不到会在最后一行出锅)。</strong></p>
<h1>多种数据范围的处理之道</h1>
<p>Python 没有大括号,这能让争论稍稍平息。但码风仍旧是重要的。</p>
<p>考虑如下例子,</p>
<blockquote>
<p>输入文件第一行两个整数 $n$,$m$,表示一个图边数和点数。<br>
接下来 $m$ 行一个 DAG,以 $u$,$v$,$w$ 的形式表示一条边。</p>
</blockquote>
<p>出题人非常贴心地在题目最后附上了表格如下。</p>
<p>$$
\begin{array}{|c|c|c|c|} \hline
\text{测试点编号} & n & m & w_i \\ \hline
1-5 & 1\leq n\leq 1000 & n-1\leq m\leq 2000 & 1\leq w_i\leq 300 \\ \hline
6-10 & 1\leq n\leq 20000 & n-1\leq m\leq 50000 & 1\leq w_i\leq 500 \\ \hline
11-20 & 1\leq n\leq 10^6 & n-1\leq m\leq5\times10^6 & 1\leq w_i\leq 500\\ \hline
\end{array}
$$</p>
<p>看到这里,是不是已经心跳加快,血压升高,开始问候出题人的直系亲属了?不要着急,看看你可以采用什么方法偷懒。</p>
<p>分析题目,发现并没有什么特殊性质(如果有的话也没关系,只需要加个特判)。这样的情况其实相当好处理。我们提供一个实例如下。</p>
<pre><code class="language-python">from cyaron import *
for id in range(1, 21):
test_data = IO(file_prefix="data_", data_id=id)
# 先把这几个变量定义了以避免作用域问题
MAXN = 0
MAXM = 0
MAXW = 0
if id <= 5:
MAXN = 1000
MAXM = 2000
MAXW = 300
elif id <= 10: # 即 C++ 中的 else if
MAXN = 20000
MAXM = 50000
MAXW = 500
else:
MAXN = int(1e6) # 不要把 C++ 的 (int)1e6 带到这里来!
MAXM = int(5e6)
MAXW = 500
n = randint(500, MAXN) # 保证最低数据强度
m = randint(n - 1, MAXM) # DAG 的性质,边数大于等于节点数-1
graph = Graph.DAG(n, m) # n 点 m 边的 DAG
test_data.writeln(n, m)
test_data.writeln(graph)
test_data.output_gen("假装这是标程地址")</code></pre>
<p>是不是很简单?同样地,特殊性质也可以用这种方法来判断。另外,Python 的部分细节语法和各位熟悉的 C++ 有较大差异,不要把 C++ 的一些偷懒写法带入 Python。</p>
<h1>成为负责任的数据人</h1>
<blockquote>
<p><a href="https://www.luogu.com.cn/problem/P8819">再完美不过的反面教材:CSP-S 2022 T3</a></p>
</blockquote>
<p>图论题对于数据人的挑战最大。这些问题往往会让只会随机生成样例的数据人体验到<strong>输出 <code>NO</code> 能拿满分</strong>、<strong>输出 <code>1</code> 能拿满分</strong>、<strong>打个奇奇怪怪的乱搞能拿满分</strong>、<strong>打个离谱到半人马座的贪心能拿满分</strong>等一系列<strong>快乐</strong>,并让自己的直系亲属在赛后总结帖中陷入危险。</p>
<p>如果这种情况出现了,作为数据人,我们就要完成对于我们来说最艰巨的任务:<strong>构造数据</strong>。</p>
<p>我们要想有没有一些性质能让问题有解。如果可以的话,就尽可能利用 CYaRon 已有的功能实现(基本都可以)。比如文档里的这个示例:</p>
<pre><code class="language-python">binary_tree = Graph.binary_tree(n, 0.4, 0.35)
# 生成一棵n个节点的二叉树,其中节点有40%的概率是左儿子,35%的概率是右儿子,25%的概率被随机选择</code></pre>
<p>这样的话不仅方便快捷,还不容易出锅。记住:<strong>多一事不如少一事</strong>。</p>
<p>如果你还不能解决问题,那么接下来,你面前的有两种可能:</p>
<ol>
<li>有明确的特殊性质,但是 CYaRon 库函数里没有;</li>
<li>没有<strong>明确</strong>的特殊性质(但是它总有一些性质让问题可解)。</li>
</ol>
<p><img src="https://s1.ax1x.com/2022/11/28/zUqXKU.md.png" alt="zUqXKU.md.png" referrerpolicy="no-referrer"></p>
<h3>对于第一种情况,</h3>
<ol>
<li>去 Github 上面提 issue,由于响应时间过长故不推荐,但是被开发者看到的 issues 能帮之后的数据人们减少困难,所以提 issue 就是在为 CYaRon 的开发做贡献。</li>
<li>自力更生,丰衣足食(继续往下看)。</li>
</ol>
<h3>对于第二种情况:</h3>
<p>我们要想如果有解的情况下是什么样的。是不是数据一定符合一些特征然后经过标程里一些奇奇妙妙的操作最后得到最终的答案的?我们没办法固定它的性质去找答案,那我们固定答案有解去反推特征是否可行呢?在大多数题目下是可行的。这里只是提供一个思想,因为不同的题目有不同的特征。如果您想到用什么样的算法能够解决问题但是不知如何实现的话,请继续往下看。</p>
<h2>学会利用外部工具</h2>
<p>现在我们面临的问题都是用 Python 和 CYaRon 难以解决的那些毒瘤性质。我们来看这样一个例子。</p>
<blockquote>
<p>题目:一笔画问题的经典模型。给定一个无向连通图,如果存在一笔画方案就输出 <code>YES</code>,不存在就输出 <code>NO</code>。</p>
</blockquote>
<p>如果随机生成数据,那么除非你拯救了地球积攒了巨量 RP,不然你的每一个输出样例都会是这个样子:</p>
<p><img src="https://s1.ax1x.com/2022/11/28/zUOspt.md.png" alt="zUOspt.md.png" referrerpolicy="no-referrer"></p>
<p>接下来我们要考虑特殊性质。如果这个问题有解,那么这张无向图里要么没有度数为奇数的点,要么只有两个度数为奇数的点。于是我们的第一反应应该是去翻 CYaRon 文档,但是很遗憾,开发者们并没有开发给定度数序列生成图的功能。</p>
<p>分析这个问题,首先确定一个图里一定只有偶数个奇数点。那么显然,使数据全部是 <code>NO</code> 的原因是奇数点过多。我们考虑如何减少奇数点的数量。</p>
<p>显然,给一个奇数加上 $1$ 之后就会变成偶数,那么在两个奇数点之间加一条边就能把这两个奇数点同时消为偶数点。接下来的思路非常显然:</p>
<ol>
<li>读入整张图并统计奇数点个数,把奇数点编号记录下来;</li>
<li>随机抽出两个奇数点相连,然后将其统计为偶数点;</li>
<li>重复第二步直至奇数点数量小于等于 $2$;</li>
<li>更新边数,重新将图输出。</li>
</ol>
<p>为了方便起见,不妨把奇数点全部消去(此时全部为偶数点)后给一部分的测试样例增加一个节点,让其与 $1$ 号节点相连(此时这些测试样例里面有两个度数为奇数的点)。不难看出,这样既能减少随机数的运算,还不会影响数据强度。</p>
<p>我们提供一种可能的实现如下。</p>
<pre><code class="language-cpp">#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int dg[MAXN];
queue<int> lst;
vector<int> e[MAXN];
int main()
{
srand((unsigned)time(NULL));
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
e[u].push_back(v);
dg[u]++;
dg[v]++;
}
for (int i = 1; i <= n; i++)
{
if (dg[i] % 2) lst.push(i);
}
while (!lst.empty())
{
int u = lst.front(); lst.pop();
int v = lst.front(); lst.pop();
e[u].push_back(v);
m++;
}
int typ = rand() % 2;
if (typ == 1)
{
n++;
e[1].push_back(n);
m++;
}
cout << n << " " << m << endl;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < e[i].size(); j++)
{
cout << i << " " << e[i][j] << endl;
}
}
return 0;
}
</code></pre>
<p>如果您对图论足够熟练并且这是一道传统 OI 题目,您应该不用 $15$ 分钟就能切掉它。但是我们要让这个程序与 CYaRon 联动。如何实现?</p>
<p>首先我们要用 CYaRon 生成一张随机图并将其输出到输出文件,再用我们的 C++ 程序来完成剩下的步骤。这里是 CYaRon 核心代码的一种实现。</p>
<pre><code class="language-python">n = randint(1, MAXN)
m = randint(n, MAXM)
graph = Graph.UDAG(n, m)
test_data.input_writeln(n, m)
test_data.input_writeln(graph.to_str(output = Edge.unweighted_edge))</code></pre>
<p>(原谅这糟糕的语法高亮吧)</p>
<p>随后,<strong>使用 <code>test_data.flush_buffer()</code> 将输出缓冲区的内容写入文件</strong>以确保刚才所有的 <code>input_writeln()</code> 函数输出的内容全部都到了我们的输入文件里而不是缓冲区中。</p>
<p>随后,调用我们刚才写的 C++ 程序。现在问题有二:</p>
<ol>
<li>如何让这个程序向文件里输出?</li>
<li>如何让这个程序知道它应该输出到哪里?</li>
</ol>
<p>而第一个问题有无数种解答方案。大家在 CCF 系列比赛中应该已经很熟悉文件输入输出了;而第二个问题则需要略施小计。</p>
<p>众所周知,标准的 C++ 主函数是有参数的(如下):</p>
<pre><code class="language-cpp">int main(int argc, char* argv[])
{
}</code></pre>
<p>只不过我们平时把主函数的参数省略了而已。而这个 <code>argc</code> 和 <code>argv</code> 是什么东西呢?<code>argc</code> 是 <code>argv</code> 数组的大小,而 <code>argv</code> 是程序的所有<strong>外部参数</strong>,而外部参数平时只有一个,就是程序名本身。</p>
<p>我们不妨从此入手。在 Python 中带参数地调用可执行文件,然后在主函数内作出反应。修改 Python 代码如下:</p>
<pre><code class="language-python">n = randint(1, MAXN)
m = randint(n, MAXM)
graph = Graph.UDAG(n, m)
test_data.input_writeln(n, m)
test_data.input_writeln(graph.to_str(output = Edge.unweighted_edge))
test_data.flush_buffer()
opr = ".\get.exe " + "\"galaxy_" + str(id) + ".in\""
status = os.system(opr)</code></pre>
<p>别忘了在 Python 文件开头添加 <code>import os</code>,在 Linux 环境下请把 <code>.\get.exe</code> 换为 <code>./get</code>。</p>
<p>而此中的 <code>opr</code> 变量即是我们调用 <code>get.exe</code> 的命令。它形如:</p>
<pre><code class="language-plain">.\get.exe "galaxy_2.in"</code></pre>
<p>其中 <code>.\get.exe</code> 是运行 <code>get.exe</code> 的命令,<strong>而 <code>"galaxy_2.in"</code> 则是 <code>argv</code> 数组的第二个值,即 <code>argv[1]</code>。这样,我们就能够在 C++ 程序里取到这个值,从而打开对应的文件。</strong></p>
<p>接下来我们在此附上添加了文件输入输出和主函数传参的 <code>get.cpp</code> 代码,大家可以对比添加前与这版本的差异。基于多样化文件输入输出的考虑(有些题目要覆写源文件,有些要在源文件后追加),这里使用 C++ 风格的文件输入输出流。</p>
<pre><code class="language-cpp">#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int dg[MAXN];
queue<int> lst;
vector<int> e[MAXN];
int main(int argc, char* argv[])
{
srand((unsigned)time(NULL));
ifstream read;
ofstream write;
read.open(argv[1], ios::in);
int n, m;
read >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
read >> u >> v;
e[u].push_back(v);
dg[u]++;
dg[v]++;
}
for (int i = 1; i <= n; i++)
{
if (dg[i] % 2) lst.push(i);
}
while (!lst.empty())
{
int u = lst.front(); lst.pop();
int v = lst.front(); lst.pop();
e[u].push_back(v);
m++;
}
int typ = rand() % 2;
if (typ == 1)
{
n++;
e[1].push_back(n);
m++;
}
read.close();
write.open(argv[1], ios::out);
write << n << " " << m << endl;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < e[i].size(); j++)
{
write << i << " " << e[i][j] << endl;
}
}
write.close();
return 0;
}
</code></pre>
<p>可以看到,本代码中采用的文件打开方式是 <code>ios::out</code>,这么做会覆写文件。若想在文件后追加内容,请使用 <code>ios::app</code>。</p>
<p><strong>总结一下</strong>,笔者认为面对此种情况最快速的方法是用熟悉且功能强大的语言修改 CYaRon 造出的数据从而手动实现 CYaRon 不能实现的特殊性质并保证数据强度。<del>当然也可以在完善功能之后 Pull Request,为 CYaRon 的开发提供自己的微薄之力</del>。</p>
<p>同理,当出题人要求生成一些有特殊性质的数据时也可以采用这种方法。</p>
<h1>为生成器提速</h1>
<p>众所周知 Python 的常数巨大,在使用 CYaRon 造数据时会比 Testlib 慢很多,但胜在简单好写,不容易出锅。</p>
<p>这也是上文所述构造特殊性质时使用 C++ 的原因。当生成器过于复杂或者特殊性质过多且数据范围过大时(特别是时间紧张的情况下),Python 巨大的常数将会成为压垮你心态的最后一根稻草。所以第一个提速方法是:<strong>在需要大量枚举以构造数据时使用 C++ 等小常数语言以提高运行效率</strong>。但请注意如果您过于追求常数小导致生成器出现 UB 或者写锅了就得不偿失了。</p>
<p>而第二种方法文档里亦有讲述:<strong>使用 PyPy 而非 Python</strong>。</p>
<blockquote>
<p>PyPy 是一个以 Python 编写的 Python 语言的 JIT 编译器。对于具有大量循环和重复操作的程序,使用 PyPy 可以让执行效率获得成倍的提升。—— CYaRon 文档</p>
</blockquote>
<h1>补锅</h1>
<p>众所周知数据人不是在补锅就是在出锅的路上。这里提供一些调试技巧。</p>
<ul>
<li>重新阅读一遍题面,确定自己没有少造某些内容。</li>
<li>仔细阅读文档,检查自己有没有搞错某函数的用法。</li>
<li>输出中间变量。CYaRon 使用专用的函数来进行文件输出,所以 <code>print()</code> 函数仍可实现输出到控制台的功能,十分方便。或者实在不济也可以写个枚举程序看看哪里不正常。</li>
<li>造一组小范围的数据,然后肉眼 debug。</li>
<li>检查一些容易踩坑的错误(比如字符串的大小写,输出带权图还是不带权图,数据范围有没有多打一个 <code>0</code> 之类的)。</li>
<li>更换编译器重新编译标程。</li>
<li>联系标程提供者和验题人确保标程无误。</li>
<li>仔细看一遍生成器和标程,确保没有调试时遗留的输出语句没有注释。</li>
<li>看看珂爱的标程提供者有没有<strong>贴心</strong>地为你写上 <code>freopen</code>,如果有的话把它删掉并<strong>友好地告知 ta 下次不要这么干了</strong>(会使每个输出文件里面都是 <code>0</code>)。</li>
<li>删了重写。</li>
</ul>
<h1>其他数据人需要考虑的方面</h1>
<ul>
<li>Subtask 及分数配置:尽量通过编辑 <code>config.yml</code> 完成,便于统一管理。</li>
<li>Special Judge:请出门左转 <a href="https://studyingfather.blog.luogu.org/testlib-guide">Testlib</a>。</li>
</ul>
<h1>Reference</h1>
<blockquote>
<p><a href="https://www.luogu.com.cn/discuss/11410">洛谷官方介绍帖</a><br>
<a href="https://github.com/luogu-dev/cyaron">Github 项目地址</a><br>
<a href="https://www.luogu.com.cn/paste/woylvw96">文档民间镜像</a></p>
</blockquote>
<br>
]]></description>
<pubDate>Wed, 03 Jan 2024 06:53:22 GMT</pubDate>
<guid isPermaLink="false">https://www.luogu.com.cn/discuss/47327#基于CYaRon的数据制造流程漫谈</guid>
<link>https://www.luogu.com.cn/discuss/47327</link>
<author><![CDATA[CharlesZiy]]></author>
</item>
</channel>
</rss>
|
github-actions
bot
added
the
Auto: Route Test Complete
Auto route test has finished on given PR
label
Jan 3, 2024
TonyRL
reviewed
Jan 4, 2024
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully generated as following: http://localhost:1200/luogu/daily - Success ✔️<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
>
<channel>
<title><![CDATA[洛谷日报]]></title>
<link>https://www.luogu.com.cn/discuss/47327</link>
<atom:link href="http://localhost:1200/luogu/daily" rel="self" type="application/rss+xml" />
<description><![CDATA[洛谷日报 - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)]]></description>
<generator>RSSHub</generator>
<webMaster>i@diygod.me (DIYgod)</webMaster>
<language>zh-cn</language>
<lastBuildDate>Mon, 08 Jan 2024 01:38:56 GMT</lastBuildDate>
<ttl>5</ttl>
<item>
<title><![CDATA[讨论 【日报#464】Awesome sanitizers - Luogu Spilopelia]]></title>
<description><![CDATA[<p>C++ 太复杂了!即使编写的时候非常小心,也不能完全杜绝内存安全问题的出现。就算是算法竞赛时编写的百余行简短代码,也时不时会有数组越界、变量未初始化、未定义行为等问题困扰我们。</p>
<p>在算法竞赛短短几个小时中,花费时间检查这种与算法本身无关的错误,无疑是浪费时间。那有没有什么工具能帮助我们检查这类错误呢?</p>
<p>Sanitizers 是由 Google 发起的一套开源工具集,包含了数个帮助开发者查找 C++ 代码中疑难杂症的工具。其中有些工具,在算法竞赛领域也十分实用。</p>
<h2>AddressSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">AddressSanitizer</a> 简称 ASan,可以帮助我们检查代码中的内存使用问题。</p>
<p>它从 LLVM 3.1 起被集成到 Clang 中,从 GCC 4.8 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=address</code> 来使用它。</p>
<h3>解引用悬垂指针</h3>
<p>来看一段显然存在问题的代码:</p>
<pre><code class="language-cpp">int main() {
char *x = new char[10];
delete[] x;
return x[5];
}</code></pre>
<p>我们申请了一段长度为 10 的 <code>char</code> 数组,随后释放了它,这时我们再取出数组的第 5 个元素——然而这个位置的内存已经被我们释放掉了!</p>
<p>像这种使用已经被释放的内存的问题,我们称之为<strong>解引用悬垂指针</strong>。让我们试试 ASan 能不能帮我们发现这个问题吧!</p>
<p>首先尝试编译这份代码:</p>
<pre><code class="language-bash">g++ main.cpp -o main -g -fsanitize=address</code></pre>
<p>代码顺利编译,看上去什么都没有发生?不要着急,我们试试执行编译出的程序:</p>
<pre><code class="language-bash">./main</code></pre>
<p>程序崩溃了!同时给出了很长一段错误信息:</p>
<pre><code class="language-plain">=================================================================
==19311==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000015 at pc 0x562f45c941de bp 0x7ffc3b87b640 sp 0x7ffc3b87b630
READ of size 1 at 0x602000000015 thread T0
#0 0x562f45c941dd in main /home/yur/Workspace/Codes/main.cpp:4
#1 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7ff979dca349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x562f45c940a4 in _start ../sysdeps/x86_64/start.S:115
0x602000000015 is located 5 bytes inside of 10-byte region [0x602000000010,0x60200000001a)
freed by thread T0 here:
#0 0x7ff97a38e35a in operator delete[](void*) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:155
#1 0x562f45c941a1 in main /home/yur/Workspace/Codes/main.cpp:3
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
previously allocated by thread T0 here:
#0 0x7ff97a38d7f2 in operator new[](unsigned long) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:98
#1 0x562f45c9418a in main /home/yur/Workspace/Codes/main.cpp:2
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
SUMMARY: AddressSanitizer: heap-use-after-free /home/yur/Workspace/Codes/main.cpp:4 in main
Shadow bytes around the buggy address:
0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[fd]fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==19311==ABORTING</code></pre>
<p>通过这段错误信息,我们可以看到 ASan 告诉我们,在 <code>main.cpp</code> 的第 4 行出现了一个 <code>heap-use-after-free</code> 错误,也就是我们在释放了某块堆内存后又使用了它。</p>
<p>不仅如此,它还告诉我们这块内存是在 <code>main.cpp</code> 的第 2 行申请的,在 <code>main.cpp</code> 的第 3 行被释放掉,并且打印出了这三个地方的调用栈!</p>
<p>也就是说,ASan 很好地完成了它的工作,但是是在运行时而不是编译时。这听上去有些令人沮丧,但这已经是最好的结果了,因为很多运行时错误只有在特定的输入下才会出现,在编译时发现它们是不可能的!</p>
<p>换一个角度想想,利用 ASan,我们可以在遇到运行时错误的时候,快速定位到错误的原因,以及发生错误的位置,这已经极大地方便调试了!</p>
<h3>全局数组越界</h3>
<p>看到这里,你可能会想:好吧 ASan 确实是个很棒的工具,可是在算法竞赛中我们真的很少很少会手动分配堆内存,事实上如果不使用 STL,我的程序可能根本不会用到任何堆内存,那么 ASan 对我来说不就没有用处了吗?</p>
<p>我们来看一段更贴近算法竞赛的,显然存在问题的代码:</p>
<pre><code class="language-cpp">#include <iostream>
constexpr int N = 100010;
int n, a[N];
int main() {
for (int i = 0; i < N; ++ i)
a[i] = i;
std::cin >> n;
std::cout << a[n] << std::endl;
return 0;
}</code></pre>
<p>我申请了一个长为 $N$ 的全局数组——这种做法在算法竞赛中很常见,然后我将数组中每个位置的值初始化为它的下标。</p>
<p>接着我们输入了一个 $n$,并输出下标为 $n$ 的位置的值。这太糟糕了!当输入的 $n$ 足够大的时候,这段代码显然会出现数组越界!</p>
<p>让我们再看看 ASan 的表现:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/2709697251.gif" alt="global-buffer-overflow" referrerpolicy="no-referrer"></p>
<p>不出所料,ASan 也能检测到这个错误,它告诉我们在 <code>main.cpp</code> 的第 12 行出现了一个 <code>global-buffer-overflow</code> 错误:</p>
<pre><code class="language-plain">=================================================================
==65354==ERROR: AddressSanitizer: global-buffer-overflow on address 0x558afdb55f68 at pc 0x558afdaf12e3 bp 0x7fff39a9d580 sp 0x7fff39a9d570
READ of size 4 at 0x558afdb55f68 thread T0
#0 0x558afdaf12e2 in main /home/yur/Workspace/Codes/main.cpp:12
#1 0x7fc18ed9c28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7fc18ed9c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x558afdaf1124 in _start ../sysdeps/x86_64/start.S:115
0x558afdb55f68 is located 0 bytes to the right of global variable 'a' defined in 'main.cpp:5:8' (0x558afdaf44c0) of size 400040
SUMMARY: AddressSanitizer: global-buffer-overflow /home/yur/Workspace/Codes/main.cpp:12 in main
Shadow bytes around the buggy address:
0x0ab1dfb62b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ab1dfb62be0: 00 00 00 00 00 00 00 00 00 00 00 00 00[f9]f9 f9
0x0ab1dfb62bf0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==65354==ABORTING</code></pre>
<h3>以及…</h3>
<p>除此之外,ASan 还能检测堆栈上数组的越界、使用离开作用域时被析构的对象、初始化顺序导致的 bug、内存泄漏等疑难杂症。由于它们在算法竞赛中出现得较少,这里就不多赘述。</p>
<p>值得一提的是,既然 ASan 是在运行时进行的检测,那它就必然会对程序的效率产生一定影响。经过<a href="https://github.com/google/sanitizers/wiki/AddressSanitizerPerformanceNumbers">测试</a>,开启 ASan 后的程序效率平均只有原先的一半左右。这个损失会根据平台和程序的不同而有所不同,但无论如何,请记得在进行<strong>重视效率</strong>的测试(如测试你的程序执行大样例时是否会超时)时关掉 ASan 以保证测试结果准确。</p>
<h2>UndefinedBehaviorSanitizer</h2>
<p><a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">UndefinedBehaviorSanitizer</a> 简称 UBSan,可以帮助我们检查代码中的未定义行为。</p>
<p>它从 LLVM 3.3 起被集成到 Clang 中,从 GCC 4.9 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=undefined</code> 来使用它。</p>
<h3>按位位移溢出</h3>
<pre><code class="language-cpp">int main() {
int x = 42;
x <<= 27;
return 0;
}</code></pre>
<p>上面的代码,按位左移的时候会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:3:5: runtime error: left shift of 42 by 27 places cannot be represented in type 'int'</code></pre>
<h3>数值溢出</h3>
<pre><code class="language-cpp">using i64 = long long;
constexpr int mod = 998244353;
int main() {
int x = 114514;
int y = 1919810;
x = ((i64)x * x + y * y) % mod;
return 0;
}</code></pre>
<p>上面的代码,<code>y * y</code> 的部分会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:9:23: runtime error: signed integer overflow: 1919810 * 1919810 cannot be represented in type 'int'</code></pre>
<h3>使用空指针</h3>
<pre><code class="language-cpp">#include <iostream>
struct Node {
Node *left, *right;
int value;
Node(int _value):
left(nullptr),
right(nullptr),
value(_value) { }
~Node() {
delete left;
delete right;
}
};
void print(Node *now) {
if (now->left != nullptr)
print(now->left);
printf("%d ", now->value);
if (now->right != nullptr)
print(now->right);
}
int main() {
Node *root = new Node(5);
root->left = new Node(3);
root->right = new Node(8);
root->left->right = new Node(4);
print(root);
delete root;
print(nullptr);
return 0;
}</code></pre>
<p>上面的代码是使用指针实现的简单的二叉树,其中 <code>print</code> 函数存在一个致命的问题:如果传入的参数本身是空指针,它就会在 <code>now->left</code> 这一步对空指针取左儿子,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:19:12: runtime error: member access within null pointer of type 'struct Node'</code></pre>
<p>如果希望 UBSan 打印出错位置的调用栈,可以在执行程序时加上 <code>UBSAN_OPTIONS=print_stacktrace=1</code> 环境变量:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/1177270905.gif" alt="stacktrace" referrerpolicy="no-referrer"></p>
<h3>除此之外…</h3>
<p>UBSan 还能检测十数种未定义行为,并且每种未定义行为是否需要被检测可以通过编译参数自由控制。与 ASan 相同的是,UBSan 也会影响程序运行效率,在实际使用时请务必注意!</p>
<h2>ThreadSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki#threadsanitizer">ThreadSanitizer</a> 简称 TSan,可以帮助我们检查多线程代码中的数据竞争。</p>
<p>算法竞赛不涉及多线程程序,因此这里不讨论 TSan 相关内容,有兴趣可以自行了解。</p>
<h2>MemorySanitizer</h2>
<p><a href="https://clang.llvm.org/docs/MemorySanitizer.html">MemorySanitizer</a> 简称 MSan,可以帮助我们检查对未初始化的值的使用。</p>
<p>它从 LLVM 4.0 起被集成到 Clang 中。而不幸的是,GCC 并没有集成这个工具。你只能通过在 Clang 中使用 <code>-fsanitize=memory</code> 参数来使用它。</p>
<pre><code class="language-cpp">#include <iostream>
// please ignore unused `argv` :)
int main(int argc, char *argv[]) {
int a[10];
for (int i = 2; i < 10; ++ i)
a[i] = i;
int x = a[argc];
int y = x * 2;
if (y == 0) {
std::cout << "Hello" << std::endl;
} else {
std::cout << "MSan" << std::endl;
}
return 0;
}</code></pre>
<p>上面的代码中,当我们通过 <code>./main</code> 执行程序时,<code>argc</code> 的值将会为 $1$,然而我们没有初始化 <code>a[1]</code>,MSan 将会在运行时报错:</p>
<pre><code class="language-plain">==95226==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55a96ddb3c96 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7f1b4f9d628f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7f1b4f9d6349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x55a96dd221d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<p>可以发现,MSan 直到第 12 行 <code>if (y == 0)</code> 处才报错,这是因为 MSan <strong>不会</strong>在读取未初始化值时<strong>立即</strong>报错,而是会等到这个值影响程序执行时才报错!在此之前,它会跟踪并记录这个未初始化值产生的影响。</p>
<p>如果一个未初始化值经过很远的传播后才引发 MSan 报错,你可能得花很大力气才能找到这个值是在哪里产生的。这时你可以选择在编译时加上 <code>-fsanitize-memory-track-origins</code> 参数,这样 MSan 报错时会从最初的未初始化值开始追踪,打印它的每一次移动,直到来到报错的位置:</p>
<pre><code class="language-plain">==96812==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x559164b57fe0 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7fd4af63f349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x559164ac61d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
Uninitialized value was stored to memory at
#0 0x559164b57f5d in main /home/yur/Workspace/Codes/main.cpp:10:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was stored to memory at
#0 0x559164b57e95 in main /home/yur/Workspace/Codes/main.cpp:9:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was created by an allocation of 'a' in the stack frame of function 'main'
#0 0x559164b57920 in main /home/yur/Workspace/Codes/main.cpp:4
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<h2>Work with sanitizers</h2>
<p>上述例子中的所有代码,在开启 GCC 最高级别警告的情况下都不会产生任何警告(最后一个例子的 <code>unused parameter</code> 除外),它们几乎只能在运行时才能发现问题,而这也就是 Sanitizers 的职责所在。</p>
<p>如果你在调试的时候遇到了恼人的「段错误」(运行时错误),而你又没有头绪,不妨试试 Sanitizers 吧。只需要在编译时加上 <code>-fsanitize=address,undefined</code> 参数,然后重新执行样例,兴许就能发现问题了。</p>
<blockquote>
<p>才疏学浅,如有纰漏,欢迎指出!</p>
</blockquote>
<br>
]]></description>
<pubDate>Mon, 08 Jan 2024 01:38:56 GMT</pubDate>
<guid isPermaLink="false">https://www.luogu.com.cn/discuss/47327#Awesome sanitizers</guid>
<link>https://www.luogu.com.cn/discuss/47327</link>
<author><![CDATA[yurzhang]]></author>
</item>
</channel>
</rss>
|
Successfully generated as following: http://localhost:1200/luogu/daily - Success ✔️<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
>
<channel>
<title><![CDATA[洛谷日报]]></title>
<link>https://www.luogu.com.cn/discuss/47327</link>
<atom:link href="http://localhost:1200/luogu/daily" rel="self" type="application/rss+xml" />
<description><![CDATA[洛谷日报 - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)]]></description>
<generator>RSSHub</generator>
<webMaster>i@diygod.me (DIYgod)</webMaster>
<language>zh-cn</language>
<lastBuildDate>Mon, 08 Jan 2024 01:49:45 GMT</lastBuildDate>
<ttl>5</ttl>
<item>
<title><![CDATA[讨论 【日报#464】Awesome sanitizers - Luogu Spilopelia]]></title>
<description><![CDATA[<p>C++ 太复杂了!即使编写的时候非常小心,也不能完全杜绝内存安全问题的出现。就算是算法竞赛时编写的百余行简短代码,也时不时会有数组越界、变量未初始化、未定义行为等问题困扰我们。</p>
<p>在算法竞赛短短几个小时中,花费时间检查这种与算法本身无关的错误,无疑是浪费时间。那有没有什么工具能帮助我们检查这类错误呢?</p>
<p>Sanitizers 是由 Google 发起的一套开源工具集,包含了数个帮助开发者查找 C++ 代码中疑难杂症的工具。其中有些工具,在算法竞赛领域也十分实用。</p>
<h2>AddressSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">AddressSanitizer</a> 简称 ASan,可以帮助我们检查代码中的内存使用问题。</p>
<p>它从 LLVM 3.1 起被集成到 Clang 中,从 GCC 4.8 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=address</code> 来使用它。</p>
<h3>解引用悬垂指针</h3>
<p>来看一段显然存在问题的代码:</p>
<pre><code class="language-cpp">int main() {
char *x = new char[10];
delete[] x;
return x[5];
}</code></pre>
<p>我们申请了一段长度为 10 的 <code>char</code> 数组,随后释放了它,这时我们再取出数组的第 5 个元素——然而这个位置的内存已经被我们释放掉了!</p>
<p>像这种使用已经被释放的内存的问题,我们称之为<strong>解引用悬垂指针</strong>。让我们试试 ASan 能不能帮我们发现这个问题吧!</p>
<p>首先尝试编译这份代码:</p>
<pre><code class="language-bash">g++ main.cpp -o main -g -fsanitize=address</code></pre>
<p>代码顺利编译,看上去什么都没有发生?不要着急,我们试试执行编译出的程序:</p>
<pre><code class="language-bash">./main</code></pre>
<p>程序崩溃了!同时给出了很长一段错误信息:</p>
<pre><code class="language-plain">=================================================================
==19311==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000015 at pc 0x562f45c941de bp 0x7ffc3b87b640 sp 0x7ffc3b87b630
READ of size 1 at 0x602000000015 thread T0
#0 0x562f45c941dd in main /home/yur/Workspace/Codes/main.cpp:4
#1 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7ff979dca349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x562f45c940a4 in _start ../sysdeps/x86_64/start.S:115
0x602000000015 is located 5 bytes inside of 10-byte region [0x602000000010,0x60200000001a)
freed by thread T0 here:
#0 0x7ff97a38e35a in operator delete[](void*) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:155
#1 0x562f45c941a1 in main /home/yur/Workspace/Codes/main.cpp:3
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
previously allocated by thread T0 here:
#0 0x7ff97a38d7f2 in operator new[](unsigned long) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:98
#1 0x562f45c9418a in main /home/yur/Workspace/Codes/main.cpp:2
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
SUMMARY: AddressSanitizer: heap-use-after-free /home/yur/Workspace/Codes/main.cpp:4 in main
Shadow bytes around the buggy address:
0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[fd]fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==19311==ABORTING</code></pre>
<p>通过这段错误信息,我们可以看到 ASan 告诉我们,在 <code>main.cpp</code> 的第 4 行出现了一个 <code>heap-use-after-free</code> 错误,也就是我们在释放了某块堆内存后又使用了它。</p>
<p>不仅如此,它还告诉我们这块内存是在 <code>main.cpp</code> 的第 2 行申请的,在 <code>main.cpp</code> 的第 3 行被释放掉,并且打印出了这三个地方的调用栈!</p>
<p>也就是说,ASan 很好地完成了它的工作,但是是在运行时而不是编译时。这听上去有些令人沮丧,但这已经是最好的结果了,因为很多运行时错误只有在特定的输入下才会出现,在编译时发现它们是不可能的!</p>
<p>换一个角度想想,利用 ASan,我们可以在遇到运行时错误的时候,快速定位到错误的原因,以及发生错误的位置,这已经极大地方便调试了!</p>
<h3>全局数组越界</h3>
<p>看到这里,你可能会想:好吧 ASan 确实是个很棒的工具,可是在算法竞赛中我们真的很少很少会手动分配堆内存,事实上如果不使用 STL,我的程序可能根本不会用到任何堆内存,那么 ASan 对我来说不就没有用处了吗?</p>
<p>我们来看一段更贴近算法竞赛的,显然存在问题的代码:</p>
<pre><code class="language-cpp">#include <iostream>
constexpr int N = 100010;
int n, a[N];
int main() {
for (int i = 0; i < N; ++ i)
a[i] = i;
std::cin >> n;
std::cout << a[n] << std::endl;
return 0;
}</code></pre>
<p>我申请了一个长为 $N$ 的全局数组——这种做法在算法竞赛中很常见,然后我将数组中每个位置的值初始化为它的下标。</p>
<p>接着我们输入了一个 $n$,并输出下标为 $n$ 的位置的值。这太糟糕了!当输入的 $n$ 足够大的时候,这段代码显然会出现数组越界!</p>
<p>让我们再看看 ASan 的表现:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/2709697251.gif" alt="global-buffer-overflow" referrerpolicy="no-referrer"></p>
<p>不出所料,ASan 也能检测到这个错误,它告诉我们在 <code>main.cpp</code> 的第 12 行出现了一个 <code>global-buffer-overflow</code> 错误:</p>
<pre><code class="language-plain">=================================================================
==65354==ERROR: AddressSanitizer: global-buffer-overflow on address 0x558afdb55f68 at pc 0x558afdaf12e3 bp 0x7fff39a9d580 sp 0x7fff39a9d570
READ of size 4 at 0x558afdb55f68 thread T0
#0 0x558afdaf12e2 in main /home/yur/Workspace/Codes/main.cpp:12
#1 0x7fc18ed9c28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7fc18ed9c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x558afdaf1124 in _start ../sysdeps/x86_64/start.S:115
0x558afdb55f68 is located 0 bytes to the right of global variable 'a' defined in 'main.cpp:5:8' (0x558afdaf44c0) of size 400040
SUMMARY: AddressSanitizer: global-buffer-overflow /home/yur/Workspace/Codes/main.cpp:12 in main
Shadow bytes around the buggy address:
0x0ab1dfb62b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ab1dfb62be0: 00 00 00 00 00 00 00 00 00 00 00 00 00[f9]f9 f9
0x0ab1dfb62bf0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==65354==ABORTING</code></pre>
<h3>以及…</h3>
<p>除此之外,ASan 还能检测堆栈上数组的越界、使用离开作用域时被析构的对象、初始化顺序导致的 bug、内存泄漏等疑难杂症。由于它们在算法竞赛中出现得较少,这里就不多赘述。</p>
<p>值得一提的是,既然 ASan 是在运行时进行的检测,那它就必然会对程序的效率产生一定影响。经过<a href="https://github.com/google/sanitizers/wiki/AddressSanitizerPerformanceNumbers">测试</a>,开启 ASan 后的程序效率平均只有原先的一半左右。这个损失会根据平台和程序的不同而有所不同,但无论如何,请记得在进行<strong>重视效率</strong>的测试(如测试你的程序执行大样例时是否会超时)时关掉 ASan 以保证测试结果准确。</p>
<h2>UndefinedBehaviorSanitizer</h2>
<p><a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">UndefinedBehaviorSanitizer</a> 简称 UBSan,可以帮助我们检查代码中的未定义行为。</p>
<p>它从 LLVM 3.3 起被集成到 Clang 中,从 GCC 4.9 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=undefined</code> 来使用它。</p>
<h3>按位位移溢出</h3>
<pre><code class="language-cpp">int main() {
int x = 42;
x <<= 27;
return 0;
}</code></pre>
<p>上面的代码,按位左移的时候会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:3:5: runtime error: left shift of 42 by 27 places cannot be represented in type 'int'</code></pre>
<h3>数值溢出</h3>
<pre><code class="language-cpp">using i64 = long long;
constexpr int mod = 998244353;
int main() {
int x = 114514;
int y = 1919810;
x = ((i64)x * x + y * y) % mod;
return 0;
}</code></pre>
<p>上面的代码,<code>y * y</code> 的部分会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:9:23: runtime error: signed integer overflow: 1919810 * 1919810 cannot be represented in type 'int'</code></pre>
<h3>使用空指针</h3>
<pre><code class="language-cpp">#include <iostream>
struct Node {
Node *left, *right;
int value;
Node(int _value):
left(nullptr),
right(nullptr),
value(_value) { }
~Node() {
delete left;
delete right;
}
};
void print(Node *now) {
if (now->left != nullptr)
print(now->left);
printf("%d ", now->value);
if (now->right != nullptr)
print(now->right);
}
int main() {
Node *root = new Node(5);
root->left = new Node(3);
root->right = new Node(8);
root->left->right = new Node(4);
print(root);
delete root;
print(nullptr);
return 0;
}</code></pre>
<p>上面的代码是使用指针实现的简单的二叉树,其中 <code>print</code> 函数存在一个致命的问题:如果传入的参数本身是空指针,它就会在 <code>now->left</code> 这一步对空指针取左儿子,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:19:12: runtime error: member access within null pointer of type 'struct Node'</code></pre>
<p>如果希望 UBSan 打印出错位置的调用栈,可以在执行程序时加上 <code>UBSAN_OPTIONS=print_stacktrace=1</code> 环境变量:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/1177270905.gif" alt="stacktrace" referrerpolicy="no-referrer"></p>
<h3>除此之外…</h3>
<p>UBSan 还能检测十数种未定义行为,并且每种未定义行为是否需要被检测可以通过编译参数自由控制。与 ASan 相同的是,UBSan 也会影响程序运行效率,在实际使用时请务必注意!</p>
<h2>ThreadSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki#threadsanitizer">ThreadSanitizer</a> 简称 TSan,可以帮助我们检查多线程代码中的数据竞争。</p>
<p>算法竞赛不涉及多线程程序,因此这里不讨论 TSan 相关内容,有兴趣可以自行了解。</p>
<h2>MemorySanitizer</h2>
<p><a href="https://clang.llvm.org/docs/MemorySanitizer.html">MemorySanitizer</a> 简称 MSan,可以帮助我们检查对未初始化的值的使用。</p>
<p>它从 LLVM 4.0 起被集成到 Clang 中。而不幸的是,GCC 并没有集成这个工具。你只能通过在 Clang 中使用 <code>-fsanitize=memory</code> 参数来使用它。</p>
<pre><code class="language-cpp">#include <iostream>
// please ignore unused `argv` :)
int main(int argc, char *argv[]) {
int a[10];
for (int i = 2; i < 10; ++ i)
a[i] = i;
int x = a[argc];
int y = x * 2;
if (y == 0) {
std::cout << "Hello" << std::endl;
} else {
std::cout << "MSan" << std::endl;
}
return 0;
}</code></pre>
<p>上面的代码中,当我们通过 <code>./main</code> 执行程序时,<code>argc</code> 的值将会为 $1$,然而我们没有初始化 <code>a[1]</code>,MSan 将会在运行时报错:</p>
<pre><code class="language-plain">==95226==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55a96ddb3c96 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7f1b4f9d628f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7f1b4f9d6349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x55a96dd221d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<p>可以发现,MSan 直到第 12 行 <code>if (y == 0)</code> 处才报错,这是因为 MSan <strong>不会</strong>在读取未初始化值时<strong>立即</strong>报错,而是会等到这个值影响程序执行时才报错!在此之前,它会跟踪并记录这个未初始化值产生的影响。</p>
<p>如果一个未初始化值经过很远的传播后才引发 MSan 报错,你可能得花很大力气才能找到这个值是在哪里产生的。这时你可以选择在编译时加上 <code>-fsanitize-memory-track-origins</code> 参数,这样 MSan 报错时会从最初的未初始化值开始追踪,打印它的每一次移动,直到来到报错的位置:</p>
<pre><code class="language-plain">==96812==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x559164b57fe0 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7fd4af63f349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x559164ac61d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
Uninitialized value was stored to memory at
#0 0x559164b57f5d in main /home/yur/Workspace/Codes/main.cpp:10:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was stored to memory at
#0 0x559164b57e95 in main /home/yur/Workspace/Codes/main.cpp:9:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was created by an allocation of 'a' in the stack frame of function 'main'
#0 0x559164b57920 in main /home/yur/Workspace/Codes/main.cpp:4
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<h2>Work with sanitizers</h2>
<p>上述例子中的所有代码,在开启 GCC 最高级别警告的情况下都不会产生任何警告(最后一个例子的 <code>unused parameter</code> 除外),它们几乎只能在运行时才能发现问题,而这也就是 Sanitizers 的职责所在。</p>
<p>如果你在调试的时候遇到了恼人的「段错误」(运行时错误),而你又没有头绪,不妨试试 Sanitizers 吧。只需要在编译时加上 <code>-fsanitize=address,undefined</code> 参数,然后重新执行样例,兴许就能发现问题了。</p>
<blockquote>
<p>才疏学浅,如有纰漏,欢迎指出!</p>
</blockquote>
<br>
]]></description>
<pubDate>Sun, 18 Jan 1970 17:09:50 GMT</pubDate>
<guid isPermaLink="false">https://www.luogu.com.cn/discuss/47327#Awesome sanitizers</guid>
<link>https://www.luogu.com.cn/discuss/47327</link>
<author><![CDATA[yurzhang]]></author>
</item>
</channel>
</rss>
|
TonyRL
reviewed
Jan 10, 2024
sakurayang
commented
Jan 12, 2024
Successfully generated as following: http://localhost:1200/luogu/daily - Success ✔️<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
>
<channel>
<title><![CDATA[洛谷日报]]></title>
<link>https://www.luogu.com.cn/discuss/47327</link>
<atom:link href="http://localhost:1200/luogu/daily" rel="self" type="application/rss+xml" />
<description><![CDATA[洛谷日报 - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)]]></description>
<generator>RSSHub</generator>
<webMaster>i@diygod.me (DIYgod)</webMaster>
<language>zh-cn</language>
<lastBuildDate>Fri, 12 Jan 2024 09:59:31 GMT</lastBuildDate>
<ttl>5</ttl>
<item>
<title><![CDATA[讨论 【日报#464】Awesome sanitizers - Luogu Spilopelia]]></title>
<description><![CDATA[<p>C++ 太复杂了!即使编写的时候非常小心,也不能完全杜绝内存安全问题的出现。就算是算法竞赛时编写的百余行简短代码,也时不时会有数组越界、变量未初始化、未定义行为等问题困扰我们。</p>
<p>在算法竞赛短短几个小时中,花费时间检查这种与算法本身无关的错误,无疑是浪费时间。那有没有什么工具能帮助我们检查这类错误呢?</p>
<p>Sanitizers 是由 Google 发起的一套开源工具集,包含了数个帮助开发者查找 C++ 代码中疑难杂症的工具。其中有些工具,在算法竞赛领域也十分实用。</p>
<h2>AddressSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">AddressSanitizer</a> 简称 ASan,可以帮助我们检查代码中的内存使用问题。</p>
<p>它从 LLVM 3.1 起被集成到 Clang 中,从 GCC 4.8 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=address</code> 来使用它。</p>
<h3>解引用悬垂指针</h3>
<p>来看一段显然存在问题的代码:</p>
<pre><code class="language-cpp">int main() {
char *x = new char[10];
delete[] x;
return x[5];
}</code></pre>
<p>我们申请了一段长度为 10 的 <code>char</code> 数组,随后释放了它,这时我们再取出数组的第 5 个元素——然而这个位置的内存已经被我们释放掉了!</p>
<p>像这种使用已经被释放的内存的问题,我们称之为<strong>解引用悬垂指针</strong>。让我们试试 ASan 能不能帮我们发现这个问题吧!</p>
<p>首先尝试编译这份代码:</p>
<pre><code class="language-bash">g++ main.cpp -o main -g -fsanitize=address</code></pre>
<p>代码顺利编译,看上去什么都没有发生?不要着急,我们试试执行编译出的程序:</p>
<pre><code class="language-bash">./main</code></pre>
<p>程序崩溃了!同时给出了很长一段错误信息:</p>
<pre><code class="language-plain">=================================================================
==19311==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000015 at pc 0x562f45c941de bp 0x7ffc3b87b640 sp 0x7ffc3b87b630
READ of size 1 at 0x602000000015 thread T0
#0 0x562f45c941dd in main /home/yur/Workspace/Codes/main.cpp:4
#1 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7ff979dca349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x562f45c940a4 in _start ../sysdeps/x86_64/start.S:115
0x602000000015 is located 5 bytes inside of 10-byte region [0x602000000010,0x60200000001a)
freed by thread T0 here:
#0 0x7ff97a38e35a in operator delete[](void*) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:155
#1 0x562f45c941a1 in main /home/yur/Workspace/Codes/main.cpp:3
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
previously allocated by thread T0 here:
#0 0x7ff97a38d7f2 in operator new[](unsigned long) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:98
#1 0x562f45c9418a in main /home/yur/Workspace/Codes/main.cpp:2
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
SUMMARY: AddressSanitizer: heap-use-after-free /home/yur/Workspace/Codes/main.cpp:4 in main
Shadow bytes around the buggy address:
0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[fd]fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==19311==ABORTING</code></pre>
<p>通过这段错误信息,我们可以看到 ASan 告诉我们,在 <code>main.cpp</code> 的第 4 行出现了一个 <code>heap-use-after-free</code> 错误,也就是我们在释放了某块堆内存后又使用了它。</p>
<p>不仅如此,它还告诉我们这块内存是在 <code>main.cpp</code> 的第 2 行申请的,在 <code>main.cpp</code> 的第 3 行被释放掉,并且打印出了这三个地方的调用栈!</p>
<p>也就是说,ASan 很好地完成了它的工作,但是是在运行时而不是编译时。这听上去有些令人沮丧,但这已经是最好的结果了,因为很多运行时错误只有在特定的输入下才会出现,在编译时发现它们是不可能的!</p>
<p>换一个角度想想,利用 ASan,我们可以在遇到运行时错误的时候,快速定位到错误的原因,以及发生错误的位置,这已经极大地方便调试了!</p>
<h3>全局数组越界</h3>
<p>看到这里,你可能会想:好吧 ASan 确实是个很棒的工具,可是在算法竞赛中我们真的很少很少会手动分配堆内存,事实上如果不使用 STL,我的程序可能根本不会用到任何堆内存,那么 ASan 对我来说不就没有用处了吗?</p>
<p>我们来看一段更贴近算法竞赛的,显然存在问题的代码:</p>
<pre><code class="language-cpp">#include <iostream>
constexpr int N = 100010;
int n, a[N];
int main() {
for (int i = 0; i < N; ++ i)
a[i] = i;
std::cin >> n;
std::cout << a[n] << std::endl;
return 0;
}</code></pre>
<p>我申请了一个长为 $N$ 的全局数组——这种做法在算法竞赛中很常见,然后我将数组中每个位置的值初始化为它的下标。</p>
<p>接着我们输入了一个 $n$,并输出下标为 $n$ 的位置的值。这太糟糕了!当输入的 $n$ 足够大的时候,这段代码显然会出现数组越界!</p>
<p>让我们再看看 ASan 的表现:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/2709697251.gif" alt="global-buffer-overflow" referrerpolicy="no-referrer"></p>
<p>不出所料,ASan 也能检测到这个错误,它告诉我们在 <code>main.cpp</code> 的第 12 行出现了一个 <code>global-buffer-overflow</code> 错误:</p>
<pre><code class="language-plain">=================================================================
==65354==ERROR: AddressSanitizer: global-buffer-overflow on address 0x558afdb55f68 at pc 0x558afdaf12e3 bp 0x7fff39a9d580 sp 0x7fff39a9d570
READ of size 4 at 0x558afdb55f68 thread T0
#0 0x558afdaf12e2 in main /home/yur/Workspace/Codes/main.cpp:12
#1 0x7fc18ed9c28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7fc18ed9c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x558afdaf1124 in _start ../sysdeps/x86_64/start.S:115
0x558afdb55f68 is located 0 bytes to the right of global variable 'a' defined in 'main.cpp:5:8' (0x558afdaf44c0) of size 400040
SUMMARY: AddressSanitizer: global-buffer-overflow /home/yur/Workspace/Codes/main.cpp:12 in main
Shadow bytes around the buggy address:
0x0ab1dfb62b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ab1dfb62be0: 00 00 00 00 00 00 00 00 00 00 00 00 00[f9]f9 f9
0x0ab1dfb62bf0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==65354==ABORTING</code></pre>
<h3>以及…</h3>
<p>除此之外,ASan 还能检测堆栈上数组的越界、使用离开作用域时被析构的对象、初始化顺序导致的 bug、内存泄漏等疑难杂症。由于它们在算法竞赛中出现得较少,这里就不多赘述。</p>
<p>值得一提的是,既然 ASan 是在运行时进行的检测,那它就必然会对程序的效率产生一定影响。经过<a href="https://github.com/google/sanitizers/wiki/AddressSanitizerPerformanceNumbers">测试</a>,开启 ASan 后的程序效率平均只有原先的一半左右。这个损失会根据平台和程序的不同而有所不同,但无论如何,请记得在进行<strong>重视效率</strong>的测试(如测试你的程序执行大样例时是否会超时)时关掉 ASan 以保证测试结果准确。</p>
<h2>UndefinedBehaviorSanitizer</h2>
<p><a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">UndefinedBehaviorSanitizer</a> 简称 UBSan,可以帮助我们检查代码中的未定义行为。</p>
<p>它从 LLVM 3.3 起被集成到 Clang 中,从 GCC 4.9 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=undefined</code> 来使用它。</p>
<h3>按位位移溢出</h3>
<pre><code class="language-cpp">int main() {
int x = 42;
x <<= 27;
return 0;
}</code></pre>
<p>上面的代码,按位左移的时候会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:3:5: runtime error: left shift of 42 by 27 places cannot be represented in type 'int'</code></pre>
<h3>数值溢出</h3>
<pre><code class="language-cpp">using i64 = long long;
constexpr int mod = 998244353;
int main() {
int x = 114514;
int y = 1919810;
x = ((i64)x * x + y * y) % mod;
return 0;
}</code></pre>
<p>上面的代码,<code>y * y</code> 的部分会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:9:23: runtime error: signed integer overflow: 1919810 * 1919810 cannot be represented in type 'int'</code></pre>
<h3>使用空指针</h3>
<pre><code class="language-cpp">#include <iostream>
struct Node {
Node *left, *right;
int value;
Node(int _value):
left(nullptr),
right(nullptr),
value(_value) { }
~Node() {
delete left;
delete right;
}
};
void print(Node *now) {
if (now->left != nullptr)
print(now->left);
printf("%d ", now->value);
if (now->right != nullptr)
print(now->right);
}
int main() {
Node *root = new Node(5);
root->left = new Node(3);
root->right = new Node(8);
root->left->right = new Node(4);
print(root);
delete root;
print(nullptr);
return 0;
}</code></pre>
<p>上面的代码是使用指针实现的简单的二叉树,其中 <code>print</code> 函数存在一个致命的问题:如果传入的参数本身是空指针,它就会在 <code>now->left</code> 这一步对空指针取左儿子,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:19:12: runtime error: member access within null pointer of type 'struct Node'</code></pre>
<p>如果希望 UBSan 打印出错位置的调用栈,可以在执行程序时加上 <code>UBSAN_OPTIONS=print_stacktrace=1</code> 环境变量:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/1177270905.gif" alt="stacktrace" referrerpolicy="no-referrer"></p>
<h3>除此之外…</h3>
<p>UBSan 还能检测十数种未定义行为,并且每种未定义行为是否需要被检测可以通过编译参数自由控制。与 ASan 相同的是,UBSan 也会影响程序运行效率,在实际使用时请务必注意!</p>
<h2>ThreadSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki#threadsanitizer">ThreadSanitizer</a> 简称 TSan,可以帮助我们检查多线程代码中的数据竞争。</p>
<p>算法竞赛不涉及多线程程序,因此这里不讨论 TSan 相关内容,有兴趣可以自行了解。</p>
<h2>MemorySanitizer</h2>
<p><a href="https://clang.llvm.org/docs/MemorySanitizer.html">MemorySanitizer</a> 简称 MSan,可以帮助我们检查对未初始化的值的使用。</p>
<p>它从 LLVM 4.0 起被集成到 Clang 中。而不幸的是,GCC 并没有集成这个工具。你只能通过在 Clang 中使用 <code>-fsanitize=memory</code> 参数来使用它。</p>
<pre><code class="language-cpp">#include <iostream>
// please ignore unused `argv` :)
int main(int argc, char *argv[]) {
int a[10];
for (int i = 2; i < 10; ++ i)
a[i] = i;
int x = a[argc];
int y = x * 2;
if (y == 0) {
std::cout << "Hello" << std::endl;
} else {
std::cout << "MSan" << std::endl;
}
return 0;
}</code></pre>
<p>上面的代码中,当我们通过 <code>./main</code> 执行程序时,<code>argc</code> 的值将会为 $1$,然而我们没有初始化 <code>a[1]</code>,MSan 将会在运行时报错:</p>
<pre><code class="language-plain">==95226==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55a96ddb3c96 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7f1b4f9d628f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7f1b4f9d6349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x55a96dd221d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<p>可以发现,MSan 直到第 12 行 <code>if (y == 0)</code> 处才报错,这是因为 MSan <strong>不会</strong>在读取未初始化值时<strong>立即</strong>报错,而是会等到这个值影响程序执行时才报错!在此之前,它会跟踪并记录这个未初始化值产生的影响。</p>
<p>如果一个未初始化值经过很远的传播后才引发 MSan 报错,你可能得花很大力气才能找到这个值是在哪里产生的。这时你可以选择在编译时加上 <code>-fsanitize-memory-track-origins</code> 参数,这样 MSan 报错时会从最初的未初始化值开始追踪,打印它的每一次移动,直到来到报错的位置:</p>
<pre><code class="language-plain">==96812==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x559164b57fe0 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7fd4af63f349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x559164ac61d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
Uninitialized value was stored to memory at
#0 0x559164b57f5d in main /home/yur/Workspace/Codes/main.cpp:10:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was stored to memory at
#0 0x559164b57e95 in main /home/yur/Workspace/Codes/main.cpp:9:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was created by an allocation of 'a' in the stack frame of function 'main'
#0 0x559164b57920 in main /home/yur/Workspace/Codes/main.cpp:4
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<h2>Work with sanitizers</h2>
<p>上述例子中的所有代码,在开启 GCC 最高级别警告的情况下都不会产生任何警告(最后一个例子的 <code>unused parameter</code> 除外),它们几乎只能在运行时才能发现问题,而这也就是 Sanitizers 的职责所在。</p>
<p>如果你在调试的时候遇到了恼人的「段错误」(运行时错误),而你又没有头绪,不妨试试 Sanitizers 吧。只需要在编译时加上 <code>-fsanitize=address,undefined</code> 参数,然后重新执行样例,兴许就能发现问题了。</p>
<blockquote>
<p>才疏学浅,如有纰漏,欢迎指出!</p>
</blockquote>
<br>
]]></description>
<pubDate>Sun, 18 Jan 1970 17:09:50 GMT</pubDate>
<guid isPermaLink="false">https://www.luogu.com.cn/discuss/47327#Awesome sanitizers</guid>
<link>https://www.luogu.com.cn/discuss/47327</link>
<author><![CDATA[yurzhang]]></author>
</item>
</channel>
</rss>
|
sakurayang
commented
Jan 12, 2024
TonyRL
reviewed
Jan 12, 2024
Successfully generated as following: http://localhost:1200/luogu/daily - Success ✔️<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
>
<channel>
<title><![CDATA[洛谷日报]]></title>
<link>https://www.luogu.com.cn/discuss/47327</link>
<atom:link href="http://localhost:1200/luogu/daily" rel="self" type="application/rss+xml" />
<description><![CDATA[洛谷日报 - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)]]></description>
<generator>RSSHub</generator>
<webMaster>i@diygod.me (DIYgod)</webMaster>
<language>zh-cn</language>
<lastBuildDate>Mon, 15 Jan 2024 01:22:50 GMT</lastBuildDate>
<ttl>5</ttl>
<item>
<title><![CDATA[讨论 【日报#464】Awesome sanitizers - Luogu Spilopelia]]></title>
<description><![CDATA[<p>C++ 太复杂了!即使编写的时候非常小心,也不能完全杜绝内存安全问题的出现。就算是算法竞赛时编写的百余行简短代码,也时不时会有数组越界、变量未初始化、未定义行为等问题困扰我们。</p>
<p>在算法竞赛短短几个小时中,花费时间检查这种与算法本身无关的错误,无疑是浪费时间。那有没有什么工具能帮助我们检查这类错误呢?</p>
<p>Sanitizers 是由 Google 发起的一套开源工具集,包含了数个帮助开发者查找 C++ 代码中疑难杂症的工具。其中有些工具,在算法竞赛领域也十分实用。</p>
<h2>AddressSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">AddressSanitizer</a> 简称 ASan,可以帮助我们检查代码中的内存使用问题。</p>
<p>它从 LLVM 3.1 起被集成到 Clang 中,从 GCC 4.8 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=address</code> 来使用它。</p>
<h3>解引用悬垂指针</h3>
<p>来看一段显然存在问题的代码:</p>
<pre><code class="language-cpp">int main() {
char *x = new char[10];
delete[] x;
return x[5];
}</code></pre>
<p>我们申请了一段长度为 10 的 <code>char</code> 数组,随后释放了它,这时我们再取出数组的第 5 个元素——然而这个位置的内存已经被我们释放掉了!</p>
<p>像这种使用已经被释放的内存的问题,我们称之为<strong>解引用悬垂指针</strong>。让我们试试 ASan 能不能帮我们发现这个问题吧!</p>
<p>首先尝试编译这份代码:</p>
<pre><code class="language-bash">g++ main.cpp -o main -g -fsanitize=address</code></pre>
<p>代码顺利编译,看上去什么都没有发生?不要着急,我们试试执行编译出的程序:</p>
<pre><code class="language-bash">./main</code></pre>
<p>程序崩溃了!同时给出了很长一段错误信息:</p>
<pre><code class="language-plain">=================================================================
==19311==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000015 at pc 0x562f45c941de bp 0x7ffc3b87b640 sp 0x7ffc3b87b630
READ of size 1 at 0x602000000015 thread T0
#0 0x562f45c941dd in main /home/yur/Workspace/Codes/main.cpp:4
#1 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7ff979dca349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x562f45c940a4 in _start ../sysdeps/x86_64/start.S:115
0x602000000015 is located 5 bytes inside of 10-byte region [0x602000000010,0x60200000001a)
freed by thread T0 here:
#0 0x7ff97a38e35a in operator delete[](void*) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:155
#1 0x562f45c941a1 in main /home/yur/Workspace/Codes/main.cpp:3
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
previously allocated by thread T0 here:
#0 0x7ff97a38d7f2 in operator new[](unsigned long) /usr/src/debug/gcc/libsanitizer/asan/asan_new_delete.cpp:98
#1 0x562f45c9418a in main /home/yur/Workspace/Codes/main.cpp:2
#2 0x7ff979dca28f (/usr/lib/libc.so.6+0x2328f)
SUMMARY: AddressSanitizer: heap-use-after-free /home/yur/Workspace/Codes/main.cpp:4 in main
Shadow bytes around the buggy address:
0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[fd]fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==19311==ABORTING</code></pre>
<p>通过这段错误信息,我们可以看到 ASan 告诉我们,在 <code>main.cpp</code> 的第 4 行出现了一个 <code>heap-use-after-free</code> 错误,也就是我们在释放了某块堆内存后又使用了它。</p>
<p>不仅如此,它还告诉我们这块内存是在 <code>main.cpp</code> 的第 2 行申请的,在 <code>main.cpp</code> 的第 3 行被释放掉,并且打印出了这三个地方的调用栈!</p>
<p>也就是说,ASan 很好地完成了它的工作,但是是在运行时而不是编译时。这听上去有些令人沮丧,但这已经是最好的结果了,因为很多运行时错误只有在特定的输入下才会出现,在编译时发现它们是不可能的!</p>
<p>换一个角度想想,利用 ASan,我们可以在遇到运行时错误的时候,快速定位到错误的原因,以及发生错误的位置,这已经极大地方便调试了!</p>
<h3>全局数组越界</h3>
<p>看到这里,你可能会想:好吧 ASan 确实是个很棒的工具,可是在算法竞赛中我们真的很少很少会手动分配堆内存,事实上如果不使用 STL,我的程序可能根本不会用到任何堆内存,那么 ASan 对我来说不就没有用处了吗?</p>
<p>我们来看一段更贴近算法竞赛的,显然存在问题的代码:</p>
<pre><code class="language-cpp">#include <iostream>
constexpr int N = 100010;
int n, a[N];
int main() {
for (int i = 0; i < N; ++ i)
a[i] = i;
std::cin >> n;
std::cout << a[n] << std::endl;
return 0;
}</code></pre>
<p>我申请了一个长为 $N$ 的全局数组——这种做法在算法竞赛中很常见,然后我将数组中每个位置的值初始化为它的下标。</p>
<p>接着我们输入了一个 $n$,并输出下标为 $n$ 的位置的值。这太糟糕了!当输入的 $n$ 足够大的时候,这段代码显然会出现数组越界!</p>
<p>让我们再看看 ASan 的表现:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/2709697251.gif" alt="global-buffer-overflow" referrerpolicy="no-referrer"></p>
<p>不出所料,ASan 也能检测到这个错误,它告诉我们在 <code>main.cpp</code> 的第 12 行出现了一个 <code>global-buffer-overflow</code> 错误:</p>
<pre><code class="language-plain">=================================================================
==65354==ERROR: AddressSanitizer: global-buffer-overflow on address 0x558afdb55f68 at pc 0x558afdaf12e3 bp 0x7fff39a9d580 sp 0x7fff39a9d570
READ of size 4 at 0x558afdb55f68 thread T0
#0 0x558afdaf12e2 in main /home/yur/Workspace/Codes/main.cpp:12
#1 0x7fc18ed9c28f (/usr/lib/libc.so.6+0x2328f)
#2 0x7fc18ed9c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#3 0x558afdaf1124 in _start ../sysdeps/x86_64/start.S:115
0x558afdb55f68 is located 0 bytes to the right of global variable 'a' defined in 'main.cpp:5:8' (0x558afdaf44c0) of size 400040
SUMMARY: AddressSanitizer: global-buffer-overflow /home/yur/Workspace/Codes/main.cpp:12 in main
Shadow bytes around the buggy address:
0x0ab1dfb62b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ab1dfb62be0: 00 00 00 00 00 00 00 00 00 00 00 00 00[f9]f9 f9
0x0ab1dfb62bf0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ab1dfb62c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==65354==ABORTING</code></pre>
<h3>以及…</h3>
<p>除此之外,ASan 还能检测堆栈上数组的越界、使用离开作用域时被析构的对象、初始化顺序导致的 bug、内存泄漏等疑难杂症。由于它们在算法竞赛中出现得较少,这里就不多赘述。</p>
<p>值得一提的是,既然 ASan 是在运行时进行的检测,那它就必然会对程序的效率产生一定影响。经过<a href="https://github.com/google/sanitizers/wiki/AddressSanitizerPerformanceNumbers">测试</a>,开启 ASan 后的程序效率平均只有原先的一半左右。这个损失会根据平台和程序的不同而有所不同,但无论如何,请记得在进行<strong>重视效率</strong>的测试(如测试你的程序执行大样例时是否会超时)时关掉 ASan 以保证测试结果准确。</p>
<h2>UndefinedBehaviorSanitizer</h2>
<p><a href="https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html">UndefinedBehaviorSanitizer</a> 简称 UBSan,可以帮助我们检查代码中的未定义行为。</p>
<p>它从 LLVM 3.3 起被集成到 Clang 中,从 GCC 4.9 起被集成到 GCC 中。你可以通过在编译参数中添加 <code>-fsanitize=undefined</code> 来使用它。</p>
<h3>按位位移溢出</h3>
<pre><code class="language-cpp">int main() {
int x = 42;
x <<= 27;
return 0;
}</code></pre>
<p>上面的代码,按位左移的时候会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:3:5: runtime error: left shift of 42 by 27 places cannot be represented in type 'int'</code></pre>
<h3>数值溢出</h3>
<pre><code class="language-cpp">using i64 = long long;
constexpr int mod = 998244353;
int main() {
int x = 114514;
int y = 1919810;
x = ((i64)x * x + y * y) % mod;
return 0;
}</code></pre>
<p>上面的代码,<code>y * y</code> 的部分会溢出 <code>int</code> 的上界,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:9:23: runtime error: signed integer overflow: 1919810 * 1919810 cannot be represented in type 'int'</code></pre>
<h3>使用空指针</h3>
<pre><code class="language-cpp">#include <iostream>
struct Node {
Node *left, *right;
int value;
Node(int _value):
left(nullptr),
right(nullptr),
value(_value) { }
~Node() {
delete left;
delete right;
}
};
void print(Node *now) {
if (now->left != nullptr)
print(now->left);
printf("%d ", now->value);
if (now->right != nullptr)
print(now->right);
}
int main() {
Node *root = new Node(5);
root->left = new Node(3);
root->right = new Node(8);
root->left->right = new Node(4);
print(root);
delete root;
print(nullptr);
return 0;
}</code></pre>
<p>上面的代码是使用指针实现的简单的二叉树,其中 <code>print</code> 函数存在一个致命的问题:如果传入的参数本身是空指针,它就会在 <code>now->left</code> 这一步对空指针取左儿子,这是未定义行为。如果你使用了 UBSan,它会在运行时报错:</p>
<pre><code class="language-plain">main.cpp:19:12: runtime error: member access within null pointer of type 'struct Node'</code></pre>
<p>如果希望 UBSan 打印出错位置的调用栈,可以在执行程序时加上 <code>UBSAN_OPTIONS=print_stacktrace=1</code> 环境变量:</p>
<p><img src="https://yurzhang.com/usr/uploads/2022/11/1177270905.gif" alt="stacktrace" referrerpolicy="no-referrer"></p>
<h3>除此之外…</h3>
<p>UBSan 还能检测十数种未定义行为,并且每种未定义行为是否需要被检测可以通过编译参数自由控制。与 ASan 相同的是,UBSan 也会影响程序运行效率,在实际使用时请务必注意!</p>
<h2>ThreadSanitizer</h2>
<p><a href="https://github.com/google/sanitizers/wiki#threadsanitizer">ThreadSanitizer</a> 简称 TSan,可以帮助我们检查多线程代码中的数据竞争。</p>
<p>算法竞赛不涉及多线程程序,因此这里不讨论 TSan 相关内容,有兴趣可以自行了解。</p>
<h2>MemorySanitizer</h2>
<p><a href="https://clang.llvm.org/docs/MemorySanitizer.html">MemorySanitizer</a> 简称 MSan,可以帮助我们检查对未初始化的值的使用。</p>
<p>它从 LLVM 4.0 起被集成到 Clang 中。而不幸的是,GCC 并没有集成这个工具。你只能通过在 Clang 中使用 <code>-fsanitize=memory</code> 参数来使用它。</p>
<pre><code class="language-cpp">#include <iostream>
// please ignore unused `argv` :)
int main(int argc, char *argv[]) {
int a[10];
for (int i = 2; i < 10; ++ i)
a[i] = i;
int x = a[argc];
int y = x * 2;
if (y == 0) {
std::cout << "Hello" << std::endl;
} else {
std::cout << "MSan" << std::endl;
}
return 0;
}</code></pre>
<p>上面的代码中,当我们通过 <code>./main</code> 执行程序时,<code>argc</code> 的值将会为 $1$,然而我们没有初始化 <code>a[1]</code>,MSan 将会在运行时报错:</p>
<pre><code class="language-plain">==95226==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55a96ddb3c96 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7f1b4f9d628f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7f1b4f9d6349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x55a96dd221d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<p>可以发现,MSan 直到第 12 行 <code>if (y == 0)</code> 处才报错,这是因为 MSan <strong>不会</strong>在读取未初始化值时<strong>立即</strong>报错,而是会等到这个值影响程序执行时才报错!在此之前,它会跟踪并记录这个未初始化值产生的影响。</p>
<p>如果一个未初始化值经过很远的传播后才引发 MSan 报错,你可能得花很大力气才能找到这个值是在哪里产生的。这时你可以选择在编译时加上 <code>-fsanitize-memory-track-origins</code> 参数,这样 MSan 报错时会从最初的未初始化值开始追踪,打印它的每一次移动,直到来到报错的位置:</p>
<pre><code class="language-plain">==96812==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x559164b57fe0 in main /home/yur/Workspace/Codes/main.cpp:12:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#2 0x7fd4af63f349 in __libc_start_main (/usr/lib/libc.so.6+0x23349) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
#3 0x559164ac61d4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
Uninitialized value was stored to memory at
#0 0x559164b57f5d in main /home/yur/Workspace/Codes/main.cpp:10:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was stored to memory at
#0 0x559164b57e95 in main /home/yur/Workspace/Codes/main.cpp:9:7
#1 0x7fd4af63f28f (/usr/lib/libc.so.6+0x2328f) (BuildId: 1e94beb079e278ac4f2c8bce1f53091548ea1584)
Uninitialized value was created by an allocation of 'a' in the stack frame of function 'main'
#0 0x559164b57920 in main /home/yur/Workspace/Codes/main.cpp:4
SUMMARY: MemorySanitizer: use-of-uninitialized-value /home/yur/Workspace/Codes/main.cpp:12:7 in main
Exiting</code></pre>
<h2>Work with sanitizers</h2>
<p>上述例子中的所有代码,在开启 GCC 最高级别警告的情况下都不会产生任何警告(最后一个例子的 <code>unused parameter</code> 除外),它们几乎只能在运行时才能发现问题,而这也就是 Sanitizers 的职责所在。</p>
<p>如果你在调试的时候遇到了恼人的「段错误」(运行时错误),而你又没有头绪,不妨试试 Sanitizers 吧。只需要在编译时加上 <code>-fsanitize=address,undefined</code> 参数,然后重新执行样例,兴许就能发现问题了。</p>
<blockquote>
<p>才疏学浅,如有纰漏,欢迎指出!</p>
</blockquote>
<br>
]]></description>
<pubDate>Sun, 18 Jan 1970 17:09:50 GMT</pubDate>
<guid isPermaLink="false">https://www.luogu.com.cn/discuss/47327#Awesome sanitizers</guid>
<link>https://www.luogu.com.cn/discuss/47327</link>
<author><![CDATA[yurzhang]]></author>
</item>
</channel>
</rss>
|
mengshang918
pushed a commit
to mengshang918/Fork_RSSHub
that referenced
this pull request
Jan 23, 2024
* feat(route): add 米课圈精华 (#14010) * feat(route): add 米课圈精华 * fix typo * fix: radar.js with type errors * fix: radar.js with type errors * fix(route): Readhub (#14013) * fix(route): Readhub * fix typo * chore(deps-dev): bump @types/react from 18.2.42 to 18.2.43 in /website (#14018) Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.42 to 18.2.43. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@types/react" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump prettier from 3.1.0 to 3.1.1 (#14016) * chore(deps-dev): bump prettier from 3.1.0 to 3.1.1 Bumps [prettier](https://github.com/prettier/prettier) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.1.0...3.1.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @stylistic/eslint-plugin-js from 1.5.0 to 1.5.1 (#14015) * chore(deps-dev): bump @stylistic/eslint-plugin-js from 1.5.0 to 1.5.1 Bumps [@stylistic/eslint-plugin-js](https://github.com/eslint-stylistic/eslint-stylistic/tree/HEAD/packages/eslint-plugin-js) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/eslint-stylistic/eslint-stylistic/releases) - [Commits](https://github.com/eslint-stylistic/eslint-stylistic/commits/v1.5.1/packages/eslint-plugin-js) --- updated-dependencies: - dependency-name: "@stylistic/eslint-plugin-js" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump eslint-plugin-n from 16.3.1 to 16.4.0 (#14017) * chore(deps-dev): bump eslint-plugin-n from 16.3.1 to 16.4.0 Bumps [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) from 16.3.1 to 16.4.0. - [Release notes](https://github.com/eslint-community/eslint-plugin-n/releases) - [Commits](https://github.com/eslint-community/eslint-plugin-n/compare/16.3.1...16.4.0) --- updated-dependencies: - dependency-name: eslint-plugin-n dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(route): QuestMobile行业研究报告 (#14020) * fix(route): QuestMobile行业研究报告 * Update website/docs/routes/new-media.mdx --------- * fix(route): fix Yuque book route (#14022) * fix: fix Yuque book route * fix: sort switch conditions * fix: add cookieJar --------- * fix(route): picnob (#13986) * fix(route): picnob * fix(route): picnob. Use one browser session to do all http requests. * fix(route): picnob. Use puppeteer as a fallback option when a normal request returns a 403 error. * fix(route): picnob. Block unnecessary requests when using puppeteer. * fix(route): picnob. Adaptation of JSON responses when using puppeteer for http requests. * Update lib/v2/picnob/user.js --------- * fix(route/apnews): remove description (#14025) * chore(deps): bump github/codeql-action from 2 to 3 (#14026) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/eslint from 8.44.8 to 8.44.9 (#14028) * chore(deps-dev): bump @types/eslint from 8.44.8 to 8.44.9 Bumps [@types/eslint](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint) from 8.44.8 to 8.44.9. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/eslint) --- updated-dependencies: - dependency-name: "@types/eslint" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump @sentry/node from 7.86.0 to 7.87.0 (#14031) * chore(deps): bump @sentry/node from 7.86.0 to 7.87.0 Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.86.0 to 7.87.0. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.86.0...7.87.0) --- updated-dependencies: - dependency-name: "@sentry/node" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/react from 18.2.43 to 18.2.45 in /website (#14032) Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.43 to 18.2.45. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@types/react" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump puppeteer from 21.6.0 to 21.6.1 (#14029) * chore(deps): bump puppeteer from 21.6.0 to 21.6.1 Bumps [puppeteer](https://github.com/puppeteer/puppeteer) from 21.6.0 to 21.6.1. - [Release notes](https://github.com/puppeteer/puppeteer/releases) - [Changelog](https://github.com/puppeteer/puppeteer/blob/main/release-please-config.json) - [Commits](https://github.com/puppeteer/puppeteer/compare/puppeteer-v21.6.0...puppeteer-v21.6.1) --- updated-dependencies: - dependency-name: puppeteer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @vercel/nft from 0.24.4 to 0.26.0 (#14030) * chore(deps-dev): bump @vercel/nft from 0.24.4 to 0.26.0 Bumps [@vercel/nft](https://github.com/vercel/nft) from 0.24.4 to 0.26.0. - [Release notes](https://github.com/vercel/nft/releases) - [Commits](https://github.com/vercel/nft/compare/0.24.4...0.26.0) --- updated-dependencies: - dependency-name: "@vercel/nft" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump dawidd6/action-download-artifact from 2 to 3 (#14027) Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2 to 3. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: bring back remark formatter (#14040) * docs: format docs * docs: Fix URLs in website documentation * chore: bring back mdast formatter * docs: format docs * docs: remove heading id in jsx component * docs: fix heading level * chore: update remark formatter plugins * chore: Update dependabot ignore list * style: auto format * docs: fix table chore: update dependabot ignore * chore(deps): bump actions/upload-artifact from 3 to 4 (#14041) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump eslint-plugin-yml from 1.10.0 to 1.11.0 (#14042) * chore(deps-dev): bump eslint-plugin-yml from 1.10.0 to 1.11.0 Bumps [eslint-plugin-yml](https://github.com/ota-meshi/eslint-plugin-yml) from 1.10.0 to 1.11.0. - [Release notes](https://github.com/ota-meshi/eslint-plugin-yml/releases) - [Changelog](https://github.com/ota-meshi/eslint-plugin-yml/blob/master/CHANGELOG.md) - [Commits](https://github.com/ota-meshi/eslint-plugin-yml/compare/v1.10.0...v1.11.0) --- updated-dependencies: - dependency-name: eslint-plugin-yml dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add 国家能源局发展规划司 (#14039) * style: auto format * chore(deps): bump @sentry/node from 7.87.0 to 7.88.0 (#14045) * chore(deps): bump @sentry/node from 7.87.0 to 7.88.0 Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.87.0 to 7.88.0. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.87.0...7.88.0) --- updated-dependencies: - dependency-name: "@sentry/node" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add 大连理工大学公共基础学院 RSS (#13982) (#14007) * Update index.js * fix(route): 中国政府网没有正确拼接相对地址路径 && 替换滚动新闻地址 * feat(route): add 大连理工大学公共基础学院 RSS (#13982) * 移除 pubDate 使用 new Date * 增加默认路由设置 * 完善 公共基础学院 说明文档 * 根据修改建议修改代码 * fix: sort maintainer --------- * style: auto format * feat(route): add fxiaoke.com blog (#14046) * feat(route): add fxiaoke.com blog * Update lib/v2/fxiaoke/radar.js * Update lib/v2/fxiaoke/radar.js * Update lib/v2/fxiaoke/radar.js * Update lib/v2/fxiaoke/radar.js * Update lib/v2/fxiaoke/radar.js * Update lib/v2/fxiaoke/radar.js * Update lib/v2/fxiaoke/crm.js * gen exact pubdate --------- * feat: title case following The Chicago Manual of Style (#14048) * feat(route): sspu (#14050) * fix(route): threads profile pic (#14061) * feat(route): add xhu people activities and answers (#14063) * style: auto format * feat(route): add 国家矿山安全监察局 (#14060) * style: auto format * fix(route): sehuatang append images in `.pattl` (#14055) * docs: fix xhu heading ids * docs: update badge * fix(route/reuters): Suppress full text fetch (#14035) * fix(route/deeplearning): The batch from deeplearning.ai (#14066) * fix(the-batch): The batch from deeplearning.ai * refactor: migrate to v2 --------- * fix(radar): 修复 xhu 用户动态匹配到自己的问题 (#14070) * docs: update badge * docs: update badge * feat: update github radars * fix: incorrect field name in UMS (#14073) * feat: remove notOperational routes - social media * feat(route): add tophub list 将榜单条目集合到一个列表中,可避免推送大量条目,更符合阅读习惯且有热度排序 (#14056) * feat(route): add fxiaoke.com blog * Update lib/v2/fxiaoke/radar.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/fxiaoke/radar.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/fxiaoke/radar.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/fxiaoke/radar.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/fxiaoke/radar.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/fxiaoke/radar.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/fxiaoke/crm.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * gen exact pubdate * feat(route): add tophub list * fix: guid * fix: use art to render rank --------- * feat(route): add artstation (#14075) * feat(route): add artstation * fix: update template * docs: add docs * feat: remove notOperational routes - new media * docs: fix badge text * chore: update stale config * chore(deps): bump pinyin-pro from 3.18.4 to 3.18.5 in /website (#14078) Bumps [pinyin-pro](https://github.com/zh-lx/pinyin-pro) from 3.18.4 to 3.18.5. - [Release notes](https://github.com/zh-lx/pinyin-pro/releases) - [Changelog](https://github.com/zh-lx/pinyin-pro/blob/main/CHANGELOG.md) - [Commits](https://github.com/zh-lx/pinyin-pro/compare/3.18.4...3.18.5) --- updated-dependencies: - dependency-name: pinyin-pro dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/react-dom in /website (#14079) Bumps [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) from 18.2.17 to 18.2.18. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) --- updated-dependencies: - dependency-name: "@types/react-dom" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump prism-react-renderer from 2.3.0 to 2.3.1 in /website (#14080) Bumps [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/FormidableLabs/prism-react-renderer/releases) - [Commits](https://github.com/FormidableLabs/prism-react-renderer/compare/prism-react-renderer@2.3.0...prism-react-renderer@2.3.1) --- updated-dependencies: - dependency-name: prism-react-renderer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/lint-staged from 13.2.2 to 13.3.0 (#14077) * chore(deps-dev): bump @types/lint-staged from 13.2.2 to 13.3.0 Bumps [@types/lint-staged](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lint-staged) from 13.2.2 to 13.3.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lint-staged) --- updated-dependencies: - dependency-name: "@types/lint-staged" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump eslint from 8.55.0 to 8.56.0 (#14076) * chore(deps-dev): bump eslint from 8.55.0 to 8.56.0 Bumps [eslint](https://github.com/eslint/eslint) from 8.55.0 to 8.56.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v8.55.0...v8.56.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): show weather info in qweather feed title (#14082) * feat(route): migrate jianshu to v2 (#14081) * feat(route): migrate jianshu to v2 * feat(docs): update jianshu docs * Refactor ProcessFeed function to improve code readability and performance --------- * feat: remove notOperational routes - traditional media * feat: remove notOperational routes - bbs * feat: remove notOperational routes - blog * feat(route): add 中国炼焦行业协会 (#14074) * feat(route): add 中国炼焦行业协会 * fix: remove subheadings for radar links * fix typo * feat: remove notOperational routes - programming * feat: remove notOperational routes - design * feat: remove notOperational routes - live * feat: remove notOperational routes - multimedia * chore(deps-dev): bump eslint-plugin-prettier from 5.0.1 to 5.1.0 (#14084) * chore(deps-dev): bump eslint-plugin-prettier from 5.0.1 to 5.1.0 Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.0.1 to 5.1.0. - [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases) - [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.0.1...v5.1.0) --- updated-dependencies: - dependency-name: eslint-plugin-prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add 中华人民共和国国家发展和改革委员会发展改革工作 (#14088) * feat: remove notOperational routes - picture * feat: hpoi * chore(deps-dev): bump eslint-plugin-n from 16.4.0 to 16.5.0 (#14091) * chore(deps-dev): bump eslint-plugin-n from 16.4.0 to 16.5.0 Bumps [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) from 16.4.0 to 16.5.0. - [Release notes](https://github.com/eslint-community/eslint-plugin-n/releases) - [Commits](https://github.com/eslint-community/eslint-plugin-n/compare/16.4.0...16.5.0) --- updated-dependencies: - dependency-name: eslint-plugin-n dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/eslint from 8.44.9 to 8.56.0 (#14092) * chore(deps-dev): bump @types/eslint from 8.44.9 to 8.56.0 Bumps [@types/eslint](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint) from 8.44.9 to 8.56.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/eslint) --- updated-dependencies: - dependency-name: "@types/eslint" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: remove notOperational routes - anime * feat: remove notOperational routes - program-update * feat: remove notOperational routes - travel * feat(route): add mof (bond management) 中华人民共和国财政部-专题-政府债券管理 (#14094) * feat(route): add mof (bond management) * fix(router): re-order router config and add radar for mof * feat(router): radar param in route doc * fix(radar): add index source for mof * feat(radar): more source path for mof * Update website/docs/routes/government.mdx --------- * feat: remove notOperational routes - shopping * feat: remove notOperational routes - game * feat: remove notOperational routes - reading * feat: remove notOperational routes - study * feat: remove notOperational routes - journal * feat: remove notOperational routes - finance * feat: remove notOperational routes - other * chore(deps-dev): bump eslint-plugin-prettier from 5.1.0 to 5.1.1 (#14097) * chore(deps-dev): bump eslint-plugin-prettier from 5.1.0 to 5.1.1 Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.1.0 to 5.1.1. - [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases) - [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.1.0...v5.1.1) --- updated-dependencies: - dependency-name: eslint-plugin-prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: fix path of zh configuration (#14100) * feat(route): add 中华人民共和国国家发展和改革委员会价格监测中心 (#14101) * chore(deps-dev): bump @types/supertest from 2.0.16 to 6.0.1 (#14104) * chore(deps-dev): bump @types/supertest from 2.0.16 to 6.0.1 Bumps [@types/supertest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/supertest) from 2.0.16 to 6.0.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/supertest) --- updated-dependencies: - dependency-name: "@types/supertest" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add consumer shopping-guide (#14105) * fix(route): dcfever (#14106) * chore(deps): bump @sentry/node from 7.88.0 to 7.89.0 (#14083) * chore(deps): bump @sentry/node from 7.88.0 to 7.89.0 Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.88.0 to 7.89.0. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.88.0...7.89.0) --- updated-dependencies: - dependency-name: "@sentry/node" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install * fix: replace deprecated `configureScope` in favor of `getCurrentScope()` ref: https://github.com/getsentry/sentry-javascript/blob/b27c2367acb312c4e9c2fd1aa2cdaf5b8cff1dad/MIGRATION.md --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add PKMer (#14103) * feat(route): PKMer * style: auto format * Update lib/v2/pkmer/recent.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/pkmer/radar.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update bbs.mdx * Update lib/v2/pkmer/recent.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * fix(route): gamme (#14108) * feat(route): add 中国民用航空局公众留言 (#14109) * feat(route): 新增 bing 搜索; 迁移 bing 每日图片到 v2; 新增 百度搜索; 迁移 搜狗特色LOGO 到 v2 规范;添加 搜狗搜索;添加 Google Search (#13936) * fix(route): 修复 米游社 公告栏 template 错误 * feat(route): 新增 bing 搜索 * docs: Update other.mdx * docs: fix docs * feat(route): 新增 百度搜索 * fix(route): 修复 pubDate 解析错误 * fix(route): 优化 百度搜索的缓存,减轻反爬问题 * feat(route): 新增 360 搜索 * feat(route): 迁移 搜狗特色LOGO 到 v2 规范;添加 搜狗搜索 * fix(route): 百度搜索增加图片 * feat(route): 新增 Google Search * fix(route): 修复 百度搜索相关问题 * fix(route): 修复 Google 相关问题 * fix(route): 修复 360 搜索 * fix(route): 修复 搜狗搜索 * fix(route): 修复 await 问题 * fix: 移除 google sites * fix(route): 修复 缓存和过滤逻辑问题 * fix(route): 修复 360 搜索缺少 cookie 的问题 * fix(route): 修复 360 搜索 cookie 的问题 * feat(route): 移除 so.com 路由 * fix: merge conflict --------- * feat: add back blockbeats (#14113) * feat: add back blockbeats * fix: path * fix: adjust http log level (#14114) * feat: log redirect * fix: change puppeteer/proxy/redirect/got log level to `http` ref: https://github.com/winstonjs/winston#logging-levels (npm levels) * chore(deps): bump @tonyrl/rand-user-agent from 2.0.42 to 2.0.43 (#14117) * chore(deps): bump @tonyrl/rand-user-agent from 2.0.42 to 2.0.43 Bumps [@tonyrl/rand-user-agent](https://github.com/TonyRL/rand-user-agent) from 2.0.42 to 2.0.43. - [Release notes](https://github.com/TonyRL/rand-user-agent/releases) - [Commits](https://github.com/TonyRL/rand-user-agent/compare/v2.0.42...v2.0.43) --- updated-dependencies: - dependency-name: "@tonyrl/rand-user-agent" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump eslint-plugin-prettier from 5.1.1 to 5.1.2 (#14116) * chore(deps-dev): bump eslint-plugin-prettier from 5.1.1 to 5.1.2 Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.1.1 to 5.1.2. - [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases) - [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.1.1...v5.1.2) --- updated-dependencies: - dependency-name: eslint-plugin-prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump @sentry/node from 7.89.0 to 7.91.0 (#14115) * chore(deps): bump @sentry/node from 7.89.0 to 7.91.0 Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.89.0 to 7.91.0. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.89.0...7.91.0) --- updated-dependencies: - dependency-name: "@sentry/node" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(route): fix shiep/hhxy shiep/jsjxy (#14110) * fix(route): sort shiep config * fix(route): fix shiep/hhxy shiep/jsjxy * refactor: list processing in shiep/index.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * refactor: selector in shiep --------- * feat(route): add 界面新闻栏目 (#14121) * feat: set default itunes_explicit to false, close #14093 * PlayStation Monthly Games * feat(route): add new route for moj of gov.cn (#14122) * feat(route): add new route for moj of gov.cn * fix: typo in path Co-authored-by: Tony <TonyRL@users.noreply.github.com> --------- * chore(deps-dev): bump @types/supertest from 6.0.1 to 6.0.2 (#14126) * chore(deps-dev): bump @types/supertest from 6.0.1 to 6.0.2 Bumps [@types/supertest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/supertest) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/supertest) --- updated-dependencies: - dependency-name: "@types/supertest" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): bluesky user posts (#14130) * chore(deps-dev): bump @types/react from 18.2.45 to 18.2.46 in /website (#14131) Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.45 to 18.2.46. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@types/react" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add Cool Papers (#14129) * feat(route): add Cool Papers * fix typo * fix: remove kimi chat content * docs: fix typo --------- * style: auto format * chore(deps-dev): bump eslint-plugin-n from 16.5.0 to 16.6.0 (#14140) * chore(deps-dev): bump eslint-plugin-n from 16.5.0 to 16.6.0 Bumps [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) from 16.5.0 to 16.6.0. - [Release notes](https://github.com/eslint-community/eslint-plugin-n/releases) - [Commits](https://github.com/eslint-community/eslint-plugin-n/compare/16.5.0...16.6.0) --- updated-dependencies: - dependency-name: eslint-plugin-n dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump koa from 2.14.2 to 2.15.0 (#14141) * chore(deps): bump koa from 2.14.2 to 2.15.0 Bumps [koa](https://github.com/koajs/koa) from 2.14.2 to 2.15.0. - [Changelog](https://github.com/koajs/koa/blob/2.15.0/History.md) - [Commits](https://github.com/koajs/koa/compare/2.14.2...2.15.0) --- updated-dependencies: - dependency-name: koa dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump clsx from 2.0.0 to 2.1.0 in /website (#14142) Bumps [clsx](https://github.com/lukeed/clsx) from 2.0.0 to 2.1.0. - [Release notes](https://github.com/lukeed/clsx/releases) - [Commits](https://github.com/lukeed/clsx/compare/v2.0.0...v2.1.0) --- updated-dependencies: - dependency-name: clsx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: add air quality content in qweather 3days forecast feed (#14136) * feat: add air quality content in qweather 3days report feed * chore: title enhancement * fix: resolve no needed lines * fix: add guard for api key config * docs: Update InstanceList.tsx - add an instance (#14143) add https://rsshub.rss.tips * feat(route): 三联生活周刊 (#14127) * feat(route): 三联生活周刊 * fix: namespace and data acquirement * fix: get article list by api * Update lib/v2/lifeweek/channel.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/lifeweek/channel.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/lifeweek/tag.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * fix: rss url * refactor: getRssItem function * Update lib/v2/lifeweek/utils.js --------- Co-authored-by: Changren Wang <changren.wcr@alibaba-inc.com> * feat(route): add 中国的中古 (#14139) * feat(route): add 中国的中古 * Update lib/v2/medieval-china/post.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update lib/v2/medieval-china/maintainer.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * fix(route): fix desc of 中国的中古 * fix(route): fix data query of 中国的中古 * Update lib/v2/medieval-china/post.js Co-authored-by: Tony <TonyRL@users.noreply.github.com> * style: auto format * fix(radar): add target --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * feat(route): id param for shmeea (#14145) * feat(route): id param for shmeea * fix(route): fix radar docs url in shmeea/self-study * fix(route): id?=08000 && block requests to binary files && fix code style --------- * feat(route): 添加 dm_img_list 字段防止被 Bilibili 识别 (#14128) * feat(route): add dm_img_list parameter Signed-off-by: NightSpaceC <NightSpaceC@outlook.com> * feat(route): readd video-all. It is still usable. * fix(route): use camelCase * feat(route): generate data of dm_img_list --------- Signed-off-by: NightSpaceC <NightSpaceC@outlook.com> * style: auto format * feat(route): add 国家气候中心最新监测 (#14151) * feat(route): add 国家气候中心最新监测 * fix typo * feat(route): add 上海第二工业大学体育部 (#14149) * feat(route): add 上海第二工业大学体育部 * fix docs * fix: block requests to binary files * fix(route): douban recommended two-digit month (#14153) * chore(deps): bump @tonyrl/rand-user-agent from 2.0.43 to 2.0.44 (#14156) * chore(deps): bump @tonyrl/rand-user-agent from 2.0.43 to 2.0.44 Bumps [@tonyrl/rand-user-agent](https://github.com/TonyRL/rand-user-agent) from 2.0.43 to 2.0.44. - [Release notes](https://github.com/TonyRL/rand-user-agent/releases) - [Commits](https://github.com/TonyRL/rand-user-agent/compare/v2.0.43...v2.0.44) --- updated-dependencies: - dependency-name: "@tonyrl/rand-user-agent" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump chrono-node from 2.7.3 to 2.7.4 (#14155) * chore(deps): bump chrono-node from 2.7.3 to 2.7.4 Bumps [chrono-node](https://github.com/wanasit/chrono) from 2.7.3 to 2.7.4. - [Release notes](https://github.com/wanasit/chrono/releases) - [Commits](https://github.com/wanasit/chrono/compare/v2.7.3...v2.7.4) --- updated-dependencies: - dependency-name: chrono-node dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add OTOBANANA (#14160) * feat(route): add OTOBANANA * fix: live guid * feat: utgd add premium identification (#14163) * fix(route): 界面新闻重复文章视频 (#14162) * fix(route): 界面新闻重复文章视频 * fix: improve url sanitization * feat(route): backlinko (#14164) * feat(route): backlinko * Refactor blog.js to destructure nested properties * chore(deps): bump pinyin-pro from 3.18.5 to 3.18.6 in /website (#14167) Bumps [pinyin-pro](https://github.com/zh-lx/pinyin-pro) from 3.18.5 to 3.18.6. - [Release notes](https://github.com/zh-lx/pinyin-pro/releases) - [Changelog](https://github.com/zh-lx/pinyin-pro/blob/main/CHANGELOG.md) - [Commits](https://github.com/zh-lx/pinyin-pro/compare/3.18.5...3.18.6) --- updated-dependencies: - dependency-name: pinyin-pro dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @stylistic/eslint-plugin-js from 1.5.1 to 1.5.3 (#14165) * chore(deps-dev): bump @stylistic/eslint-plugin-js from 1.5.1 to 1.5.3 Bumps [@stylistic/eslint-plugin-js](https://github.com/eslint-stylistic/eslint-stylistic/tree/HEAD/packages/eslint-plugin-js) from 1.5.1 to 1.5.3. - [Release notes](https://github.com/eslint-stylistic/eslint-stylistic/releases) - [Commits](https://github.com/eslint-stylistic/eslint-stylistic/commits/v1.5.3/packages/eslint-plugin-js) --- updated-dependencies: - dependency-name: "@stylistic/eslint-plugin-js" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump eslint-plugin-n from 16.6.0 to 16.6.1 (#14166) * chore(deps-dev): bump eslint-plugin-n from 16.6.0 to 16.6.1 Bumps [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) from 16.6.0 to 16.6.1. - [Release notes](https://github.com/eslint-community/eslint-plugin-n/releases) - [Commits](https://github.com/eslint-community/eslint-plugin-n/compare/16.6.0...16.6.1) --- updated-dependencies: - dependency-name: eslint-plugin-n dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(route): 第一财经DT财经 (#14171) * chore(deps-dev): bump @types/imapflow from 1.0.16 to 1.0.17 (#14172) * chore(deps-dev): bump @types/imapflow from 1.0.16 to 1.0.17 Bumps [@types/imapflow](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/imapflow) from 1.0.16 to 1.0.17. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/imapflow) --- updated-dependencies: - dependency-name: "@types/imapflow" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/eslint from 8.56.0 to 8.56.1 (#14173) * chore(deps-dev): bump @types/eslint from 8.56.0 to 8.56.1 Bumps [@types/eslint](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint) from 8.56.0 to 8.56.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/eslint) --- updated-dependencies: - dependency-name: "@types/eslint" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @vercel/nft from 0.26.0 to 0.26.2 (#14174) * chore(deps-dev): bump @vercel/nft from 0.26.0 to 0.26.2 Bumps [@vercel/nft](https://github.com/vercel/nft) from 0.26.0 to 0.26.2. - [Release notes](https://github.com/vercel/nft/releases) - [Commits](https://github.com/vercel/nft/compare/0.26.0...0.26.2) --- updated-dependencies: - dependency-name: "@vercel/nft" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: recover /ft/myft, close #14096 * fix(route): 第一财经DT财经报告附件 (#14176) * feat(route): recover gofans (#14183) * chore(deps): bump mailparser from 3.6.5 to 3.6.6 (#14184) * chore(deps): bump mailparser from 3.6.5 to 3.6.6 Bumps [mailparser](https://github.com/nodemailer/mailparser) from 3.6.5 to 3.6.6. - [Release notes](https://github.com/nodemailer/mailparser/releases) - [Changelog](https://github.com/nodemailer/mailparser/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodemailer/mailparser/compare/v3.6.5...v3.6.6) --- updated-dependencies: - dependency-name: mailparser dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump puppeteer from 21.6.1 to 21.7.0 (#14185) * chore(deps): bump puppeteer from 21.6.1 to 21.7.0 Bumps [puppeteer](https://github.com/puppeteer/puppeteer) from 21.6.1 to 21.7.0. - [Release notes](https://github.com/puppeteer/puppeteer/releases) - [Changelog](https://github.com/puppeteer/puppeteer/blob/main/release-please-config.json) - [Commits](https://github.com/puppeteer/puppeteer/compare/puppeteer-v21.6.1...puppeteer-v21.7.0) --- updated-dependencies: - dependency-name: puppeteer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump @sentry/node from 7.91.0 to 7.92.0 (#14186) * chore(deps): bump @sentry/node from 7.91.0 to 7.92.0 Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.91.0 to 7.92.0. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.91.0...7.92.0) --- updated-dependencies: - dependency-name: "@sentry/node" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: domp4 supports secondary address (#14181) (#14189) * fix: domp4 supports secondary address * fix: domp4 remove invalid domain * feat(route): 调整生成鼠标路径的参数,在配置中预置路径 (#14179) * fix(route): adjust the parameter to generate path * feat(route): use the path from configure * feat(docs): add the usage of BILIBILI_DM_IMG_LIST * style: auto format * feat: New Router for liveuamap (#14175) * Added new route for liveuamap * Fix unsafe domain and the 3rd level domain defaulting * docs: fix heading --------- * chore(deps): bump googleapis from 129.0.0 to 130.0.0 (#14193) * chore(deps): bump googleapis from 129.0.0 to 130.0.0 Bumps [googleapis](https://github.com/googleapis/google-api-nodejs-client) from 129.0.0 to 130.0.0. - [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases) - [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/release-please-config.json) - [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v129.0.0...googleapis-v130.0.0) --- updated-dependencies: - dependency-name: googleapis dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump jsdom from 23.0.1 to 23.1.0 (#14194) * chore(deps): bump jsdom from 23.0.1 to 23.1.0 Bumps [jsdom](https://github.com/jsdom/jsdom) from 23.0.1 to 23.1.0. - [Release notes](https://github.com/jsdom/jsdom/releases) - [Changelog](https://github.com/jsdom/jsdom/blob/main/Changelog.md) - [Commits](https://github.com/jsdom/jsdom/compare/23.0.1...23.1.0) --- updated-dependencies: - dependency-name: jsdom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump the docusaurus group in /website with 7 updates (#14192) Bumps the docusaurus group in /website with 7 updates: | Package | From | To | | --- | --- | --- | | [@docusaurus/core](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus) | `3.0.1` | `3.1.0` | | [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) | `3.0.1` | `3.1.0` | | [@docusaurus/plugin-pwa](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-pwa) | `3.0.1` | `3.1.0` | | [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) | `3.0.1` | `3.1.0` | | [@docusaurus/module-type-aliases](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-module-type-aliases) | `3.0.1` | `3.1.0` | | [@docusaurus/tsconfig](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-tsconfig) | `3.0.1` | `3.1.0` | | [@docusaurus/types](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-types) | `3.0.1` | `3.1.0` | Updates `@docusaurus/core` from 3.0.1 to 3.1.0 - [Release notes](https://github.com/facebook/docusaurus/releases) - [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/docusaurus/commits/v3.1.0/packages/docusaurus) Updates `@docusaurus/plugin-client-redirects` from 3.0.1 to 3.1.0 - [Release notes](https://github.com/facebook/docusaurus/releases) - [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/docusaurus/commits/v3.1.0/packages/docusaurus-plugin-client-redirects) Updates `@docusaurus/plugin-pwa` from 3.0.1 to 3.1.0 - [Release notes](https://github.com/facebook/docusaurus/releases) - [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/docusaurus/commits/v3.1.0/packages/docusaurus-plugin-pwa) Updates `@docusaurus/preset-classic` from 3.0.1 to 3.1.0 - [Release notes](https://github.com/facebook/docusaurus/releases) - [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/docusaurus/commits/v3.1.0/packages/docusaurus-preset-classic) Updates `@docusaurus/module-type-aliases` from 3.0.1 to 3.1.0 - [Release notes](https://github.com/facebook/docusaurus/releases) - [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/docusaurus/commits/v3.1.0/packages/docusaurus-module-type-aliases) Updates `@docusaurus/tsconfig` from 3.0.1 to 3.1.0 - [Release notes](https://github.com/facebook/docusaurus/releases) - [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/docusaurus/commits/v3.1.0/packages/docusaurus-tsconfig) Updates `@docusaurus/types` from 3.0.1 to 3.1.0 - [Release notes](https://github.com/facebook/docusaurus/releases) - [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md) - [Commits](https://github.com/facebook/docusaurus/commits/v3.1.0/packages/docusaurus-types) --- updated-dependencies: - dependency-name: "@docusaurus/core" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docusaurus - dependency-name: "@docusaurus/plugin-client-redirects" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docusaurus - dependency-name: "@docusaurus/plugin-pwa" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docusaurus - dependency-name: "@docusaurus/preset-classic" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docusaurus - dependency-name: "@docusaurus/module-type-aliases" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: docusaurus - dependency-name: "@docusaurus/tsconfig" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: docusaurus - dependency-name: "@docusaurus/types" dependency-type: direct:development update-type: version-update:semver-minor dependency-group: docusaurus ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(route): Tradingview Blog (#14191) * fix(route): Tradingview Blog * fix: use tiny-async-pool * fix(route): fix shiep/jsjxy shiep/jwc (#14196) * docs: change html example to use items variable instead of item (#14205) * change html example to use items variable instead of item The existing example for HTML retrieval uses 'item' variable on item retrieval, but the final rss output uses the 'items' variable. This results in undefined variable for anyone who directly uses the example code. * docs: fix cn docs too --------- * feat(route): add 中华全国专利代理师协会 (#14197) * fix: zhihu timeline (#14169) * fix zhihu timeline * deal with content in an array * adopt content_html if exists * fix(route): 处理大麦网查询结果为空的情况 (#14203) * fix(route): 处理大麦网查询结果为空的情况 * refactor: migrate to v2 --------- * chore(deps): bump @tonyrl/rand-user-agent from 2.0.44 to 2.0.45 (#14208) * chore(deps): bump @tonyrl/rand-user-agent from 2.0.44 to 2.0.45 Bumps [@tonyrl/rand-user-agent](https://github.com/TonyRL/rand-user-agent) from 2.0.44 to 2.0.45. - [Release notes](https://github.com/TonyRL/rand-user-agent/releases) - [Commits](https://github.com/TonyRL/rand-user-agent/compare/v2.0.44...v2.0.45) --- updated-dependencies: - dependency-name: "@tonyrl/rand-user-agent" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump jsdom from 23.1.0 to 23.2.0 (#14209) * chore(deps): bump jsdom from 23.1.0 to 23.2.0 Bumps [jsdom](https://github.com/jsdom/jsdom) from 23.1.0 to 23.2.0. - [Release notes](https://github.com/jsdom/jsdom/releases) - [Changelog](https://github.com/jsdom/jsdom/blob/main/Changelog.md) - [Commits](https://github.com/jsdom/jsdom/compare/23.1.0...23.2.0) --- updated-dependencies: - dependency-name: jsdom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/react from 18.2.46 to 18.2.47 in /website (#14210) Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.46 to 18.2.47. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@types/react" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): Add Onet (#14200) * feat(route): Add Onet * use arrow function in `router.js` * Update lib/v2/onet/templates/article.art * Update lib/v2/onet/templates/image.art * Update lib/v2/onet/maintainer.js * Update website/docs/routes/new-media.mdx --------- * fix(route): saraba1st digest image (#14206) * fix saraba1st digest image * add missing semicolon * chore(deps-dev): bump @types/koa from 2.13.12 to 2.14.0 (#14215) * chore(deps-dev): bump @types/koa from 2.13.12 to 2.14.0 Bumps [@types/koa](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/koa) from 2.13.12 to 2.14.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/koa) --- updated-dependencies: - dependency-name: "@types/koa" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat(route): add huggingface zh blog (#14211) * feat(route): add huggingface zh blog * refactor: update * feat(route): Add ekantipur.com (Nepal) (#14207) * feat(route): Add ekantipur remove unused deps * feat(route): Add ekantipur radar * removed undefined field * updated maintainer.js to use optional field character - ? * updated radar.js with full name --------- * style: auto format * feat(route): HoYoLAB (#14146) * hoyolab * 修改分页参数 * 统一名称 * 替换limit参数 * 参数默认值问题 * 参数默认值问题 * feat(route): trending papers on arXiv from trendingpapers (#14182) * style: auto format * chore(deps): bump @sentry/node from 7.92.0 to 7.93.0 (#14220) * chore(deps): bump @sentry/node from 7.92.0 to 7.93.0 Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.92.0 to 7.93.0. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/7.92.0...7.93.0) --- updated-dependencies: - dependency-name: "@sentry/node" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump eslint-plugin-n from 16.6.1 to 16.6.2 (#14216) * chore(deps-dev): bump eslint-plugin-n from 16.6.1 to 16.6.2 Bumps [eslint-plugin-n](https://github.com/eslint-community/eslint-plugin-n) from 16.6.1 to 16.6.2. - [Release notes](https://github.com/eslint-community/eslint-plugin-n/releases) - [Commits](https://github.com/eslint-community/eslint-plugin-n/compare/16.6.1...16.6.2) --- updated-dependencies: - dependency-name: eslint-plugin-n dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 (#14221) * chore(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 5.1.2 to 5.1.3. - [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases) - [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v5.1.2...v5.1.3) --- updated-dependencies: - dependency-name: eslint-plugin-prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: 修正 cyzone 返回link 为空 (#14224) * fix(egsea): pubDate Invalid Date the https://rsshub.app/egsea/flash response error pubDate <pubDate>Invalid Date</pubDate> * refactor: migrate to v2 * Refactor link generation in util.js --------- * fix(route): 国家外汇管理局业务咨询 & 投诉建议链接 (#14226) * chore(deps): bump pinyin-pro from 3.18.6 to 3.19.0 in /website (#14222) Bumps [pinyin-pro](https://github.com/zh-lx/pinyin-pro) from 3.18.6 to 3.19.0. - [Release notes](https://github.com/zh-lx/pinyin-pro/releases) - [Changelog](https://github.com/zh-lx/pinyin-pro/blob/main/CHANGELOG.md) - [Commits](https://github.com/zh-lx/pinyin-pro/commits) --- updated-dependencies: - dependency-name: pinyin-pro dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps-dev): bump @types/eslint from 8.56.1 to 8.56.2 (#14228) * chore(deps-dev): bump @types/eslint from 8.56.1 to 8.56.2 Bumps [@types/eslint](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/eslint) from 8.56.1 to 8.56.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/eslint) --- updated-dependencies: - dependency-name: "@types/eslint" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: fix maintainer * feat(route): add BT之家1LOU站 (#14219) * route: BT之家1LOU * 1. using new routers. 2. If path is empty, visit correct main page of website. 3. roll back deleted doc by mistake. * Update lib/v2/1lou/radar.js * Update website/docs/routes/multimedia.mdx * Update website/docs/routes/multimedia.mdx --------- * style: auto format * chore(deps-dev): bump prettier from 3.1.1 to 3.2.1 (#14230) * chore(deps-dev): bump prettier from 3.1.1 to 3.2.1 Bumps [prettier](https://github.com/prettier/prettier) from 3.1.1 to 3.2.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.1.1...3.2.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * chore: fix pnpm install --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * style: auto format * feat(proxy): add PAC script support (#14218) * feat(proxy): add PAC script support * fix pnpm fail * fix coverage * fix coverage final * update docs * feat(ps): use art * feat(route): add TradingView Desktop releases and release notes (#14234) * fix: pornhub pubDate (#14232) * fix(route): fix twitch (#14238) * fix(route): fix twitch * fix docs * feat(route): add 苏州市发展和改革委员会 (#14214) * feat(route): add 苏州市发展和改革委员会 * docs: remove duplicated heading * refactor: migrate to v2 * fix: suzhou docs * fix: news --------- * fix(route): tencent author (#14241) * fix: luogu route parse error (#14170) * fix route parse error * use parse-date instead of Date * optimize decode processes * fix typo --------- * fix(route): hoyolab (#14242) * feat: support CIDR IP ranges in allowlist (#14243) * docs: Update InstanceList.tsx (#14244) Add instance hosted by Kai. * feat(route): recover kuwaitlocal agirls qianp taiwannews jiaoliudao (#14247) * fix: recover kuwaitlocal * fix: recover agirls * fix: recover qianp * fix: recover taiwannews * fix: recover hket * fix: recover jiaoliudao * fix: qianp * fix: deepscan issue * feat(route): zhihu xhu posts (#14246) * feat: recover shuiguopai (#14248) * chore(deps-dev): bump @types/react from 18.2.47 to 18.2.48 in /website (#14255) Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.47 to 18.2.48. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) --- updated-dependencies: - dependency-name: "@types/react" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.nor…
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
why ?
RSSHub will throw thi error while fetch
/luogu/daily
.After check the response, now it will send a encode string to client for decode, like this.
and after decode:
What we want is in
currentData.post.content
, and it's a markdown format string with CRLF.And we can render it to html by markdown-it.
After these steps, we finally can return old process flow.
Example for the Proposed Route(s) / 路由地址示例
New RSS Route Checklist / 新 RSS 路由检查表
Puppeteer
Note / 说明