Skip to content

Commit d7e40f3

Browse files
authored
[clang][bytecode] Call CheckStore() before activating pointers (#165235)
We used to do this the other way around to work around an awkwardness with CheckStore, namely that we shouldn't check pointers for being activated when activating them. Add a parameter to CheckStore instead and call CheckStore() _before_ activating and initializing the pointers in the respective opcode implementations. Fixes #164975
1 parent 51cecd3 commit d7e40f3

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,8 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
870870
return true;
871871
}
872872

873-
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
873+
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
874+
bool WillBeActivated) {
874875
if (!Ptr.isBlockPointer() || Ptr.isZero())
875876
return false;
876877

@@ -885,7 +886,7 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
885886
return false;
886887
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
887888
return false;
888-
if (!CheckActive(S, OpPC, Ptr, AK_Assign))
889+
if (!WillBeActivated && !CheckActive(S, OpPC, Ptr, AK_Assign))
889890
return false;
890891
if (!CheckGlobal(S, OpPC, Ptr))
891892
return false;

clang/lib/AST/ByteCode/Interp.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B);
7575
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B);
7676

7777
/// Checks if a value can be stored in a block.
78-
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
78+
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
79+
bool WillBeActivated = false);
7980

8081
/// Checks if a value can be initialized.
8182
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
@@ -1977,13 +1978,12 @@ bool StoreActivate(InterpState &S, CodePtr OpPC) {
19771978
const T &Value = S.Stk.pop<T>();
19781979
const Pointer &Ptr = S.Stk.peek<Pointer>();
19791980

1981+
if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
1982+
return false;
19801983
if (Ptr.canBeInitialized()) {
19811984
Ptr.initialize();
19821985
Ptr.activate();
19831986
}
1984-
1985-
if (!CheckStore(S, OpPC, Ptr))
1986-
return false;
19871987
Ptr.deref<T>() = Value;
19881988
return true;
19891989
}
@@ -1993,12 +1993,12 @@ bool StoreActivatePop(InterpState &S, CodePtr OpPC) {
19931993
const T &Value = S.Stk.pop<T>();
19941994
const Pointer &Ptr = S.Stk.pop<Pointer>();
19951995

1996+
if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
1997+
return false;
19961998
if (Ptr.canBeInitialized()) {
19971999
Ptr.initialize();
19982000
Ptr.activate();
19992001
}
2000-
if (!CheckStore(S, OpPC, Ptr))
2001-
return false;
20022002
Ptr.deref<T>() = Value;
20032003
return true;
20042004
}
@@ -2007,7 +2007,8 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
20072007
bool StoreBitField(InterpState &S, CodePtr OpPC) {
20082008
const T &Value = S.Stk.pop<T>();
20092009
const Pointer &Ptr = S.Stk.peek<Pointer>();
2010-
if (!CheckStore(S, OpPC, Ptr))
2010+
2011+
if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
20112012
return false;
20122013
if (Ptr.canBeInitialized())
20132014
Ptr.initialize();
@@ -2037,12 +2038,13 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
20372038
bool StoreBitFieldActivate(InterpState &S, CodePtr OpPC) {
20382039
const T &Value = S.Stk.pop<T>();
20392040
const Pointer &Ptr = S.Stk.peek<Pointer>();
2041+
2042+
if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
2043+
return false;
20402044
if (Ptr.canBeInitialized()) {
20412045
Ptr.initialize();
20422046
Ptr.activate();
20432047
}
2044-
if (!CheckStore(S, OpPC, Ptr))
2045-
return false;
20462048
if (const auto *FD = Ptr.getField())
20472049
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
20482050
else
@@ -2055,12 +2057,12 @@ bool StoreBitFieldActivatePop(InterpState &S, CodePtr OpPC) {
20552057
const T &Value = S.Stk.pop<T>();
20562058
const Pointer &Ptr = S.Stk.pop<Pointer>();
20572059

2060+
if (!CheckStore(S, OpPC, Ptr, /*WillBeActivated=*/true))
2061+
return false;
20582062
if (Ptr.canBeInitialized()) {
20592063
Ptr.initialize();
20602064
Ptr.activate();
20612065
}
2062-
if (!CheckStore(S, OpPC, Ptr))
2063-
return false;
20642066
if (const auto *FD = Ptr.getField())
20652067
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
20662068
else

clang/test/AST/ByteCode/unions.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,4 +977,13 @@ namespace UnionMemberOnePastEnd {
977977
}
978978
static_assert(!b());
979979
}
980+
981+
namespace ActicvateInvalidPtr {
982+
constexpr void bar() { // both-error {{never produces a constant expression}}
983+
union {
984+
int a[1];
985+
} foo;
986+
foo.a[1] = 0; // both-note {{assignment to dereferenced one-past-the-end pointer}}
987+
}
988+
}
980989
#endif

0 commit comments

Comments
 (0)