Skip to content

[clang][bytecode] Fix checking for integer overflow #137962

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 1, 2025
Merged
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
1 change: 1 addition & 0 deletions clang/lib/AST/ByteCode/ByteCodeEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class ByteCodeEmitter {

/// We're always emitting bytecode.
bool isActive() const { return true; }
bool checkingForUndefinedBehavior() const { return false; }

/// Callback for local registration.
Local createLocal(Descriptor *D);
Expand Down
21 changes: 17 additions & 4 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -866,12 +866,14 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {

// Assignments require us to evalute the RHS first.
if (BO->getOpcode() == BO_Assign) {
// We don't support assignments in C.
if (!Ctx.getLangOpts().CPlusPlus)
return this->emitInvalid(BO);

if (!visit(RHS) || !visit(LHS))
return false;

// We don't support assignments in C.
if (!Ctx.getLangOpts().CPlusPlus && !this->emitInvalid(BO))
return false;

if (!this->emitFlip(*LT, *RT, BO))
return false;
} else {
Expand Down Expand Up @@ -2364,8 +2366,19 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
return false;
}

if (!this->visitBool(Condition))
if (!this->visitBool(Condition)) {
// If the condition failed and we're checking for undefined behavior
// (which only happens with EvalEmitter) check the TrueExpr and FalseExpr
// as well.
if (this->checkingForUndefinedBehavior()) {
if (!this->discard(TrueExpr))
return false;
if (!this->discard(FalseExpr))
return false;
}
return false;
}

if (!this->jumpFalse(LabelFalse))
return false;
if (!visitChildExpr(TrueExpr))
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/ByteCode/EvalEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ class EvalEmitter : public SourceMapper {
/// Since expressions can only jump forward, predicated execution is
/// used to deal with if-else statements.
bool isActive() const { return CurrentLabel == ActiveLabel; }
bool checkingForUndefinedBehavior() const {
return S.checkingForUndefinedBehavior();
}

/// Callback for registering a local.
Local createLocal(Descriptor *D);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
}

if (Off > Ptr.block()->getSize())
if ((Ptr.getByteOffset() + Off) >= Ptr.block()->getSize())
return false;

S.Stk.push<Pointer>(Ptr.atField(Off));
Expand Down
1 change: 1 addition & 0 deletions clang/test/Sema/integer-overflow.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -verify -fsyntax-only -triple x86_64-pc-linux-gnu
// RUN: %clang_cc1 %s -verify -fsyntax-only -triple x86_64-pc-linux-gnu -fexperimental-new-constant-interpreter
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;

Expand Down