Skip to content

Commit a586b5a

Browse files
authored
Reland [AArch64][AsmParser] Directives should clear transitively implied features (#106625) (#106850)
Relands 2497739 addressing the buffer overflow caused when dereferencing an iterator past the end of ExtensionMap.
1 parent 55eb93b commit a586b5a

7 files changed

+88
-64
lines changed

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 46 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6947,18 +6947,22 @@ static void ExpandCryptoAEK(const AArch64::ArchInfo &ArchInfo,
69476947
}
69486948
}
69496949

6950+
static SMLoc incrementLoc(SMLoc L, int Offset) {
6951+
return SMLoc::getFromPointer(L.getPointer() + Offset);
6952+
}
6953+
69506954
/// parseDirectiveArch
69516955
/// ::= .arch token
69526956
bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
6953-
SMLoc ArchLoc = getLoc();
6957+
SMLoc CurLoc = getLoc();
69546958

69556959
StringRef Arch, ExtensionString;
69566960
std::tie(Arch, ExtensionString) =
69576961
getParser().parseStringToEndOfStatement().trim().split('+');
69586962

69596963
const AArch64::ArchInfo *ArchInfo = AArch64::parseArch(Arch);
69606964
if (!ArchInfo)
6961-
return Error(ArchLoc, "unknown arch name");
6965+
return Error(CurLoc, "unknown arch name");
69626966

69636967
if (parseToken(AsmToken::EndOfStatement))
69646968
return true;
@@ -6978,27 +6982,29 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
69786982
ExtensionString.split(RequestedExtensions, '+');
69796983

69806984
ExpandCryptoAEK(*ArchInfo, RequestedExtensions);
6985+
CurLoc = incrementLoc(CurLoc, Arch.size());
69816986

6982-
FeatureBitset Features = STI.getFeatureBits();
6983-
setAvailableFeatures(ComputeAvailableFeatures(Features));
69846987
for (auto Name : RequestedExtensions) {
6988+
// Advance source location past '+'.
6989+
CurLoc = incrementLoc(CurLoc, 1);
6990+
69856991
bool EnableFeature = !Name.consume_front_insensitive("no");
69866992

6987-
for (const auto &Extension : ExtensionMap) {
6988-
if (Extension.Name != Name)
6989-
continue;
6993+
auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
6994+
return Extension.Name == Name;
6995+
});
69906996

6991-
if (Extension.Features.none())
6992-
report_fatal_error("unsupported architectural extension: " + Name);
6997+
if (It == std::end(ExtensionMap))
6998+
return Error(CurLoc, "unsupported architectural extension: " + Name);
69936999

6994-
FeatureBitset ToggleFeatures =
6995-
EnableFeature
6996-
? STI.SetFeatureBitsTransitively(~Features & Extension.Features)
6997-
: STI.ToggleFeature(Features & Extension.Features);
6998-
setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
6999-
break;
7000-
}
7000+
if (EnableFeature)
7001+
STI.SetFeatureBitsTransitively(It->Features);
7002+
else
7003+
STI.ClearFeatureBitsTransitively(It->Features);
7004+
CurLoc = incrementLoc(CurLoc, Name.size());
70017005
}
7006+
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7007+
setAvailableFeatures(Features);
70027008
return false;
70037009
}
70047010

@@ -7018,28 +7024,21 @@ bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
70187024
Name = Name.substr(2);
70197025
}
70207026

7021-
MCSubtargetInfo &STI = copySTI();
7022-
FeatureBitset Features = STI.getFeatureBits();
7023-
for (const auto &Extension : ExtensionMap) {
7024-
if (Extension.Name != Name)
7025-
continue;
7026-
7027-
if (Extension.Features.none())
7028-
return Error(ExtLoc, "unsupported architectural extension: " + Name);
7029-
7030-
FeatureBitset ToggleFeatures =
7031-
EnableFeature
7032-
? STI.SetFeatureBitsTransitively(~Features & Extension.Features)
7033-
: STI.ToggleFeature(Features & Extension.Features);
7034-
setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
7035-
return false;
7036-
}
7027+
auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
7028+
return Extension.Name == Name;
7029+
});
70377030

7038-
return Error(ExtLoc, "unknown architectural extension: " + Name);
7039-
}
7031+
if (It == std::end(ExtensionMap))
7032+
return Error(ExtLoc, "unsupported architectural extension: " + Name);
70407033

7041-
static SMLoc incrementLoc(SMLoc L, int Offset) {
7042-
return SMLoc::getFromPointer(L.getPointer() + Offset);
7034+
MCSubtargetInfo &STI = copySTI();
7035+
if (EnableFeature)
7036+
STI.SetFeatureBitsTransitively(It->Features);
7037+
else
7038+
STI.ClearFeatureBitsTransitively(It->Features);
7039+
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7040+
setAvailableFeatures(Features);
7041+
return false;
70437042
}
70447043

70457044
/// parseDirectiveCPU
@@ -7075,30 +7074,21 @@ bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
70757074

70767075
bool EnableFeature = !Name.consume_front_insensitive("no");
70777076

7078-
bool FoundExtension = false;
7079-
for (const auto &Extension : ExtensionMap) {
7080-
if (Extension.Name != Name)
7081-
continue;
7077+
auto It = llvm::find_if(ExtensionMap, [&Name](const auto &Extension) {
7078+
return Extension.Name == Name;
7079+
});
70827080

7083-
if (Extension.Features.none())
7084-
report_fatal_error("unsupported architectural extension: " + Name);
7085-
7086-
FeatureBitset Features = STI.getFeatureBits();
7087-
FeatureBitset ToggleFeatures =
7088-
EnableFeature
7089-
? STI.SetFeatureBitsTransitively(~Features & Extension.Features)
7090-
: STI.ToggleFeature(Features & Extension.Features);
7091-
setAvailableFeatures(ComputeAvailableFeatures(ToggleFeatures));
7092-
FoundExtension = true;
7093-
7094-
break;
7095-
}
7096-
7097-
if (!FoundExtension)
7098-
Error(CurLoc, "unsupported architectural extension");
7081+
if (It == std::end(ExtensionMap))
7082+
return Error(CurLoc, "unsupported architectural extension: " + Name);
70997083

7084+
if (EnableFeature)
7085+
STI.SetFeatureBitsTransitively(It->Features);
7086+
else
7087+
STI.ClearFeatureBitsTransitively(It->Features);
71007088
CurLoc = incrementLoc(CurLoc, Name.size());
71017089
}
7090+
FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits());
7091+
setAvailableFeatures(Features);
71027092
return false;
71037093
}
71047094

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s
2+
3+
// Check that setting +nosve implies +nosve2
4+
.arch armv9-a+nosve
5+
6+
adclb z0.s, z1.s, z31.s
7+
// CHECK: error: instruction requires: sve2
8+
// CHECK-NEXT: adclb z0.s, z1.s, z31.s
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s
22

3-
.arch_extension nosve
3+
.arch_extension sve2+nosve
44

55
ptrue p0.b, pow2
66
// CHECK: error: instruction requires: sve or sme
77
// CHECK-NEXT: ptrue p0.b, pow2
8+
9+
// Check that setting +nosve implies +nosve2
10+
adclb z0.s, z1.s, z31.s
11+
// CHECK: error: instruction requires: sve2
12+
// CHECK-NEXT: adclb z0.s, z1.s, z31.s
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s
22

3-
.cpu generic+sve+nosve
3+
.cpu generic+sve2+nosve
44
ptrue p0.b, pow2
55
// CHECK: error: instruction requires: sve or sme
66
// CHECK-NEXT: ptrue p0.b, pow2
7+
8+
// Check that setting +nosve implies +nosve2
9+
adclb z0.s, z1.s, z31.s
10+
// CHECK: error: instruction requires: sve2
11+
// CHECK-NEXT: adclb z0.s, z1.s, z31.s

llvm/test/MC/AArch64/directive-arch-negative.s

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
# CHECK-NEXT: aese v0.8h, v1.8h
1313
# CHECK-NEXT: ^
1414

15-
// We silently ignore invalid features.
16-
.arch armv8+foo
15+
.arch armv8+foo+nobar
1716
aese v0.8h, v1.8h
1817

18+
# CHECK: error: unsupported architectural extension: foo
19+
# CHECK-NEXT: .arch armv8+foo+nobar
20+
# CHECK-NEXT: ^
21+
1922
# CHECK: error: invalid operand for instruction
2023
# CHECK-NEXT: aese v0.8h, v1.8h
2124
# CHECK-NEXT: ^

llvm/test/MC/AArch64/directive-arch_extension-negative.s

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// RUN: -filetype asm -o - %s 2>&1 | FileCheck %s
55

66
.arch_extension axp64
7-
// CHECK: error: unknown architectural extension: axp64
7+
// CHECK: error: unsupported architectural extension: axp64
88
// CHECK-NEXT: .arch_extension axp64
99

1010
crc32cx w0, w1, x3
@@ -49,6 +49,8 @@ fminnm d0, d0, d1
4949
// CHECK: [[@LINE-1]]:1: error: instruction requires: fp
5050
// CHECK-NEXT: fminnm d0, d0, d1
5151

52+
// nofp implied nosimd, so reinstate it
53+
.arch_extension simd
5254
addp v0.4s, v0.4s, v0.4s
5355
// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: neon
5456
.arch_extension nosimd
@@ -70,6 +72,8 @@ casa w5, w7, [x20]
7072
// CHECK: [[@LINE-1]]:1: error: instruction requires: lse
7173
// CHECK-NEXT: casa w5, w7, [x20]
7274

75+
// nolse implied nolse128, so reinstate it
76+
.arch_extension lse128
7377
swpp x0, x2, [x3]
7478
// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: lse128
7579
.arch_extension nolse128
@@ -84,6 +88,8 @@ cfp rctx, x0
8488
// CHECK: [[@LINE-1]]:5: error: CFPRCTX requires: predres
8589
// CHECK-NEXT: cfp rctx, x0
8690

91+
// nopredres implied nopredres2, so reinstate it
92+
.arch_extension predres2
8793
cosp rctx, x0
8894
// CHECK-NOT: [[@LINE-1]]:6: error: COSP requires: predres2
8995
.arch_extension nopredres2
@@ -133,6 +139,8 @@ ldapr x0, [x1]
133139
// CHECK: [[@LINE-1]]:1: error: instruction requires: rcpc
134140
// CHECK-NEXT: ldapr x0, [x1]
135141

142+
// norcpc implied norcpc3, so reinstate it
143+
.arch_extension rcpc3
136144
stilp w24, w0, [x16, #-8]!
137145
// CHECK-NOT: [[@LINE-1]]:1: error: instruction requires: rcpc3
138146
.arch_extension norcpc3
@@ -169,6 +177,8 @@ cpyfp [x0]!, [x1]!, x2!
169177
// CHECK: [[@LINE-1]]:1: error: instruction requires: mops
170178
// CHECK-NEXT: cpyfp [x0]!, [x1]!, x2!
171179

180+
// nolse128 implied nod128, so reinstate it
181+
.arch_extension d128
172182
// This needs to come before `.arch_extension nothe` as it uses an instruction
173183
// that requires both the and d128
174184
sysp #0, c2, c0, #0, x0, x1
@@ -204,6 +214,8 @@ umax x0, x1, x2
204214
// CHECK: [[@LINE-1]]:1: error: instruction requires: cssc
205215
// CHECK-NEXT: umax x0, x1, x2
206216

217+
// noras implied norasv2, so reinstate it
218+
.arch_extension rasv2
207219
mrs x0, ERXGSR_EL1
208220
// CHECK-NOT: [[@LINE-1]]:9: error: expected readable system register
209221
.arch_extension norasv2

llvm/test/MC/AArch64/directive-cpu-err.s

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
.cpu invalid
55
// CHECK: error: unknown CPU name
66

7-
.cpu generic+wibble+nowobble
8-
// CHECK: :[[@LINE-1]]:18: error: unsupported architectural extension
9-
// CHECK: :[[@LINE-2]]:25: error: unsupported architectural extension
7+
.cpu generic+fp+wibble+nowobble
8+
// CHECK: error: unsupported architectural extension: wibble
9+
// CHECK-NEXT: .cpu generic+fp+wibble+nowobble
10+
// CHECK-NEXT: ^
1011

1112
.cpu generic+nofp
1213
fminnm d0, d0, d1

0 commit comments

Comments
 (0)