[PATCH] Perform calculation of array size in chars instead of bits to prevent an assertion.

Richard Smith richard at metafoo.co.uk
Fri May 10 19:51:55 PDT 2013


On Fri, May 10, 2013 at 7:35 PM, Richard Trieu <rtrieu at google.com> wrote:

> For large arrays, the size calculation in bits may overflow a uint64_t.
>  If only the size in chars is important, perform the calculation in chars
> to prevent this overflow which triggers an assertion.  This fixes PR15216.
>
> http://llvm-reviews.chandlerc.com/D781
>
> Files:
>   test/Sema/offsetof.c
>   include/clang/AST/ASTContext.h
>   lib/AST/ASTContext.cpp
>
> Index: test/Sema/offsetof.c
> ===================================================================
> --- test/Sema/offsetof.c
> +++ test/Sema/offsetof.c
> @@ -69,3 +69,15 @@
>  int test5() {
>    return __builtin_offsetof(Array, array[*(int*)0]); //
> expected-warning{{indirection of non-volatile null pointer}}
> expected-note{{__builtin_trap}}
>  }
> +
> +// PR15216
> +// Don't crash on when taking computing the offset of structs with large
> arrays.
> +const unsigned long Size = (1l << 62);
> +
> +struct Chunk {
> +  char padding[Size];
> +  char data;
> +};
> +
> +int test6 = __builtin_offsetof(struct Chunk, data);
> +
> Index: include/clang/AST/ASTContext.h
> ===================================================================
> --- include/clang/AST/ASTContext.h
> +++ include/clang/AST/ASTContext.h
> @@ -1591,6 +1591,9 @@
>    std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
>    std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
>
> +  std::pair<CharUnits, CharUnits> getConstantArrayInfoInChars(
> +      const ConstantArrayType* CAT) const;
> +
>    /// \brief Return the "preferred" alignment of the specified type \p T
> for
>    /// the current target, in bits.
>    ///
> Index: lib/AST/ASTContext.cpp
> ===================================================================
> --- lib/AST/ASTContext.cpp
> +++ lib/AST/ASTContext.cpp
> @@ -1345,11 +1345,28 @@
>
>  std::pair<CharUnits, CharUnits>
>  ASTContext::getTypeInfoInChars(const Type *T) const {
> +  if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
> +    return getConstantArrayInfoInChars(CAT);
>    std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
>    return std::make_pair(toCharUnitsFromBits(Info.first),
>                          toCharUnitsFromBits(Info.second));
>  }
>
> +/// getConstantArrayInfoInChars - Performing the computation in CharUnits
> +/// instead of in bits prevents overflowing the uint64_t for some large
> arrays.
> +std::pair<CharUnits, CharUnits>
> +ASTContext::getConstantArrayInfoInChars(const ConstantArrayType *CAT)
> const {
>

Can you make this a static non-member helper function? I don't think we
need it to be part of ASTContext's interface.


> +  std::pair<uint64_t, unsigned> EltInfo =
> getTypeInfo(CAT->getElementType());
> +  uint64_t Size = CAT->getSize().getZExtValue();
> +  assert((Size == 0 || EltInfo.first/getCharWidth() <=
> (uint64_t)(-1)/Size) &&
> +         "Overflow in array type char size evaluation");
> +  uint64_t Width = EltInfo.first / getCharWidth() * Size;
> +  unsigned Align = EltInfo.second / getCharWidth();
> +  Width = llvm::RoundUpToAlignment(Width, Align);
> +  return std::make_pair(CharUnits::fromQuantity(Width),
> +                        CharUnits::fromQuantity(Align));
> +}
> +
>  std::pair<CharUnits, CharUnits>
>  ASTContext::getTypeInfoInChars(QualType T) const {
>    return getTypeInfoInChars(T.getTypePtr());
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130510/6952f9a2/attachment.html>


More information about the cfe-commits mailing list