On Fri, Oct 13, 2017 at 01:01:37PM +0200, Martin Liška wrote:
> @@ -3826,6 +3827,18 @@ pointer_diff (location_t loc, tree op0, tree op1)
>      pedwarn (loc, OPT_Wpointer_arith,
>            "pointer to a function used in subtraction");
>  
> +  if (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT))
> +    {
> +      gcc_assert (current_function_decl != NULL_TREE);
> +
> +      op0 = c_fully_fold (op0, false, NULL);
> +      op1 = c_fully_fold (op1, false, NULL);
> +
> +      tree tt = builtin_decl_explicit (BUILT_IN_ASAN_POINTER_SUBTRACT);
> +      *instrument_expr
> +     = build_call_expr_loc (loc, tt, 2, op0, op1);
> +    }

If op0 or op1 have some embedded side-effects, won't you evaluate them
multiple times?  I'd expect you need to c_save_expr them and make sure the
actual pointer difference expression uses the result of the save expr too.

> --- a/libsanitizer/asan/asan_report.cc
> +++ b/libsanitizer/asan/asan_report.cc
> @@ -344,14 +344,68 @@ static INLINE void CheckForInvalidPointerPair(void *p1, 
> void *p2) {
>    if (!flags()->detect_invalid_pointer_pairs) return;
>    uptr a1 = reinterpret_cast<uptr>(p1);
>    uptr a2 = reinterpret_cast<uptr>(p2);
> -  AsanChunkView chunk1 = FindHeapChunkByAddress(a1);
> -  AsanChunkView chunk2 = FindHeapChunkByAddress(a2);
> -  bool valid1 = chunk1.IsAllocated();
> -  bool valid2 = chunk2.IsAllocated();
> -  if (!valid1 || !valid2 || !chunk1.Eq(chunk2)) {
> -    GET_CALLER_PC_BP_SP;
> -    return ReportInvalidPointerPair(pc, bp, sp, a1, a2);
> +
> +  if (a1 == a2)
> +    return;
> +
> +  uptr offset = a1 < a2 ? a2 - a1 : a1 - a2;
> +  uptr left = a1 < a2 ? a1 : a2;
> +  uptr right = a1 < a2 ? a2 : a1;
> +  if (offset <= 2048) {
> +    if (__asan_region_is_poisoned (left, offset) == 0)
> +      return;
> +  }

If offset <= 2048 and something is poisoned in between, then it is
clearly a failure, so you should either goto the error or duplicate
the two lines inside of the outer if above.

> +
> +  uptr shadow_offset1, shadow_offset2;
> +  bool valid1, valid2;
> +  {
> +    ThreadRegistryLock l(&asanThreadRegistry());
> +    valid1 = GetStackVariableBeginning(left, &shadow_offset1);
>    }
> +
> +  // check whether a1 is a stack memory pointer
> +  if (valid1) {
> +    {
> +      ThreadRegistryLock l(&asanThreadRegistry());
> +      valid2 = GetStackVariableBeginning(right - 1, &shadow_offset2);

Why do you take the registery lock twice?  Just do:
  {
    ThreadRegistryLock l(&asanThreadRegistry());
    if (GetStackVariableBeginning(left, &shadow_offset1))
      {
        if (GetStackVariableBeginning(right - 1, &shadow_offset2) &&
            shadow_offset1 == shadow_offset2)
          return;
// goto do_error; or:
        GET_CALLER_PC_BP_SP;
        ReportInvalidPointerPair(pc, bp, sp, a1, a2);
        return;
      }
  }

> +    }
> +
> +    if (valid2 && shadow_offset1 == shadow_offset2)
> +      return;
> +  }
> +  // check whether a1 is a heap memory address
> +  else {
> +    HeapAddressDescription hdesc1;
> +    valid1 = GetHeapAddressInformation(a1, 0, &hdesc1);
> +
> +    if (valid1 && hdesc1.chunk_access.access_type == kAccessTypeInside) {
> +      HeapAddressDescription hdesc2;
> +      valid2 = GetHeapAddressInformation(a2, 0, &hdesc2);

Again, no need for valid1/valid2.  Why do you use above left and right - 1
and here a1 and a2?  Shouldn't it be always left and right - 1?

        Jakub

Reply via email to