Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ template <class Emitter>
bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Expr *SubExpr = CE->getSubExpr();

if (isPunningDereference(SubExpr))
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to call this when we already switch'ed for the cast kind later.

CE);

if (DiscardResult)
return this->delegate(SubExpr);

Expand Down Expand Up @@ -5511,6 +5515,46 @@ bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
return true;
}

template <class Emitter>
bool Compiler<Emitter>::isPunningDereference(const Expr *E)
{
E = E->IgnoreParenImpCasts();

const auto *UO = dyn_cast<UnaryOperator>(E);
if (!UO || UO->getOpcode() != UO_Deref)
return false;

const Expr *Base = UO->getSubExpr()->IgnoreParenImpCasts();
const auto *Cast = dyn_cast<CastExpr>(Base);
if (!Cast)
return false;

// Only consider reinterpret-ish casts
switch (Cast->getCastKind()) {
case CK_BitCast:
case CK_PointerToIntegral:
case CK_IntegralToPointer:
case CK_AddressSpaceConversion:
break;
default:
return false; // CK_NoOp etc. are fine
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did you come up with this list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's tentative. I think we need to check for actual UBness of the cast, as there are cases where some casts are legal and should be allowed in CE

For a POC to see if this fixes the issue I linked, I just put everything that remotely resembles a fishy cast


QualType DestPtrTy = Cast->getType();
QualType SrcPtrTy = Cast->getSubExpr()->getType();
if (!DestPtrTy->isPointerType() || !SrcPtrTy->isPointerType())
return true; // super fishy, treat it as a pun

QualType DestPointee = DestPtrTy->getPointeeType();
QualType SrcPointee = SrcPtrTy->getPointeeType();

// If pointee types differ (ignoring qualifiers), its a pun
if (!Ctx.getASTContext().hasSameUnqualifiedType(DestPointee, SrcPointee))
return true;

return false;
}

static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {
assert(FD);
assert(FD->getParent()->isUnion());
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/ByteCode/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool checkLiteralType(const Expr *E);
bool maybeEmitDeferredVarInit(const VarDecl *VD);

bool isPunningDereference(const Expr *E);

bool refersToUnion(const Expr *E);

protected:
Expand Down
Loading