我在我的一个真实项目中遇到了一个难以调试的情况,我不小心访问了已被移动的lambda中的局部变量的引用.访问是从另一个线程完成的,但移动的lambda保持活着直到第二个线程完成.
该错误仅在禁用优化时发生,并且是由粗心重构引起的.
我创建了一个最小的例子(可在wandbox上找到),它可以重现这个问题:
struct state
{
int x = 100;
};
template <typename TF>
void eat1(TF&& f)
{
// Call the lambda.
f();
// Simulate waiting for the second thread
// to finish.
std::this_thread::sleep_for(1000ms);
}
template <typename TF>
void eat0(TF&& f)
{
// Move the lambda to some other handler.
eat1(std::forward<TF>(f));
}
void use_state(state& s)
{
// Will print `100`.
std::cout << s.x << "\n";
// Separate thread. Note that `s` is captured by
// reference. …
Run Code Online (Sandbox Code Playgroud) 我试图让地址清理黑名单在 C++ 项目中工作,但它没有按预期工作。我在他们的网站上尝试了这个例子,如果我用 编译clang
,它工作得很好。
build % cat suppress.txt
fun:bad_foo
build % cat foo.c
#include <stdlib.h>
void bad_foo() {
int *a = (int*)malloc(40);
a[10] = 1;
}
int main() { bad_foo(); }
build % clang -fsanitize=address -fsanitize-blacklist=suppress.txt foo.c ; ./a.out
Exit code: 0
Run Code Online (Sandbox Code Playgroud)
但一旦我使用clang++
,它就会被忽略。
build % cp foo.c foo.cpp
build % clang++ -fsanitize=address -fsanitize-blacklist=suppress.txt foo.cpp ; ./a.out
=================================================================
==9943==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6040000003f8 at pc 0x00010ff93ee8 bp 0x7ffedfc6c340 sp 0x7ffedfc6c338
WRITE of size 4 at 0x6040000003f8 …
Run Code Online (Sandbox Code Playgroud) 我使用 DomSanitizer 来清理数据库中要显示在页面上的 HTML 内容。
<div [innerHtml]="safeHtml(article.text)"></div>
Run Code Online (Sandbox Code Playgroud)
其中 safeHtml 是:
safeHtml(html){
return this.sanitize.bypassSecurityTrustHtml(html);
}
Run Code Online (Sandbox Code Playgroud)
它工作完美。但我注意到该文本在网页上显示时无法选择或复制。否则,可以正常复制或选择普通字符串字段中显示的文本。
GCC 和 Clang 编译器都支持LeakSanitizer,这有助于查找 C 程序中的内存泄漏。有时内存泄漏是不可避免的(例如,因为它正在测试套件中进行测试)。
可以使用Leak Sanitizer 接口对此类内存进行注释:
#include <sanitizer/lsan_interface.h>
void *p = create_new_object();
__lsan_ignore_object(p);
Run Code Online (Sandbox Code Playgroud)
然而,这会在不支持 LSan 的编译器上崩溃。在 Address Sanitizer 中,此构造可用于检测 ASAN 的可用性:
/* __has_feature(address_sanitizer) is used later for Clang, this is for
* compatibility with other compilers (such as GCC and MSVC) */
#ifndef __has_feature
# define __has_feature(x) 0
#endif
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
/* ASAN-aware code here. */
#endif
Run Code Online (Sandbox Code Playgroud)
仅在 Clang 中检测不到__has_feature(leak_sanitizer)
LSan 的存在,__SANITIZE_LEAKS__
在 GCC 中也检测不到 LSan 的存在。我怎样才能检测 ASAN 的可用性?请注意,LSan 可以独立于 …
使用-fsanitize=undefined使用 clang 3.6 编译应用程序后,我尝试在使用抑制文件的同时启动检测程序以忽略一些错误:
UBSAN_OPTIONS="suppressions=ubsan.supp" ./app.exe
Run Code Online (Sandbox Code Playgroud)
抑制文件 ubsan.supp 包含:
signed-integer-overflow:example.c
Run Code Online (Sandbox Code Playgroud)
这会导致错误消息:
UndefinedBehaviorSanitizer: failed to parse suppressions
Run Code Online (Sandbox Code Playgroud)
gcc 4.9 版本也会发生同样的情况。我能找到的唯一文档是http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html,它适用于 clang 3.9,而我使用的是 3.6(它没有包含 ubsan 的文档)。
任何人都可以提供适用于 clang 3.6 的 ubsan 抑制文件的工作示例吗?
编辑:通过浏览 ubsan 的源代码,我发现唯一有效的抑制类型可能是“vptr_check”——但不知道我在看哪个版本。任何人都可以确认在 clang 3.9 中有更多的抑制类型可用吗?
在下面的代码片段中,有一个不是微不足道的错误,但我希望像 AddressSanitizer 这样的工具来捕捉它。
#include <vector>
#include <iostream>
int main ()
{
std::vector<int> toto;
toto.push_back(2);
int const& titi = toto[0];
toto.pop_back();
std::cout << titi << std::endl;
return 1;
}
Run Code Online (Sandbox Code Playgroud)
当作用域向量并在范围之外打印时,catch 引用会抛出一个错误,使用堆后释放。
但是当没有作用域时,std::vector
实现可能不会在 pop_back 之后释放内存,因此引用仍然指向有效内存。
我四处搜索,发现您可以手动毒化内存,我想知道这是否已在 STL 中实现(https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning)
Clang 有许多消毒剂,可以在运行时检查可疑行为。不幸的是,它们不能同时启用。
不能在同一程序中组合多个
-fsanitize=address,
-fsanitize=thread
, 和-fsanitize=memory
检查器。
更糟糕的是,这三个中的每一个似乎都非常有用,不能省略。AddressSanitizer 检查内存错误,ThreadSanitizer 检查竞争条件,MemorySanitizer 检查未初始化的读取。 我担心所有这些事情!
显然,如果我对虫子的位置有预感,我可以据此选择消毒剂。但如果我不这样做呢?更进一步,如果我想使用消毒剂作为预防工具而不是诊断工具来指出我什至不知道的错误怎么办?
换句话说,鉴于我没有特别寻找任何东西,默认情况下我应该使用哪种消毒剂进行编译? 我是不是只需要编译和测试整个程序三遍,每个消毒剂一次?
我试图抑制来自 clang/gcc 中地址清理程序的警告
我的源文件如下所示:
int foo(){
double bar[] = {7,8};
return bar[3];
}
int main(){
return foo();
}
Run Code Online (Sandbox Code Playgroud)
显然第 3 行有溢出。
抑制文件 (myasan.supp) 包含:
interceptor_via_fun:foo
Run Code Online (Sandbox Code Playgroud)
编译(clang 也会产生警告)并运行:
clang -O0 -g -fsanitize=address -fno-omit-frame-pointer sanitizerTest.c
ASAN_SYMBOLIZER_PATH=/software/clang/7.0.0/bin/llvm-symbolizer ASAN_OPTIONS=suppressions=myasan.supp ./a.out
Run Code Online (Sandbox Code Playgroud)
但地址消毒剂仍然抱怨溢出。
==8119==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffeab4e75f8 at pc 0x0000004008bf bp 0x7ffeab4e75b0 sp 0x7ffeab4e75a8
READ of size 8 at 0x7ffeab4e75f8 thread T0
#0 0x4008be in foo() /tmp/asan/sanitizerTest.c:3
#1 0x400919 in main /tmp/asan/sanitizerTest.c:7
#2 0x7f549fbfb82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#3 0x400718 in _start (/tmp/asan/a.out+0x400718)
Run Code Online (Sandbox Code Playgroud)
编译器是clang7。我也测试了 clang6、gcc7。 …
当启用未定义的消毒剂时,我在 GNU 科学库 (GSL) 中发现了一个运行时错误:
deque.c:58:11: runtime error: member access within misaligned address 0x0000024010f4 for type 'struct deque', which requires 8 byte alignment
0x0000024010f4: note: pointer points here
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
deque.c:59:11: runtime error: member access within misaligned address 0x0000024010f4 for type 'struct deque', which requires 8 byte alignment
0x0000024010f4: …
Run Code Online (Sandbox Code Playgroud) 我正在使用 owasp-java-html-sanitizer 并尝试将 id 属性添加到 HTML 代码中的每个 h2 标签,该属性应该在多个页面加载过程中保持不变,但对于页面上的每个元素都是唯一的(如 id 属性所定义的) )。我尝试对所有元素进行计数以获得索引并将索引添加到每个 h2 元素。但是,我目前无法在 java 中访问这些数据。然后我使用了 UUID.randomUUID(),但是由于它是随机的,因此 id 不是持久的。
这是我目前拥有的代码:
public PolicyFactory HtmlPolicy() {
return new HtmlPolicyBuilder()
.allowElements("h3", "h4", "h5", "h6", "p", "span", "br", "b", "strong", "i", "em", "u", "hr", "ol", "ul", "li",
"img", "table", "tr", "th", "td", "thead", "tbody", "tfoot", "caption", "colgroup", "col", "blockquote", "figure", "figcaption", "object", "iframe")
.allowElements(
(String elementName, List<String> attrs) -> {
String uniqueID = UUID.randomUUID().toString();
// Add an attribute.
attrs.add("id");
attrs.add("headline-" + uniqueID);
attrs.add("class");
attrs.add("scrollspy"); …
Run Code Online (Sandbox Code Playgroud)