Skip to content

Commit 1f34837

Browse files
committed
[clang][modules] Fix use-after-free in header serialization (llvm#96356)
With the pruning of unused module map files disabled (`-fno-modules-prune-non-affecting-module-map-files`), `HeaderFileInfo` no longer gets deserialized before `ASTWriter::WriteHeaderSearch()`. This function then interleaves the stores of references to `KnownHeader` with their lazy deserialization. Lazy deserialization may cause reallocation of `ModuleMap::Headers` entries (including its `SmallVector<KnownHeader, 1>` values) thus making previously-stored `ArrayRef<KnownHeader>` dangling. This patch fixes that situation by storing a copy instead. (cherry picked from commit 0387a86)
1 parent 3602748 commit 1f34837

File tree

2 files changed

+188
-2
lines changed

2 files changed

+188
-2
lines changed

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,9 +1928,15 @@ namespace {
19281928
llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>;
19291929

19301930
struct data_type {
1931-
const HeaderFileInfo &HFI;
1931+
data_type(const HeaderFileInfo &HFI, bool AlreadyIncluded,
1932+
ArrayRef<ModuleMap::KnownHeader> KnownHeaders,
1933+
UnresolvedModule Unresolved)
1934+
: HFI(HFI), AlreadyIncluded(AlreadyIncluded),
1935+
KnownHeaders(KnownHeaders), Unresolved(Unresolved) {}
1936+
1937+
HeaderFileInfo HFI;
19321938
bool AlreadyIncluded;
1933-
ArrayRef<ModuleMap::KnownHeader> KnownHeaders;
1939+
SmallVector<ModuleMap::KnownHeader, 1> KnownHeaders;
19341940
UnresolvedModule Unresolved;
19351941
};
19361942
using data_type_ref = const data_type &;

clang/test/Modules/use-after-free-2.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// RUN: rm -rf %t
2+
// RUN: split-file %s %t
3+
4+
//--- A.modulemap
5+
module A {
6+
header "A.h"
7+
8+
textual header "A00.h"
9+
textual header "A01.h"
10+
textual header "A02.h"
11+
textual header "A03.h"
12+
textual header "A04.h"
13+
textual header "A05.h"
14+
textual header "A06.h"
15+
textual header "A07.h"
16+
textual header "A08.h"
17+
textual header "A09.h"
18+
19+
textual header "A10.h"
20+
textual header "A11.h"
21+
textual header "A12.h"
22+
textual header "A13.h"
23+
textual header "A14.h"
24+
textual header "A15.h"
25+
textual header "A16.h"
26+
textual header "A17.h"
27+
textual header "A18.h"
28+
textual header "A19.h"
29+
30+
textual header "A20.h"
31+
textual header "A21.h"
32+
textual header "A22.h"
33+
textual header "A23.h"
34+
textual header "A24.h"
35+
textual header "A25.h"
36+
textual header "A26.h"
37+
textual header "A27.h"
38+
textual header "A28.h"
39+
textual header "A29.h"
40+
41+
textual header "A30.h"
42+
textual header "A31.h"
43+
textual header "A32.h"
44+
textual header "A33.h"
45+
textual header "A34.h"
46+
textual header "A35.h"
47+
textual header "A36.h"
48+
textual header "A37.h"
49+
textual header "A38.h"
50+
textual header "A39.h"
51+
52+
textual header "A40.h"
53+
textual header "A41.h"
54+
textual header "A42.h"
55+
textual header "A43.h"
56+
textual header "A44.h"
57+
textual header "A45.h"
58+
}
59+
//--- A.h
60+
61+
//--- A00.h
62+
//--- A01.h
63+
//--- A02.h
64+
//--- A03.h
65+
//--- A04.h
66+
//--- A05.h
67+
//--- A06.h
68+
//--- A07.h
69+
//--- A08.h
70+
//--- A09.h
71+
72+
//--- A10.h
73+
//--- A11.h
74+
//--- A12.h
75+
//--- A13.h
76+
//--- A14.h
77+
//--- A15.h
78+
//--- A16.h
79+
//--- A17.h
80+
//--- A18.h
81+
//--- A19.h
82+
83+
//--- A20.h
84+
//--- A21.h
85+
//--- A22.h
86+
//--- A23.h
87+
//--- A24.h
88+
//--- A25.h
89+
//--- A26.h
90+
//--- A27.h
91+
//--- A28.h
92+
//--- A29.h
93+
94+
//--- A30.h
95+
//--- A31.h
96+
//--- A32.h
97+
//--- A33.h
98+
//--- A34.h
99+
//--- A35.h
100+
//--- A36.h
101+
//--- A37.h
102+
//--- A38.h
103+
//--- A39.h
104+
105+
//--- A40.h
106+
//--- A41.h
107+
//--- A42.h
108+
//--- A43.h
109+
//--- A44.h
110+
//--- A45.h
111+
112+
//--- B.modulemap
113+
module B { header "B.h" }
114+
//--- B.h
115+
#include "A.h"
116+
117+
//--- C.modulemap
118+
module C { header "C.h" }
119+
//--- C.h
120+
#include "A00.h"
121+
#include "A01.h"
122+
#include "A02.h"
123+
#include "A03.h"
124+
#include "A04.h"
125+
#include "A05.h"
126+
#include "A06.h"
127+
#include "A07.h"
128+
#include "A08.h"
129+
#include "A09.h"
130+
131+
#include "A10.h"
132+
#include "A11.h"
133+
#include "A12.h"
134+
#include "A13.h"
135+
#include "A14.h"
136+
#include "A15.h"
137+
#include "A16.h"
138+
#include "A17.h"
139+
#include "A18.h"
140+
#include "A19.h"
141+
142+
#include "A20.h"
143+
#include "A21.h"
144+
#include "A22.h"
145+
#include "A23.h"
146+
#include "A24.h"
147+
#include "A25.h"
148+
#include "A26.h"
149+
#include "A27.h"
150+
#include "A28.h"
151+
#include "A29.h"
152+
153+
#include "A30.h"
154+
#include "A31.h"
155+
#include "A32.h"
156+
#include "A33.h"
157+
#include "A34.h"
158+
#include "A35.h"
159+
#include "A36.h"
160+
#include "A37.h"
161+
#include "A38.h"
162+
#include "A39.h"
163+
164+
#include "A40.h"
165+
#include "A41.h"
166+
#include "A42.h"
167+
#include "A43.h"
168+
#include "A44.h"
169+
#include "A45.h"
170+
171+
#include "B.h"
172+
173+
// RUN: %clang_cc1 -fmodules -fno-modules-prune-non-affecting-module-map-files \
174+
// RUN: -emit-module %t/A.modulemap -fmodule-name=A -o %t/A.pcm
175+
// RUN: %clang_cc1 -fmodules -fno-modules-prune-non-affecting-module-map-files \
176+
// RUN: -emit-module %t/B.modulemap -fmodule-name=B -o %t/B.pcm \
177+
// RUN: -fmodule-file=A=%t/A.pcm -fmodule-map-file=%t/A.modulemap
178+
// RUN: %clang_cc1 -fmodules -fno-modules-prune-non-affecting-module-map-files \
179+
// RUN: -emit-module %t/C.modulemap -fmodule-name=C -o %t/C.pcm \
180+
// RUN: -fmodule-file=B=%t/B.pcm -fmodule-map-file=%t/B.modulemap

0 commit comments

Comments
 (0)