Skip to content

Commit b5df8d7

Browse files
committed
required para use reference not pointer, ensure command isn null-terminated
1 parent af9294c commit b5df8d7

File tree

3 files changed

+34
-21
lines changed

3 files changed

+34
-21
lines changed

flang/include/flang/Runtime/execute.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extern "C" {
2121
// 16.9.83 EXECUTE_COMMAND_LINE
2222
// Execute a command line.
2323
// Returns a EXITSTAT, CMDSTAT, and CMDMSG as described in the standard.
24-
void RTNAME(ExecuteCommandLine)(const Descriptor *command = nullptr,
24+
void RTNAME(ExecuteCommandLine)(const Descriptor &command,
2525
bool wait = true, const Descriptor *exitstat = nullptr,
2626
const Descriptor *cmdstat = nullptr, const Descriptor *cmdmsg = nullptr,
2727
const char *sourceFile = nullptr, int line = 0);

flang/runtime/execute.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,11 @@ template <int KIND> struct FitsInIntegerKind {
100100

101101
// If a condition occurs that would assign a nonzero value to CMDSTAT but
102102
// the CMDSTAT variable is not present, error termination is initiated.
103-
int TerminationCheck(int status, const Descriptor *command,
104-
const Descriptor *cmdstat, const Descriptor *cmdmsg,
103+
int TerminationCheck(int status, const Descriptor *cmdstat, const Descriptor *cmdmsg,
105104
Terminator &terminator) {
106105
if (status == -1) {
107106
if (!cmdstat) {
108-
terminator.Crash("Execution error with system status code: %d",
109-
command->OffsetElement(), status);
107+
terminator.Crash("Execution error with system status code: %d", status);
110108
} else {
111109
CheckAndStoreIntToDescriptor(cmdstat, EXECL_ERR, terminator);
112110
CopyToDescriptor(*cmdmsg, "Execution error", 15);
@@ -151,14 +149,29 @@ int TerminationCheck(int status, const Descriptor *command,
151149
return exitStatusVal;
152150
}
153151

154-
void RTNAME(ExecuteCommandLine)(const Descriptor *command, bool wait,
152+
const char *ensureNullTerminated(
153+
const char *str, size_t length, Terminator &terminator) {
154+
if (length < strlen(str)) {
155+
char *newCmd{(char *)malloc(length + 1)};
156+
if (newCmd == NULL) {
157+
terminator.Crash("Command not null-terminated, memory allocation failed "
158+
"for null-terminated newCmd.");
159+
}
160+
161+
strncpy(newCmd, str, length);
162+
newCmd[length] = '\0';
163+
return newCmd;
164+
} else {
165+
return str;
166+
}
167+
}
168+
169+
void RTNAME(ExecuteCommandLine)(const Descriptor &command, bool wait,
155170
const Descriptor *exitstat, const Descriptor *cmdstat,
156171
const Descriptor *cmdmsg, const char *sourceFile, int line) {
157172
Terminator terminator{sourceFile, line};
158-
159-
if (command) {
160-
RUNTIME_CHECK(terminator, IsValidCharDescriptor(command));
161-
}
173+
const char *newCmd{ensureNullTerminated(
174+
command.OffsetElement(), command.ElementBytes(), terminator)};
162175

163176
if (exitstat) {
164177
RUNTIME_CHECK(terminator, IsValidIntDescriptor(exitstat));
@@ -177,9 +190,9 @@ void RTNAME(ExecuteCommandLine)(const Descriptor *command, bool wait,
177190

178191
if (wait) {
179192
// either wait is not specified or wait is true: synchronous mode
180-
int status{std::system(command->OffsetElement())};
193+
int status{std::system(newCmd)};
181194
int exitStatusVal{
182-
TerminationCheck(status, command, cmdstat, cmdmsg, terminator)};
195+
TerminationCheck(status, cmdstat, cmdmsg, terminator)};
183196
CheckAndStoreIntToDescriptor(exitstat, exitStatusVal, terminator);
184197
} else {
185198
// Asynchronous mode
@@ -235,8 +248,8 @@ void RTNAME(ExecuteCommandLine)(const Descriptor *command, bool wait,
235248
CheckAndCopyToDescriptor(cmdmsg, "Fork failed", 11);
236249
}
237250
} else if (pid == 0) {
238-
int status{std::system(command->OffsetElement())};
239-
TerminationCheck(status, command, cmdstat, cmdmsg, terminator);
251+
int status{std::system(newCmd)};
252+
TerminationCheck(status, cmdstat, cmdmsg, terminator);
240253
exit(status);
241254
}
242255
#endif

flang/unittests/Runtime/CommandTest.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ TEST_F(ZeroArguments, ECLValidCommandAndPadSync) {
247247
OwningPtr<Descriptor> cmdMsg{CharDescriptor("No change")};
248248

249249
RTNAME(ExecuteCommandLine)
250-
(command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
250+
(*command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
251251

252252
std::string spaces(cmdMsg->ElementBytes(), ' ');
253253
CheckDescriptorEqInt(exitStat.get(), 0);
@@ -263,7 +263,7 @@ TEST_F(ZeroArguments, ECLValidCommandStatusSetSync) {
263263
OwningPtr<Descriptor> cmdMsg{CharDescriptor("No change")};
264264

265265
RTNAME(ExecuteCommandLine)
266-
(command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
266+
(*command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
267267

268268
CheckDescriptorEqInt(exitStat.get(), 0);
269269
CheckDescriptorEqInt(cmdStat.get(), 0);
@@ -278,7 +278,7 @@ TEST_F(ZeroArguments, ECLInvalidCommandErrorSync) {
278278
OwningPtr<Descriptor> cmdMsg{CharDescriptor("Message ChangedXXXXXXXXX")};
279279

280280
RTNAME(ExecuteCommandLine)
281-
(command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
281+
(*command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
282282
#ifdef _WIN32
283283
CheckDescriptorEqInt(exitStat.get(), 1);
284284
#else
@@ -296,11 +296,11 @@ TEST_F(ZeroArguments, ECLInvalidCommandTerminatedSync) {
296296

297297
#ifdef _WIN32
298298
EXPECT_DEATH(RTNAME(ExecuteCommandLine)(
299-
command.get(), wait, exitStat.get(), nullptr, cmdMsg.get()),
299+
*command.get(), wait, exitStat.get(), nullptr, cmdMsg.get()),
300300
"Invalid command quit with exit status code: 1");
301301
#else
302302
EXPECT_DEATH(RTNAME(ExecuteCommandLine)(
303-
command.get(), wait, exitStat.get(), nullptr, cmdMsg.get()),
303+
*command.get(), wait, exitStat.get(), nullptr, cmdMsg.get()),
304304
"Invalid command quit with exit status code: 127");
305305
#endif
306306
CheckDescriptorEqInt(exitStat.get(), 404);
@@ -315,7 +315,7 @@ TEST_F(ZeroArguments, ECLValidCommandAndExitStatNoChangeAndCMDStatusSetAsync) {
315315
OwningPtr<Descriptor> cmdMsg{CharDescriptor("No change")};
316316

317317
RTNAME(ExecuteCommandLine)
318-
(command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
318+
(*command.get(), wait, exitStat.get(), cmdStat.get(), cmdMsg.get());
319319

320320
CheckDescriptorEqInt(exitStat.get(), 404);
321321
CheckDescriptorEqInt(cmdStat.get(), 0);
@@ -329,7 +329,7 @@ TEST_F(ZeroArguments, ECLInvalidCommandParentNotTerminatedAsync) {
329329
OwningPtr<Descriptor> cmdMsg{CharDescriptor("No change")};
330330

331331
EXPECT_NO_FATAL_FAILURE(RTNAME(ExecuteCommandLine)(
332-
command.get(), wait, exitStat.get(), nullptr, cmdMsg.get()));
332+
*command.get(), wait, exitStat.get(), nullptr, cmdMsg.get()));
333333

334334
CheckDescriptorEqInt(exitStat.get(), 404);
335335
CheckDescriptorEqStr(cmdMsg.get(), "No change");

0 commit comments

Comments
 (0)