<br><br><div class="gmail_quote">On Fri, Dec 16, 2011 at 12:37 PM, Eli Friedman <span dir="ltr"><<a href="mailto:eli.friedman@gmail.com">eli.friedman@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5">On Fri, Dec 16, 2011 at 12:19 PM, John Criswell <<a href="mailto:criswell@illinois.edu">criswell@illinois.edu</a>> wrote:<br>
> On 12/16/11 12:24 PM, Kostya Serebryany wrote:<br>
><br>
> Hello,<br>
><br>
> We've just got a bug report from Mozilla folks about AddressSanitizer false<br>
> positive with -O2.<br>
> Turns out there is a conflict between load widening and AddressSanitizer.<br>
><br>
> Simple reproducer:<br>
><br>
> % cat load_widening.c && echo ========= && clang -O2 -c load_widening.c<br>
> -flto && llvm-dis load_widening.o && cat load_widening.o.ll<br>
> void init(char *);<br>
> int foo() {<br>
> char a[22];<br>
> init(a);<br>
> return a[16] a[21];<br>
> }<br>
> =========<br>
> ; ModuleID = 'load_widening.o'<br>
> target datalayout =<br>
> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"<br>
> target triple = "x86_64-unknown-linux-gnu"<br>
><br>
> define i32 @foo() nounwind uwtable {<br>
> entry:<br>
> %a = alloca [22 x i8], align 16<br>
> %arraydecay = getelementptr inbounds [22 x i8]* %a, i64 0, i64 0<br>
> call void @init(i8* %arraydecay) nounwind<br>
> %arrayidx = getelementptr inbounds [22 x i8]* %a, i64 0, i64 16<br>
> %0 = bitcast i8* %arrayidx to i64*<br>
> %1 = load i64* %0, align 16 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<br>
> %2 = trunc i64 %1 to i32<br>
> %sext = shl i32 %2, 24<br>
> %conv = ashr exact i32 %sext, 24<br>
> %3 = lshr i64 %1, 16<br>
> %.tr = trunc i64 %3 to i32<br>
> %sext3 = ashr i32 %.tr, 24<br>
> %add = add nsw i32 %sext3, %conv<br>
> ret i32 %add<br>
> }<br>
><br>
><br>
> Here, the load widening replaces two 1-byte loads with one 8-byte load which<br>
> partially goes out of bounds.<br>
> Since the array is 16-byte aligned, this transformation should never cause<br>
> problems in regular compilation,<br>
> but it causes AddressSanitizer false positives because the generated load<br>
> *is* in fact out of bounds.<br>
><br>
><br>
> SAFECode would have the same problem on this code as it now checks for loads<br>
> and stores that "fall off" the beginning or end of a memory object.<br>
><br>
><br>
><br>
> Do we consider the above transformation legal?<br>
><br>
><br>
> I would argue that it should not be legal. We don't actually know what<br>
> comes after the 22 byte object. Is it another memory object? A<br>
> memory-mapped I/O device? Unmapped memory? Padded junk space? Reading<br>
> memory-mapped I/O could have nasty side effects, and accessing unmapped<br>
> memory could cause the program to fault even though it was written correctly<br>
> as the source-language level.<br>
><br>
> While some may consider these sorts of scenarios to be unlikely, consider<br>
> the possibility that the alloca is transformed into a global variable or<br>
> heap allocation. That would be a legitimate transform and makes the above<br>
> scenarios more likely.<br>
<br>
</div></div>Having the load hit unmapped memory is impossible on common<br>
architectures given the alignment we're talking about here. And if<br>
memory-mapped IO comes after the memory object, the object itself also<br>
has some sort of unusual semantics, so it should be using volatile<br>
loads anyway.<br></blockquote><div><br></div><div>Would would be the right way to disable load widening when AddressSanitizer (or SAFECode) is enabled? </div><div><br></div><div>--kcc </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
That said, LLVM isn't actually keeping track of the "page size" (or<br>
equivalent), so the optimizers can't actually prove this will happen.<br>
<span class="HOEnZb"><font color="#888888"><br>
-Eli<br>
</font></span></blockquote></div><br>