Skip to content

Commit 5c76b0d

Browse files
committed
[clang][bytecode] Check pointers in GetPtrField{,Pop}
The pointer needs to point to a record. Fixes #166371
1 parent 0400b9a commit 5c76b0d

File tree

6 files changed

+49
-26
lines changed

6 files changed

+49
-26
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,10 @@ static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
14481448
return false;
14491449
}
14501450

1451+
// We can't get the field of something that's not a record.
1452+
if (!Ptr.getFieldDesc()->isRecord())
1453+
return false;
1454+
14511455
if ((Ptr.getByteOffset() + Off) >= Ptr.block()->getSize())
14521456
return false;
14531457

clang/lib/AST/ByteCode/Interp.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,13 +2317,11 @@ std::optional<Pointer> OffsetHelper(InterpState &S, CodePtr OpPC,
23172317
template <PrimType Name, class T = typename PrimConv<Name>::T>
23182318
bool AddOffset(InterpState &S, CodePtr OpPC) {
23192319
const T &Offset = S.Stk.pop<T>();
2320-
Pointer Ptr = S.Stk.pop<Pointer>();
2321-
if (Ptr.isBlockPointer())
2322-
Ptr = Ptr.expand();
2320+
Pointer Ptr = S.Stk.pop<Pointer>().expand();
23232321

23242322
if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Add>(
23252323
S, OpPC, Offset, Ptr, /*IsPointerArith=*/true)) {
2326-
S.Stk.push<Pointer>(*Result);
2324+
S.Stk.push<Pointer>(Result->narrow());
23272325
return true;
23282326
}
23292327
return false;
@@ -2332,11 +2330,11 @@ bool AddOffset(InterpState &S, CodePtr OpPC) {
23322330
template <PrimType Name, class T = typename PrimConv<Name>::T>
23332331
bool SubOffset(InterpState &S, CodePtr OpPC) {
23342332
const T &Offset = S.Stk.pop<T>();
2335-
const Pointer &Ptr = S.Stk.pop<Pointer>();
2333+
Pointer Ptr = S.Stk.pop<Pointer>().expand();
23362334

23372335
if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Sub>(
23382336
S, OpPC, Offset, Ptr, /*IsPointerArith=*/true)) {
2339-
S.Stk.push<Pointer>(*Result);
2337+
S.Stk.push<Pointer>(Result->narrow());
23402338
return true;
23412339
}
23422340
return false;
@@ -3191,7 +3189,7 @@ inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
31913189
}
31923190

31933191
if (Ptr.isRoot() || !Ptr.isUnknownSizeArray()) {
3194-
S.Stk.push<Pointer>(Ptr.atIndex(0));
3192+
S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
31953193
return true;
31963194
}
31973195

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
296296
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
297297
const InterpFrame *Frame,
298298
const CallExpr *Call, unsigned ID) {
299-
const Pointer &StrPtr = S.Stk.pop<Pointer>();
299+
const Pointer &StrPtr = S.Stk.pop<Pointer>().expand();
300300

301301
if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
302302
diagnoseNonConstexprBuiltin(S, OpPC, ID);
@@ -1439,7 +1439,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
14391439
Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
14401440
DynamicAllocator::Form::Operator);
14411441
assert(B);
1442-
S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1442+
S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
14431443
return true;
14441444
}
14451445

@@ -1763,8 +1763,8 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
17631763
assert(Call->getNumArgs() == 3);
17641764
const ASTContext &ASTCtx = S.getASTContext();
17651765
APSInt Size = popToAPSInt(S, Call->getArg(2));
1766-
const Pointer SrcPtr = S.Stk.pop<Pointer>();
1767-
const Pointer DestPtr = S.Stk.pop<Pointer>();
1766+
Pointer SrcPtr = S.Stk.pop<Pointer>().expand();
1767+
Pointer DestPtr = S.Stk.pop<Pointer>().expand();
17681768

17691769
assert(!Size.isSigned() && "memcpy and friends take an unsigned size");
17701770

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,14 @@ def NarrowPtr : Opcode;
361361
// [Pointer] -> [Pointer]
362362
def ExpandPtr : Opcode;
363363
// [Pointer, Offset] -> [Pointer]
364-
def ArrayElemPtr : AluOpcode;
365-
def ArrayElemPtrPop : AluOpcode;
364+
def ArrayElemPtr : Opcode {
365+
let Types = [IntegralTypeClass];
366+
let HasGroup = 1;
367+
}
368+
def ArrayElemPtrPop : Opcode {
369+
let Types = [IntegralTypeClass];
370+
let HasGroup = 1;
371+
}
366372

367373
def ArrayElemPop : Opcode {
368374
let Args = [ArgUint32];
@@ -536,9 +542,15 @@ def InitElemPop : Opcode {
536542
//===----------------------------------------------------------------------===//
537543

538544
// [Pointer, Integral] -> [Pointer]
539-
def AddOffset : AluOpcode;
545+
def AddOffset : Opcode {
546+
let Types = [IntegralTypeClass];
547+
let HasGroup = 1;
548+
}
540549
// [Pointer, Integral] -> [Pointer]
541-
def SubOffset : AluOpcode;
550+
def SubOffset : Opcode {
551+
let Types = [IntegralTypeClass];
552+
let HasGroup = 1;
553+
}
542554

543555
// [Pointer, Pointer] -> [Integral]
544556
def SubPtr : Opcode {

clang/lib/AST/ByteCode/Pointer.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,20 @@ class Pointer {
199199
return Pointer(BS.Pointee, sizeof(InlineDescriptor),
200200
Offset == 0 ? Offset : PastEndMark);
201201

202-
// Pointer is one past end - magic offset marks that.
203-
if (isOnePastEnd())
204-
return Pointer(BS.Pointee, Base, PastEndMark);
205-
206-
if (Offset != Base) {
207-
// If we're pointing to a primitive array element, there's nothing to do.
208-
if (inPrimitiveArray())
209-
return *this;
210-
// Pointer is to a composite array element - enter it.
211-
if (Offset != Base)
212-
return Pointer(BS.Pointee, Offset, Offset);
202+
if (inArray()) {
203+
// Pointer is one past end - magic offset marks that.
204+
if (isOnePastEnd())
205+
return Pointer(BS.Pointee, Base, PastEndMark);
206+
207+
if (Offset != Base) {
208+
// If we're pointing to a primitive array element, there's nothing to
209+
// do.
210+
if (inPrimitiveArray())
211+
return *this;
212+
// Pointer is to a composite array element - enter it.
213+
if (Offset != Base)
214+
return Pointer(BS.Pointee, Offset, Offset);
215+
}
213216
}
214217

215218
// Otherwise, we're pointing to a non-array element or
@@ -219,6 +222,8 @@ class Pointer {
219222

220223
/// Expands a pointer to the containing array, undoing narrowing.
221224
[[nodiscard]] Pointer expand() const {
225+
if (!isBlockPointer())
226+
return *this;
222227
assert(isBlockPointer());
223228
Block *Pointee = BS.Pointee;
224229

clang/test/AST/ByteCode/invalid.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,8 @@ namespace InvalidBitCast {
106106
return ((sockaddr_in *)&addr)->sin_addr.s_addr;
107107
}
108108

109+
110+
struct s { int a; int b[1]; };
111+
struct s myx;
112+
int *myy = ((struct s *)&myx.a)->b;
109113
}

0 commit comments

Comments
 (0)