From 6b445c0dc53f1c5778258bd673c0b61f6dd93a69 Mon Sep 17 00:00:00 2001 From: Vlad Khorsun Date: Fri, 20 Sep 2024 17:30:32 +0300 Subject: [PATCH] Catch possible stack overflow when preparing and compiling user statements --- src/dsql/dsql.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/dsql/dsql.cpp b/src/dsql/dsql.cpp index 18ad503847..a69b672fc3 100644 --- a/src/dsql/dsql.cpp +++ b/src/dsql/dsql.cpp @@ -43,6 +43,7 @@ #include "../common/intlobj_new.h" #include "../jrd/jrd.h" #include "../jrd/status.h" +#include "../jrd/ibsetjmp.h" #include "../common/CharSet.h" #include "../dsql/Parser.h" #include "../dsql/ddl_proto.h" @@ -85,6 +86,7 @@ using namespace Firebird; static ULONG get_request_info(thread_db*, DsqlRequest*, ULONG, UCHAR*); static dsql_dbb* init(Jrd::thread_db*, Jrd::Attachment*); static DsqlRequest* prepareRequest(thread_db*, dsql_dbb*, jrd_tra*, ULONG, const TEXT*, USHORT, unsigned, bool); +static DsqlRequest* safePrepareRequest(thread_db*, dsql_dbb*, jrd_tra*, ULONG, const TEXT*, USHORT, bool); static RefPtr prepareStatement(thread_db*, dsql_dbb*, jrd_tra*, ULONG, const TEXT*, USHORT, unsigned, bool, ntrace_result_t* traceResult); static UCHAR* put_item(UCHAR, const USHORT, const UCHAR*, UCHAR*, const UCHAR* const); @@ -260,7 +262,7 @@ DsqlRequest* DSQL_prepare(thread_db* tdbb, { // Allocate a new request block and then prepare the request. - dsqlRequest = prepareRequest(tdbb, database, transaction, length, string, dialect, + dsqlRequest = safePrepareRequest(tdbb, database, transaction, length, string, dialect, prepareFlags, isInternalRequest); // Can not prepare a CREATE DATABASE/SCHEMA statement @@ -335,7 +337,7 @@ void DSQL_execute_immediate(thread_db* tdbb, Jrd::Attachment* attachment, jrd_tr try { - dsqlRequest = prepareRequest(tdbb, database, *tra_handle, length, string, dialect, + dsqlRequest = safePrepareRequest(tdbb, database, *tra_handle, length, string, dialect, 0, isInternalRequest); const auto dsqlStatement = dsqlRequest->getDsqlStatement(); @@ -439,6 +441,23 @@ static dsql_dbb* init(thread_db* tdbb, Jrd::Attachment* attachment) return attachment->att_dsql_instance; } +// Use SEH frame when preparing user requests to catch possible stack overflows +static DsqlRequest* safePrepareRequest(thread_db* tdbb, dsql_dbb* database, jrd_tra* transaction, + ULONG textLength, const TEXT* text, USHORT clientDialect, bool isInternalRequest) +{ + if (isInternalRequest) + return prepareRequest(tdbb, database, transaction, textLength, text, clientDialect, true); + +#ifdef WIN_NT + START_CHECK_FOR_EXCEPTIONS(NULL); +#endif + return prepareRequest(tdbb, database, transaction, textLength, text, clientDialect, false); + +#ifdef WIN_NT + END_CHECK_FOR_EXCEPTIONS(NULL); +#endif +} + // Prepare a request for execution. // Note: caller is responsible for pool handling.