From 1f45bc73126833559ae588886203e091d4c3d700 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 3 Jan 2025 09:18:40 +0100 Subject: [PATCH] kernel: close streams after internal exception ... then rethrow. Otherwise we may end up with references to input/output stream objects on the stack that are invalid. --- src/streams.c | 124 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 39 deletions(-) diff --git a/src/streams.c b/src/streams.c index 23a0c18646..79c7f9168b 100644 --- a/src/streams.c +++ b/src/streams.c @@ -245,7 +245,17 @@ static Obj FuncREAD_COMMAND_REAL(Obj self, Obj stream, Obj echo) if (!OpenInputStream(&input, stream, echo == True)) { return result; } - ExecStatus status = ReadEvalCommand(0, &input, &evalResult, 0); + ExecStatus status; + + GAP_TRY + { + status = ReadEvalCommand(0, &input, &evalResult, 0); + } + GAP_CATCH + { + CloseInput(&input); + GAP_THROW(); + } CloseInput(&input); if (status == STATUS_EOF || status == STATUS_QQUIT) @@ -404,7 +414,11 @@ Int READ_GAP_ROOT ( const Char * filename ) } TypInputFile input; - if (OpenInput(&input, path)) { + if (!OpenInput(&input, path)) + return 0; + + GAP_TRY + { while (1) { ExecStatus status = ReadEvalCommand(0, &input, 0, 0); if (STATE(UserHasQuit) || STATE(UserHasQUIT)) @@ -416,11 +430,14 @@ Int READ_GAP_ROOT ( const Char * filename ) break; } } + } + GAP_CATCH + { CloseInput(&input); - return 1; + GAP_THROW(); } - - return 0; + CloseInput(&input); + return 1; } @@ -806,8 +823,17 @@ static Obj FuncREAD(Obj self, Obj inputObj) if (!OpenInputFileOrStream(SELF_NAME, &input, inputObj)) return False; - // read the file - READ_INNER(&input); + GAP_TRY + { + // read the file + READ_INNER(&input); + } + GAP_CATCH + { + CloseInput(&input); + GAP_THROW(); + } + if (!CloseInput(&input)) { ErrorQuit("Panic: READ cannot close input", 0, 0); } @@ -856,49 +882,58 @@ static Obj FuncREAD_STREAM_LOOP(Obj self, // get the starting time UInt oldPrintObjState = SetPrintObjState(0); - // now do the reading - while (1) { - Obj evalResult; - BOOL dualSemicolon; - UInt oldtime = SyTime(); - - // read and evaluate the command - SetPrintObjState(0); - ExecStatus status = - ReadEvalCommand(context, &input, &evalResult, &dualSemicolon); - - // stop the stopwatch - UpdateTime(oldtime); - - // handle ordinary command - if (status == STATUS_END && evalResult != 0) { - UpdateLast(evalResult); - if (!dualSemicolon) { - ViewObjHandler(evalResult); + BOOL rethrow = FALSE; + + GAP_TRY + { + // now do the reading + while (1) { + Obj evalResult; + BOOL dualSemicolon; + UInt oldtime = SyTime(); + + // read and evaluate the command + SetPrintObjState(0); + ExecStatus status = + ReadEvalCommand(context, &input, &evalResult, &dualSemicolon); + + // stop the stopwatch + UpdateTime(oldtime); + + // handle ordinary command + if (status == STATUS_END && evalResult != 0) { + UpdateLast(evalResult); + if (!dualSemicolon) { + ViewObjHandler(evalResult); + } } - } - // handle return-value or return-void command - else if (status == STATUS_RETURN) { - Pr("'return' must not be used in file read-eval loop\n", 0, 0); - } + // handle return-value or return-void command + else if (status == STATUS_RETURN) { + Pr("'return' must not be used in file read-eval loop\n", 0, 0); + } - // handle quit command or - else if (status == STATUS_EOF || status == STATUS_QUIT || - status == STATUS_QQUIT) { - break; + // handle quit command or + else if (status == STATUS_EOF || status == STATUS_QUIT || + status == STATUS_QQUIT) { + break; + } } } + GAP_CATCH + { + rethrow = TRUE; + } SetPrintObjState(oldPrintObjState); LockCurrentOutput(FALSE); res = CloseInput(&input); - GAP_ASSERT(res); - res &= CloseOutput(&output); - GAP_ASSERT(res); + + if (rethrow) + GAP_THROW(); return res ? True : False; } @@ -914,7 +949,18 @@ static Obj FuncREAD_AS_FUNC(Obj self, Obj inputObj) if (!OpenInputFileOrStream(SELF_NAME, &input, inputObj)) return False; - Obj func = READ_AS_FUNC(&input); + Obj func; + + GAP_TRY + { + func = READ_AS_FUNC(&input); + } + GAP_CATCH + { + CloseInput(&input); + GAP_THROW(); + } + if (!CloseInput(&input)) { ErrorQuit("Panic: READ_AS_FUNC cannot close input", 0, 0); }