Skip to content

Commit 17f3394

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:34415fd611e2 into amd-gfx:7ec97b47cb56
Local branch amd-gfx 7ec97b4 Merged main:985362e2f38f into amd-gfx:9003dd05f959 Remote branch main 34415fd [Clang][LLVM][Coroutines] Prevent __coro_gro from outliving __promise (llvm#66706)
2 parents 7ec97b4 + 34415fd commit 17f3394

File tree

12 files changed

+305
-34
lines changed

12 files changed

+305
-34
lines changed

clang/lib/Basic/Sarif.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ static std::string fileNameToURI(StringRef Filename) {
8787
assert(Iter != End && "Expected there to be a non-root path component.");
8888
// Add the rest of the path components, encoding any reserved characters;
8989
// we skip past the first path component, as it was handled it above.
90-
std::for_each(++Iter, End, [&Ret](StringRef Component) {
90+
for (StringRef Component : llvm::make_range(++Iter, End)) {
9191
// For reasons unknown to me, we may get a backslash with Windows native
9292
// paths for the initial backslash following the drive component, which
9393
// we need to ignore as a URI path part.
9494
if (Component == "\\")
95-
return;
95+
continue;
9696

9797
// Add the separator between the previous path part and the one being
9898
// currently processed.
@@ -102,7 +102,7 @@ static std::string fileNameToURI(StringRef Filename) {
102102
for (char C : Component) {
103103
Ret += percentEncodeURICharacter(C);
104104
}
105-
});
105+
}
106106

107107
return std::string(Ret);
108108
}

clang/lib/CodeGen/CGCoroutine.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,11 @@ struct GetReturnObjectManager {
535535
Builder.CreateStore(Builder.getFalse(), GroActiveFlag);
536536

537537
GroEmission = CGF.EmitAutoVarAlloca(*GroVarDecl);
538+
auto *GroAlloca = dyn_cast_or_null<llvm::AllocaInst>(
539+
GroEmission.getOriginalAllocatedAddress().getPointer());
540+
assert(GroAlloca && "expected alloca to be emitted");
541+
GroAlloca->setMetadata(llvm::LLVMContext::MD_coro_outside_frame,
542+
llvm::MDNode::get(CGF.CGM.getLLVMContext(), {}));
538543

539544
// Remember the top of EHStack before emitting the cleanup.
540545
auto old_top = CGF.EHStack.stable_begin();

clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -744,12 +744,14 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
744744
// Sinks
745745
{{{"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
746746
{{{"popen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
747-
{{{"execl"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
748-
{{{"execle"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
749-
{{{"execlp"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
750-
{{{"execvp"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
751-
{{{"execvP"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
752-
{{{"execve"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
747+
{{{"execl"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)},
748+
{{{"execle"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)},
749+
{{{"execlp"}}, TR::Sink({{}, {0}}, MsgSanitizeSystemArgs)},
750+
{{{"execv"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)},
751+
{{{"execve"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)},
752+
{{{"fexecve"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)},
753+
{{{"execvp"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)},
754+
{{{"execvpe"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)},
753755
{{{"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
754756
{{CDF_MaybeBuiltin, {{"malloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
755757
{{CDF_MaybeBuiltin, {{"calloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},

clang/test/Analysis/taint-generic.c

Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ void clang_analyzer_isTainted_wchar(wchar_t);
6464
void clang_analyzer_isTainted_charp(char*);
6565
void clang_analyzer_isTainted_int(int);
6666

67+
int coin();
68+
6769
int scanf(const char *restrict format, ...);
6870
char *gets(char *str);
6971
char *gets_s(char *str, rsize_t n);
@@ -118,6 +120,41 @@ void *malloc(size_t);
118120
void *calloc(size_t nmemb, size_t size);
119121
void bcopy(void *s1, void *s2, size_t n);
120122

123+
124+
// function | pathname | filename | fd | arglist | argv[] | envp[]
125+
// ===============================================================
126+
// 1 execl | X | | | X | |
127+
// 2 execle | X | | | X | | X
128+
// 3 execlp | | X | | X | |
129+
// 4 execv | X | | | | X |
130+
// 5 execve | X | | | | X | X
131+
// 6 execvp | | X | | | X |
132+
// 7 execvpe | | X | | | X | X
133+
// 8 fexecve | | | X | | X | X
134+
// ===============================================================
135+
// letter | | p | f | l | v | e
136+
//
137+
// legend:
138+
// - pathname: rel/abs path to the binary
139+
// - filename: file name searched in PATH to execute the binary
140+
// - fd: accepts a file descriptor
141+
// - arglist: accepts variadic arguments
142+
// - argv: accepts a pointer to array, denoting the new argv
143+
// - envp: accepts a pointer to array, denoting the new envp
144+
145+
int execl(const char *path, const char *arg, ...);
146+
int execle(const char *path, const char *arg, ...);
147+
int execlp(const char *file, const char *arg, ...);
148+
int execv(const char *path, char *const argv[]);
149+
int execve(const char *path, char *const argv[], char *const envp[]);
150+
int execvp(const char *file, char *const argv[]);
151+
int execvpe(const char *file, char *const argv[], char *const envp[]);
152+
int fexecve(int fd, char *const argv[], char *const envp[]);
153+
FILE *popen(const char *command, const char *type);
154+
int pclose(FILE *stream);
155+
int system(const char *command);
156+
157+
121158
typedef size_t socklen_t;
122159

123160
struct sockaddr {
@@ -224,7 +261,6 @@ void testUncontrolledFormatString(char **p) {
224261

225262
}
226263

227-
int system(const char *command);
228264
void testTaintSystemCall(void) {
229265
char buffer[156];
230266
char addr[128];
@@ -287,7 +323,6 @@ void testTaintedBufferSize(void) {
287323
#define SOCK_STREAM 1
288324
int socket(int, int, int);
289325
size_t read(int, void *, size_t);
290-
int execl(const char *, const char *, ...);
291326

292327
void testSocket(void) {
293328
int sock;
@@ -1129,6 +1164,128 @@ void testConfigurationSinks(void) {
11291164
// expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
11301165
}
11311166

1167+
int test_exec_like_functions() {
1168+
char buf[100] = {0};
1169+
scanf("%99s", buf);
1170+
clang_analyzer_isTainted_char(buf[0]); // expected-warning {{YES}}
1171+
1172+
char *cleanArray[] = {"ENV1=V1", "ENV2=V2", NULL};
1173+
char *taintedArray[] = {buf, "ENV2=V2", NULL};
1174+
clang_analyzer_isTainted_char(taintedArray[0][0]); // expected-warning {{YES}}
1175+
clang_analyzer_isTainted_char(*(char*)taintedArray[0]); // expected-warning {{YES}}
1176+
clang_analyzer_isTainted_char(*(char*)taintedArray); // expected-warning {{NO}} We should have YES here.
1177+
// FIXME: Above the triple pointer indirection will confuse the checker,
1178+
// as we only check two levels. The results would be worse, if the tainted
1179+
// subobject ("buf") would not be at the beginning of the enclosing object,
1180+
// for the same reason.
1181+
1182+
switch (coin()) {
1183+
default: break;
1184+
// Execute `path` with all arguments after `path` until a NULL pointer
1185+
// and environment from `environ'.
1186+
case 0: return execl("path", "arg0", "arg1", "arg2", NULL); // no-warning
1187+
case 1: return execl(buf, "arg0", "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1188+
case 2: return execl("path", buf, "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1189+
case 3: return execl("path", "arg0", buf, "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1190+
case 4: return execl("path", "arg0", "arg1", buf, NULL); // expected-warning {{Untrusted data is passed to a system call}}
1191+
}
1192+
1193+
switch (coin()) {
1194+
default: break;
1195+
// Execute `path` with all arguments after `PATH` until a NULL pointer,
1196+
// and the argument after that for environment.
1197+
case 0: return execle("path", "arg0", "arg1", NULL, cleanArray); // no-warning
1198+
case 1: return execle( buf, "arg0", "arg1", NULL, cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1199+
case 2: return execle("path", buf, "arg1", NULL, cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1200+
case 3: return execle("path", "arg0", buf, NULL, cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1201+
case 4: return execle("path", "arg0", "arg1", NULL, buf); // expected-warning {{Untrusted data is passed to a system call}}
1202+
case 5: return execle("path", "arg0", "arg1", NULL, taintedArray); // FIXME: We might wanna have a report here.
1203+
}
1204+
1205+
switch (coin()) {
1206+
default: break;
1207+
// Execute `file`, searching in the `PATH' environment variable if it
1208+
// contains no slashes, with all arguments after `file` until a NULL
1209+
// pointer and environment from `environ'.
1210+
case 0: return execlp("file", "arg0", "arg1", "arg2", NULL); // no-warning
1211+
case 1: return execlp( buf, "arg0", "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1212+
case 2: return execlp("file", buf, "arg1", "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1213+
case 3: return execlp("file", "arg0", buf, "arg2", NULL); // expected-warning {{Untrusted data is passed to a system call}}
1214+
case 4: return execlp("file", "arg0", "arg1", buf, NULL); // expected-warning {{Untrusted data is passed to a system call}}
1215+
}
1216+
1217+
switch (coin()) {
1218+
default: break;
1219+
// Execute `path` with arguments `ARGV` and environment from `environ'.
1220+
case 0: return execv("path", /*argv=*/ cleanArray); // no-warning
1221+
case 1: return execv( buf, /*argv=*/ cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1222+
case 2: return execv("path", /*argv=*/taintedArray); // FIXME: We might wanna have a report here.
1223+
}
1224+
1225+
switch (coin()) {
1226+
default: break;
1227+
// Replace the current process, executing `path` with arguments `ARGV`
1228+
// and environment `ENVP`. `ARGV` and `ENVP` are terminated by NULL pointers.
1229+
case 0: return execve("path", /*argv=*/ cleanArray, /*envp=*/cleanArray); // no-warning
1230+
case 1: return execve( buf, /*argv=*/ cleanArray, /*envp=*/cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1231+
case 2: return execve("path", /*argv=*/taintedArray, /*envp=*/cleanArray); // FIXME: We might wanna have a report here.
1232+
case 3: return execve("path", /*argv=*/cleanArray, /*envp=*/taintedArray); // FIXME: We might wanna have a report here.
1233+
}
1234+
1235+
switch (coin()) {
1236+
default: break;
1237+
// Execute `file`, searching in the `PATH' environment variable if it
1238+
// contains no slashes, with arguments `ARGV` and environment from `environ'.
1239+
case 0: return execvp("file", /*argv=*/ cleanArray); // no-warning
1240+
case 1: return execvp( buf, /*argv=*/ cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1241+
case 2: return execvp("file", /*argv=*/taintedArray); // FIXME: We might wanna have a report here.
1242+
}
1243+
1244+
// execvpe
1245+
switch (coin()) {
1246+
default: break;
1247+
// Execute `file`, searching in the `PATH' environment variable if it
1248+
// contains no slashes, with arguments `ARGV` and environment `ENVP`.
1249+
// `ARGV` and `ENVP` are terminated by NULL pointers.
1250+
case 0: return execvpe("file", /*argv=*/ cleanArray, /*envp=*/ cleanArray); // no-warning
1251+
case 1: return execvpe( buf, /*argv=*/ cleanArray, /*envp=*/ cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1252+
case 2: return execvpe("file", /*argv=*/taintedArray, /*envp=*/ cleanArray); // FIXME: We might wanna have a report here.
1253+
case 3: return execvpe("file", /*argv=*/ cleanArray, /*envp=*/taintedArray); // FIXME: We might wanna have a report here.
1254+
}
1255+
1256+
int cleanFD = coin();
1257+
int taintedFD;
1258+
scanf("%d", &taintedFD);
1259+
clang_analyzer_isTainted_int(taintedFD); // expected-warning {{YES}}
1260+
1261+
switch (coin()) {
1262+
default: break;
1263+
// Execute the file `FD` refers to, overlaying the running program image.
1264+
// `ARGV` and `ENVP` are passed to the new program, as for `execve'.
1265+
case 0: return fexecve( cleanFD, /*argv=*/ cleanArray, /*envp=*/ cleanArray); // no-warning
1266+
case 1: return fexecve(taintedFD, /*argv=*/ cleanArray, /*envp=*/ cleanArray); // expected-warning {{Untrusted data is passed to a system call}}
1267+
case 2: return fexecve( cleanFD, /*argv=*/taintedArray, /*envp=*/ cleanArray); // FIXME: We might wanna have a report here.
1268+
case 3: return fexecve( cleanFD, /*argv=*/ cleanArray, /*envp=*/taintedArray); // FIXME: We might wanna have a report here.
1269+
}
1270+
1271+
switch (coin()) {
1272+
default: break;
1273+
// Create a new stream connected to a pipe running the given `command`.
1274+
case 0: return pclose(popen("command", /*mode=*/"r")); // no-warning
1275+
case 1: return pclose(popen( buf, /*mode=*/"r")); // expected-warning {{Untrusted data is passed to a system call}}
1276+
case 2: return pclose(popen("command", /*mode=*/buf)); // 'mode' is not a taint sink.
1277+
}
1278+
1279+
switch (coin()) {
1280+
default: break;
1281+
// Execute the given line as a shell command.
1282+
case 0: return system("command"); // no-warning
1283+
case 1: return system( buf); // expected-warning {{Untrusted data is passed to a system call}}
1284+
}
1285+
1286+
return 0;
1287+
}
1288+
11321289
void testUnknownFunction(void (*foo)(void)) {
11331290
foo(); // no-crash
11341291
}

clang/test/CodeGenCoroutines/coro-gro.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ void doSomething() noexcept;
3030
int f() {
3131
// CHECK: %[[RetVal:.+]] = alloca i32
3232
// CHECK: %[[GroActive:.+]] = alloca i1
33+
// CHECK: %[[CoroGro:.+]] = alloca %struct.GroType, {{.*}} !coro.outside.frame ![[OutFrameMetadata:.+]]
3334

3435
// CHECK: %[[Size:.+]] = call i64 @llvm.coro.size.i64()
3536
// CHECK: call noalias noundef nonnull ptr @_Znwm(i64 noundef %[[Size]])
3637
// CHECK: store i1 false, ptr %[[GroActive]]
3738
// CHECK: call void @_ZNSt16coroutine_traitsIiJEE12promise_typeC1Ev(
38-
// CHECK: call void @_ZNSt16coroutine_traitsIiJEE12promise_type17get_return_objectEv(
39+
// CHECK: call void @_ZNSt16coroutine_traitsIiJEE12promise_type17get_return_objectEv({{.*}} %[[CoroGro]]
3940
// CHECK: store i1 true, ptr %[[GroActive]]
4041

4142
Cleanup cleanup;
@@ -104,3 +105,4 @@ invoker g() {
104105
// CHECK: call void @_ZN7invoker15invoker_promise17get_return_objectEv({{.*}} %[[AggRes]]
105106
co_return;
106107
}
108+
// CHECK: ![[OutFrameMetadata]] = !{}

compiler-rt/lib/hwasan/hwasan_report.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,13 @@ template <typename PrintTag>
342342
static void PrintTagInfoAroundAddr(uptr addr, uptr num_rows,
343343
InternalScopedString &s,
344344
PrintTag print_tag) {
345-
const uptr row_len = 16; // better be power of two.
346-
uptr center_row_beg = RoundDownTo(addr, row_len);
347-
uptr beg_row = center_row_beg - row_len * (num_rows / 2);
348-
uptr end_row = center_row_beg + row_len * ((num_rows + 1) / 2);
349-
for (uptr row = beg_row; row < end_row; row += row_len) {
345+
uptr center_row_beg = RoundDownTo(addr, kDumpWidth);
346+
uptr beg_row = center_row_beg - kDumpWidth * (num_rows / 2);
347+
uptr end_row = center_row_beg + kDumpWidth * ((num_rows + 1) / 2);
348+
for (uptr row = beg_row; row < end_row; row += kDumpWidth) {
350349
s.Append(row == center_row_beg ? "=>" : " ");
351350
s.AppendF("%p:", (void *)ShadowToMem(row));
352-
for (uptr i = 0; i < row_len; i++) {
351+
for (uptr i = 0; i < kDumpWidth; i++) {
353352
s.Append(row + i == addr ? "[" : " ");
354353
print_tag(s, row + i);
355354
s.Append(row + i == addr ? "]" : " ");

libc/include/llvm-libc-macros/linux/sys-stat-macros.h

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,40 @@
99
#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H
1010
#define __LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H
1111

12-
// File mode flags
13-
#define S_IRWXU 0700
14-
#define S_IRUSR 0400
15-
#define S_IWUSR 0200
16-
#define S_IXUSR 0100
17-
#define S_IRWXG 070
18-
#define S_IRGRP 040
19-
#define S_IWGRP 020
20-
#define S_IXGRP 010
21-
#define S_IRWXO 07
22-
#define S_IROTH 04
23-
#define S_IWOTH 02
24-
#define S_IXOTH 01
25-
#define S_ISUID 04000
26-
#define S_ISGID 02000
12+
// Definitions from linux/stat.h
13+
#define S_IFMT 00170000
14+
#define S_IFSOCK 0140000
15+
#define S_IFLNK 0120000
16+
#define S_IFREG 0100000
17+
#define S_IFBLK 0060000
18+
#define S_IFDIR 0040000
19+
#define S_IFCHR 0020000
20+
#define S_IFIFO 0010000
21+
#define S_ISUID 0004000
22+
#define S_ISGID 0002000
23+
#define S_ISVTX 0001000
24+
25+
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
26+
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
27+
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
28+
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
29+
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
30+
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
31+
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
32+
33+
#define S_IRWXU 00700
34+
#define S_IRUSR 00400
35+
#define S_IWUSR 00200
36+
#define S_IXUSR 00100
37+
38+
#define S_IRWXG 00070
39+
#define S_IRGRP 00040
40+
#define S_IWGRP 00020
41+
#define S_IXGRP 00010
42+
43+
#define S_IRWXO 00007
44+
#define S_IROTH 00004
45+
#define S_IWOTH 00002
46+
#define S_IXOTH 00001
2747

2848
#endif // __LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H

llvm/docs/Coroutines.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,25 @@ CoroCleanup
17751775
This pass runs late to lower all coroutine related intrinsics not replaced by
17761776
earlier passes.
17771777

1778+
Metadata
1779+
========
1780+
1781+
'``coro.outside.frame``' Metadata
1782+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1783+
1784+
``coro.outside.frame`` metadata may be attached to an alloca instruction to
1785+
to signify that it shouldn't be promoted to the coroutine frame, useful for
1786+
filtering allocas out by the frontend when emitting internal control mechanisms.
1787+
Additionally, this metadata is only used as a flag, so the associated
1788+
node must be empty.
1789+
1790+
.. code-block:: text
1791+
1792+
%__coro_gro = alloca %struct.GroType, align 1, !coro.outside.frame !0
1793+
1794+
...
1795+
!0 = !{}
1796+
17781797
Areas Requiring Attention
17791798
=========================
17801799
#. When coro.suspend returns -1, the coroutine is suspended, and it's possible

llvm/include/llvm/Config/llvm-config.h.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
/* Indicate that this is LLVM compiled from the amd-gfx branch. */
1818
#define LLVM_HAVE_BRANCH_AMD_GFX
19-
#define LLVM_MAIN_REVISION 475568
19+
#define LLVM_MAIN_REVISION 475573
2020

2121
/* Define if LLVM_ENABLE_DUMP is enabled */
2222
#cmakedefine LLVM_ENABLE_DUMP

llvm/include/llvm/IR/FixedMetadataKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ LLVM_FIXED_MD_KIND(MD_callsite, "callsite", 35)
5050
LLVM_FIXED_MD_KIND(MD_kcfi_type, "kcfi_type", 36)
5151
LLVM_FIXED_MD_KIND(MD_pcsections, "pcsections", 37)
5252
LLVM_FIXED_MD_KIND(MD_DIAssignID, "DIAssignID", 38)
53+
LLVM_FIXED_MD_KIND(MD_coro_outside_frame, "coro.outside.frame", 39)

0 commit comments

Comments
 (0)