<div dir="ltr">Hi all,<div><br></div><div>I'm having trouble wrapping my head around hwasan instrumentation for specific alloca instructions. For the given (minimized reproducer) C code:</div><div><br></div><div>```</div><div><font face="monospace">void func(const char *);</font></div><div><font face="monospace">void trace(const char *str, ...) {</font></div><div><font face="monospace">  func(str);</font></div><div><font face="monospace">}</font></div><div>```</div><div><br></div><div>I can generate the following IR:</div><div><br></div><div>```</div><div><font face="monospace">; Compiled (from a near ToT clang) with:</font></div><div><font face="monospace">; clang /tmp/test.c -fsanitize=hwaddress --target=aarch64-unknown-fuchsia -S -o - -mllvm --hwasan-instrument-with-calls=1 -mllvm --hwasan-generate-tags-with-calls=1 -emit-llvm</font></div><div><font face="monospace">; Function Attrs: noinline nounwind optnone sanitize_hwaddress shadowcallstack sspstrong uwtable<br>define dso_local void @trace(i8* %0, ...) #0 {<br>  %2 = call i8* asm "", "=r,0"(i8* null)<br>  %3 = alloca i8*, align 8<br>  %4 = ptrtoint i8** %3 to i64<br>  call void @__hwasan_store8(i64 %4)<br>  store i8* %0, i8** %3, align 8<br>  %5 = ptrtoint i8** %3 to i64<br>  call void @__hwasan_load8(i64 %5)<br>  %6 = load i8*, i8** %3, align 8<br>  call void @func(i8* %6) #2<br>  ret void<br>}</font><br></div><div>```</div><div><br></div><div>This IR contains one load and store check on the `<font face="monospace">%3 = alloca i8*, align 8</font>`. The thing that confuses me is<b> the alloca in this instance isn't tagged, nor is shadow memory setup for it, but we still check a load/store on it.</b> My understanding is that if shadow isn't set up with a tag, then hwasan will likely throw an error on the first <font face="monospace" style="">__hwasan_store8 </font><font face="arial, sans-serif" style="">from comparing an untagged pointer against a value at an arbitrary shadow address which could be non-zero from some previous allocation. The above C code is a minimal reproducer for the case I ran into which I think might be a false-negative.</font></div><div><b><br></b></div><div>In the pass, it looks like hwasan will only instrument an alloca based on `isInterestingAlloca()`, which is dependent on `isAllocaPromotable()` returning false. All other requirements for `isInterestingAlloca()` seem to be fulfilled except for this. Based on comments, it looks like we only want to instrument an alloca that is not promotable to a register. This looks to be the case since the `alloca` seems to be lowered to space on the stack:</div><div><br></div><div>```</div><div><font face="monospace">trace:<br>        sub     sp, sp, #256<br>        str     x30, [x18], #8<br>        stp     x29, x30, [sp, #240]<br><b>        add     x29, sp, #240<br>        str     x0, [sp, #8]<br></b>...<br><b>        sub     x0, x29, #16<br></b>        bl      __hwasan_store8  // x29 is offset into stack</font><br></div><div><font face="monospace"><b>        ldr     x8, [sp, #8]<br>        stur    x8, [x29, #-16]  // Load original arg onto stack</b></font><b><br></b></div><div><font face="monospace">...</font></div><div>```</div><div><br></div><div>At a glance, it looks like the store into the alloca isn't an actual bug, so we shouldn't need to instrument it. I'm thinking perhaps this is an issue regarding where to add load/store checks. HWASan has a similar function `getInterestingMemoryOperands()` for determining interesting places to add checks before loads/stores, but it doesn't seem to specifically if a load/store operand accepts one of these ignored allocas. Should there be extra checks to ensure that these allocas aren't checked?</div><div><br></div><div>Thanks,</div><div>Leonard</div></div>