diff --git a/src/gpre/cme.cpp b/src/gpre/cme.cpp index 467230c479..9efdaae534 100644 --- a/src/gpre/cme.cpp +++ b/src/gpre/cme.cpp @@ -25,7 +25,7 @@ // //____________________________________________________________ // -// $Id: cme.cpp,v 1.33 2004-08-27 04:50:00 robocop Exp $ +// $Id: cme.cpp,v 1.34 2005-01-17 05:02:08 robocop Exp $ // #include "firebird.h" @@ -1516,7 +1516,7 @@ static void cmp_literal( const gpre_nod* node, gpre_req* request) else { // Remove surrounding quotes from string, etc. - char buffer[MAXSYMLEN]; + char buffer[MAX_SYM_SIZE]; char* p = buffer; // Skip introducing quote mark @@ -1693,8 +1693,6 @@ static void cmp_plan(const gpre_nod* plan_expression, gpre_req* request) static void cmp_sdl_dtype( const gpre_fld* field, REF reference) { - TEXT s[50]; - switch (field->fld_dtype) { case dtype_cstring: @@ -1789,8 +1787,11 @@ static void cmp_sdl_dtype( const gpre_fld* field, REF reference) break; default: - sprintf(s, "datatype %d not understood", field->fld_dtype); - CPR_error(s); + { + TEXT s[50]; + sprintf(s, "datatype %d not understood", field->fld_dtype); + CPR_error(s); + } } } diff --git a/src/gpre/exp.cpp b/src/gpre/exp.cpp index 1cbbec0c58..e680b8e627 100644 --- a/src/gpre/exp.cpp +++ b/src/gpre/exp.cpp @@ -25,7 +25,7 @@ // //____________________________________________________________ // -// $Id: exp.cpp,v 1.36 2004-08-26 21:44:11 brodsom Exp $ +// $Id: exp.cpp,v 1.37 2005-01-17 05:02:08 robocop Exp $ // #include "firebird.h" @@ -272,10 +272,10 @@ gpre_fld* EXP_field(gpre_ctx** rcontext) if (!MSC_match(KW_DOT)) CPR_s_error("dot after context variable"); - TEXT s[128]; - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); gpre_fld* field = MET_field(relation, gpreGlob.token_global.tok_string); if (!field) { + TEXT s[ERROR_LENGTH]; sprintf(s, "field \"%s\" is not defined in relation %s", gpreGlob.token_global.tok_string, relation->rel_symbol->sym_string); PAR_error(s); @@ -325,6 +325,7 @@ GPRE_NOD EXP_literal(void) strcat(string, "\'"); MSC_copy(gpreGlob.token_global.tok_string, gpreGlob.token_global.tok_length, string + 1); strcat((string + gpreGlob.token_global.tok_length + 1), "\'"); + // What kind of hack is this? The token has not been enlarged nor modified. gpreGlob.token_global.tok_length += 2; } else { @@ -624,13 +625,11 @@ bool EXP_match_paren(void) //____________________________________________________________ // -// Parse and look up a qualfied relation name. +// Parse and look up a qualified relation name. // gpre_rel* EXP_relation(void) { - TEXT s[256]; - if (!gpreGlob.isc_databases) PAR_error("no database for operation"); @@ -641,14 +640,14 @@ gpre_rel* EXP_relation(void) gpre_rel* relation = NULL; - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); gpre_sym* symbol = MSC_find_symbol(gpreGlob.token_global.tok_symbol, SYM_database); if (symbol) { dbb* db = (DBB) symbol->sym_object; PAR_get_token(); if (!MSC_match(KW_DOT)) CPR_s_error("period after database name"); - SQL_resolve_identifier("", s); + SQL_resolve_identifier("
", NULL, NAME_SIZE); relation = MET_get_relation(db, gpreGlob.token_global.tok_string, ""); } else { @@ -658,6 +657,7 @@ gpre_rel* EXP_relation(void) if (!relation) relation = temp; else { + TEXT s[ERROR_LENGTH]; sprintf(s, "relation %s is ambiguous", gpreGlob.token_global.tok_string); PAR_get_token(); PAR_error(s); @@ -918,9 +918,7 @@ static bool check_relation(void) static GPRE_NOD lookup_field(gpre_ctx* context) { - char s[132]; - - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); gpre_fld* field = MET_field(context->ctx_relation, gpreGlob.token_global.tok_string); if (!field) return NULL; diff --git a/src/gpre/gpre.cpp b/src/gpre/gpre.cpp index bd13bfcac4..3b8589d39c 100644 --- a/src/gpre/gpre.cpp +++ b/src/gpre/gpre.cpp @@ -1173,7 +1173,7 @@ void CPR_get_text( TEXT* buffer, const gpre_txt* text) void CPR_raw_read() { - SCHAR token_string[MAXSYMLEN]; + SCHAR token_string[MAX_SYM_SIZE]; bool continue_char = false; SCHAR* p = token_string; diff --git a/src/gpre/gpre.h b/src/gpre/gpre.h index a26d6123d2..fc286252f5 100644 --- a/src/gpre/gpre.h +++ b/src/gpre/gpre.h @@ -90,12 +90,13 @@ static const char* const CONST_STR = "const "; static const char* const CONST_STR = ""; #endif -const int MAXSYMLEN = 512; // max length of symbol + terminator +const int MAX_SYM_SIZE = 512; // max length of symbol + terminator const int NAME_SIZE = 32; const int MAX_CURSOR_SIZE = 64; const int MAX_REF_SIZE = 32; // references are generated by gpre const int ERROR_LENGTH = 256; const int MAX_DATABASES = 32; +const int MAX_EVENT_SIZE = 16; // event names use 15 chars from old docs. // Values for SQL dialects. #include "../dsql/sqlda_pub.h" diff --git a/src/gpre/gpre_meta.epp b/src/gpre/gpre_meta.epp index f7833a80d6..74d9dbbcd4 100644 --- a/src/gpre/gpre_meta.epp +++ b/src/gpre/gpre_meta.epp @@ -59,6 +59,21 @@ static const UCHAR blr_bpb[] = { static const SCHAR db_version_info[] = { isc_info_base_level }; #endif +// CVC: I made this class as a quick solution for the many buffer overruns +// that would result in erratic behavior. +class MetIdentifier +{ + char name[NAME_SIZE]; +public: + MetIdentifier(const char* s) + { + strncpy(name, s, NAME_SIZE); + name[NAME_SIZE - 1] = 0; + } + operator char*() {return name;} +}; + + static SLONG array_size(gpre_fld*); static void get_array(dbb*, const TEXT*, gpre_fld*); static bool get_intl_char_subtype(SSHORT*, const UCHAR*, USHORT, dbb*); @@ -83,8 +98,7 @@ gpre_fld* MET_context_field( gpre_ctx* context, const char* string) return NULL; } - SCHAR name[NAME_SIZE]; - strcpy(name, string); + MetIdentifier name(string); gpre_prc* procedure = context->ctx_procedure; /* At this point the procedure should have been scanned, so all @@ -325,11 +339,9 @@ bool MET_database(dbb* database, bool print_version) bool MET_domain_lookup(gpre_req* request, gpre_fld* field, const char* string) { - SCHAR name[NAME_SIZE]; + MetIdentifier name(string); bool found = false; - strcpy(name, string); - /* Lookup domain. If we find it in the hash table, and it is not the * field we a currently looking at, use it. Else look it up from the * database. @@ -441,11 +453,6 @@ bool MET_get_domain_default(dbb* database, TEXT* buffer, USHORT buff_length) { - SCHAR name[NAME_SIZE]; - ISC_STATUS_ARRAY status_vect; - - strcpy(name, domain_name); - if (database == NULL) return false; @@ -453,8 +460,10 @@ bool MET_get_domain_default(dbb* database, CPR_exit(FINI_ERROR); fb_assert(database->dbb_transaction == 0); + MetIdentifier name(domain_name); gds_trans = 0; DB = database->dbb_handle; + ISC_STATUS_ARRAY status_vect; START_TRANSACTION; @@ -536,10 +545,7 @@ bool MET_get_column_default(const gpre_rel* relation, TEXT* buffer, USHORT buff_length) { - SCHAR name[NAME_SIZE]; - ISC_STATUS_ARRAY status_vect; - - strcpy(name, column_name); + MetIdentifier name(column_name); dbb* database = relation->rel_database; if (database == NULL) @@ -551,6 +557,7 @@ bool MET_get_column_default(const gpre_rel* relation, fb_assert(database->dbb_transaction == 0); gds_trans = 0; DB = database->dbb_handle; + ISC_STATUS_ARRAY status_vect; START_TRANSACTION; @@ -637,9 +644,7 @@ bool MET_get_column_default(const gpre_rel* relation, gpre_lls* MET_get_primary_key(dbb* database, const TEXT* relation_name) { - SCHAR name[NAME_SIZE]; - - strcpy(name, relation_name); + MetIdentifier name(relation_name); if (database == NULL) return NULL; @@ -692,9 +697,7 @@ gpre_lls* MET_get_primary_key(dbb* database, const TEXT* relation_name) gpre_fld* MET_field(gpre_rel* relation, const char* string) { - SCHAR name[NAME_SIZE]; - - strcpy(name, string); + MetIdentifier name(string); const SSHORT length = strlen(name); // Lookup field. If we find it, nifty. If not, look it up in the @@ -965,9 +968,7 @@ void MET_fini(dbb* end) const SCHAR* MET_generator(const TEXT* string, dbb* database) { - SCHAR name[NAME_SIZE]; - - strcpy(name, string); + MetIdentifier name(string); for (gpre_sym* symbol = HSH_lookup(name); symbol; symbol = symbol->sym_homonym) if ((symbol->sym_type == SYM_generator) && @@ -1079,10 +1080,8 @@ USHORT MET_get_dtype(USHORT blr_dtype, USHORT sub_type, USHORT* length) gpre_prc* MET_get_procedure(dbb* database, const TEXT* string, const TEXT* owner_name) { - SCHAR name[NAME_SIZE], owner[NAME_SIZE]; + MetIdentifier name(string), owner(owner_name); - strcpy(name, string); - strcpy(owner, owner_name); gpre_prc* procedure = NULL; for (gpre_sym* symbol = HSH_lookup(name); symbol; symbol = symbol->sym_homonym) @@ -1195,10 +1194,7 @@ gpre_prc* MET_get_procedure(dbb* database, const TEXT* string, const TEXT* owner gpre_rel* MET_get_relation(dbb* database, const TEXT* string, const TEXT* owner_name) { gpre_rel* relation; - SCHAR name[NAME_SIZE], owner[NAME_SIZE]; - - strcpy(name, string); - strcpy(owner, owner_name); + MetIdentifier name(string), owner(owner_name); for (gpre_sym* symbol = HSH_lookup(name); symbol; symbol = symbol->sym_homonym) if (symbol->sym_type == SYM_relation && @@ -1239,9 +1235,8 @@ INTLSYM MET_get_text_subtype(SSHORT ttype) udf* MET_get_udf(dbb* database, const TEXT* string) { - SCHAR name[NAME_SIZE]; - - strcpy(name, string); + MetIdentifier name(string); + udf* the_udf = NULL; for (gpre_sym* symbol = HSH_lookup(name); symbol; symbol = symbol->sym_homonym) if (symbol->sym_type == SYM_udf && @@ -1390,9 +1385,7 @@ gpre_rel* MET_get_view_relation(gpre_req* request, IND MET_index(dbb* database, const TEXT* string) { IND index; - SCHAR name[NAME_SIZE]; - - strcpy(name, string); + MetIdentifier name(string); const USHORT length = strlen(name); gpre_sym* symbol; @@ -1899,9 +1892,7 @@ bool MET_type(gpre_fld* field, bool MET_trigger_exists(dbb* database, const TEXT* trigger_name) { - char name[NAME_SIZE]; - - strcpy(name, trigger_name); + MetIdentifier name(trigger_name); DB = database->dbb_handle; gds_trans = database->dbb_transaction; diff --git a/src/gpre/par.cpp b/src/gpre/par.cpp index 622bf5d02f..b6fb776582 100644 --- a/src/gpre/par.cpp +++ b/src/gpre/par.cpp @@ -672,12 +672,13 @@ void PAR_error(const TEXT* string) act* PAR_event_init(bool sql) { - char req_name[128]; +// char req_name[128]; // make up statement node - SQL_resolve_identifier("", req_name); - strcpy(gpreGlob.token_global.tok_string, req_name); + SQL_resolve_identifier("", NULL, MAX_EVENT_SIZE); + //SQL_resolve_identifier("", req_name, sizeof(req_name)); + //strcpy(gpreGlob.token_global.tok_string, req_name); Why? It's already done. gpre_nod* init = MSC_node(nod_event_init, 4); init->nod_arg[0] = (GPRE_NOD) PAR_symbol(SYM_dummy); init->nod_arg[3] = (GPRE_NOD) gpreGlob.isc_databases; @@ -756,13 +757,14 @@ act* PAR_event_init(bool sql) act* PAR_event_wait(bool sql) { - char req_name[132]; +// char req_name[132]; // this is a simple statement, just add a handle act* action = MSC_action(0, ACT_event_wait); - SQL_resolve_identifier("", req_name); - strcpy(gpreGlob.token_global.tok_string, req_name); + SQL_resolve_identifier("", NULL, MAX_EVENT_SIZE); + //SQL_resolve_identifier("", req_name, sizeof(req_name)); + //strcpy(gpreGlob.token_global.tok_string, req_name); redundant action->act_object = (REF) PAR_symbol(SYM_dummy); if (!sql) PAR_end(); @@ -960,7 +962,7 @@ TEXT* PAR_native_value(bool array_ref, } int length = string - buffer; - SCHAR* s2 = string = (SCHAR *) MSC_alloc(length + 1); + SCHAR* const s2 = string = (SCHAR *) MSC_alloc(length + 1); const SCHAR* s1 = buffer; if (length) { @@ -1307,7 +1309,6 @@ static act* par_at() static act* par_based() { - TEXT t_str[NAME_SIZE + 1]; bool notSegment = false; // a COBOL specific patch MSC_match(KW_ON); @@ -1321,7 +1322,7 @@ static act* par_based() gpre_rel* relation = EXP_relation(); if (!MSC_match(KW_DOT)) CPR_s_error("dot in qualified field reference"); - SQL_resolve_identifier("", t_str); + SQL_resolve_identifier("", NULL, NAME_SIZE + 1); gpre_fld* field = MET_field(relation, gpreGlob.token_global.tok_string); if (!field) { fb_utils::snprintf(s, sizeof(s), @@ -1609,8 +1610,7 @@ static act* par_derived_from() if (!MSC_match(KW_DOT)) CPR_s_error("dot in qualified field reference"); - TEXT dummy[64]; - SQL_resolve_identifier("", dummy); + SQL_resolve_identifier("", NULL, NAME_SIZE); gpre_fld* field = MET_field(relation, gpreGlob.token_global.tok_string); if (!field) { @@ -3004,8 +3004,7 @@ static act* par_type() // Look for field name. No field name, punt - TEXT dummy[64]; - SQL_resolve_identifier("", dummy); + SQL_resolve_identifier("", NULL, NAME_SIZE); gpre_fld* field = MET_field(relation, gpreGlob.token_global.tok_string); if (!field) return NULL; @@ -3040,9 +3039,7 @@ static act* par_type() static act* par_variable() { - bool is_null = false; - -// +// // Since fortran is fussy about continuations and the like, // see if this variable token is the first thing in a statement. // @@ -3058,6 +3055,7 @@ static act* par_variable() dot = MSC_match(KW_DOT); } + bool is_null = false; if (dot && MSC_match(KW_NULL)) { is_null = true; dot = false; diff --git a/src/gpre/parse.h b/src/gpre/parse.h index 686aaeec32..e4ff5abc2a 100644 --- a/src/gpre/parse.h +++ b/src/gpre/parse.h @@ -45,7 +45,7 @@ typedef struct tok { SLONG tok_position; /* byte number in input stream */ USHORT tok_length; USHORT tok_white_space; - SCHAR tok_string[MAXSYMLEN]; + SCHAR tok_string[MAX_SYM_SIZE]; USHORT tok_first; /* first token in a statement */ gpre_sym* tok_charset; /* Character set of token */ } *TOK; diff --git a/src/gpre/sqe.cpp b/src/gpre/sqe.cpp index fbb1602469..55a1dc6cc4 100644 --- a/src/gpre/sqe.cpp +++ b/src/gpre/sqe.cpp @@ -327,7 +327,6 @@ GPRE_NOD SQE_field(gpre_req* request, { GPRE_NOD node; gpre_req* slice_req; - TEXT s[ERROR_LENGTH]; assert_IS_REQ(request); @@ -343,11 +342,13 @@ GPRE_NOD SQE_field(gpre_req* request, // if the token isn't an identifier, complain - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); // For domains we can't be resolving tokens to field names // in the CHECK constraint. + TEXT s[ERROR_LENGTH]; + act* action; if (request && request->req_type == REQ_ddl && @@ -382,7 +383,7 @@ GPRE_NOD SQE_field(gpre_req* request, TOK f_token = (TOK) MSC_alloc(TOK_LEN); node->nod_arg[0] = (GPRE_NOD) f_token; f_token->tok_length = gpreGlob.token_global.tok_length; - SQL_resolve_identifier("", f_token->tok_string); + SQL_resolve_identifier("", f_token->tok_string, f_token->tok_length + 1); CPR_token(); if (MSC_match(KW_DOT)) { @@ -397,7 +398,7 @@ GPRE_NOD SQE_field(gpre_req* request, f_token = (TOK) MSC_alloc(TOK_LEN); node->nod_arg[0] = (GPRE_NOD) f_token; f_token->tok_length = gpreGlob.token_global.tok_length; - SQL_resolve_identifier("", f_token->tok_string); + SQL_resolve_identifier("", f_token->tok_string, f_token->tok_length + 1); } CPR_token(); } @@ -491,7 +492,7 @@ GPRE_NOD SQE_field(gpre_req* request, CPR_s_error(" in qualified column"); if (context->ctx_request != request) PAR_error("context not part of this request"); - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); if (! (reference->ref_field = MET_context_field(context, gpreGlob.token_global.tok_string))) @@ -535,7 +536,7 @@ GPRE_NOD SQE_field(gpre_req* request, } else { /** We've got the column name. resolve it **/ - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); for (context = request->req_contexts; context; context = context->ctx_next) { @@ -578,7 +579,7 @@ GPRE_NOD SQE_field(gpre_req* request, CPR_token(); if (!MSC_match(KW_DOT)) CPR_s_error(" in qualified column"); - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); for (context = request->req_contexts; context; context = context->ctx_next) { @@ -616,7 +617,7 @@ GPRE_NOD SQE_field(gpre_req* request, // Hmmm. So it wasn't a qualified field. Try any field. - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); for (context = request->req_contexts; context; context = context->ctx_next) { @@ -2958,10 +2959,6 @@ static void par_terminating_parens( static GPRE_NOD par_udf( gpre_req* request) { - GPRE_NOD node; - USHORT local_count; - SCHAR s[ERROR_LENGTH]; - if (!request) return NULL; @@ -2970,8 +2967,11 @@ static GPRE_NOD par_udf( gpre_req* request) // Check for user defined functions // ** resolve only if an identifier * if ((isQuoted(gpreGlob.token_global.tok_type)) || gpreGlob.token_global.tok_type == tok_ident) - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", NULL, NAME_SIZE); + GPRE_NOD node; + USHORT local_count; + udf* an_udf; if (request->req_database) an_udf = MET_get_udf(request->req_database, gpreGlob.token_global.tok_string); @@ -2986,6 +2986,7 @@ static GPRE_NOD par_udf( gpre_req* request) if (tmp_udf) if (an_udf) { // udf was found in more than one database + SCHAR s[ERROR_LENGTH]; sprintf(s, "UDF %s is ambiguous", gpreGlob.token_global.tok_string); PAR_error(s); } @@ -3044,7 +3045,7 @@ static GPRE_NOD par_udf( gpre_req* request) node = MSC_node(nod_gen_id, 2); node->nod_count = 1; EXP_left_paren(0); - SQL_resolve_identifier("", gen_name); + SQL_resolve_identifier("", gen_name, NAME_SIZE); node->nod_arg[1] = (GPRE_NOD) gen_name; PAR_get_token(); if (!MSC_match(KW_COMMA)) diff --git a/src/gpre/sql.cpp b/src/gpre/sql.cpp index ccc9a80d64..1f46685001 100644 --- a/src/gpre/sql.cpp +++ b/src/gpre/sql.cpp @@ -135,7 +135,7 @@ static bool par_transaction_modes(gpre_tra*, bool); static bool par_using(DYN); static USHORT resolve_dtypes(KWWORDS, bool); static bool tail_database(enum act_t, DBB); -static void to_upcase(const TEXT *, TEXT *); +static void to_upcase(const TEXT*, TEXT*, int); static swe* global_whenever[SWE_max]; static swe* global_whenever_list; @@ -579,8 +579,8 @@ void SQL_par_field_dtype(gpre_req* request, CPR_s_error(""); } else { - char s[ERROR_LENGTH]; - SQL_resolve_identifier("", s); + char s[NAME_SIZE]; + SQL_resolve_identifier("", s, NAME_SIZE); gpre_sym* symbol = MSC_symbol(SYM_field, s, (USHORT) strlen(s), (gpre_ctx*) field); field->fld_global = symbol; @@ -970,19 +970,20 @@ void SQL_relation_name(TEXT* r_name, db_name[0] = 0; owner_name[0] = 0; - TEXT t_str[NAME_SIZE + 1]; - SQL_resolve_identifier("
", t_str); + SQL_resolve_identifier("", NULL, NAME_SIZE); gpre_sym* symbol = MSC_find_symbol(gpreGlob.token_global.tok_symbol, SYM_database); if (symbol) { - strcpy(db_name, symbol->sym_name); + if (strlen(symbol->sym_name) >= NAME_SIZE) + PAR_error("Database alias too long"); + strcpy(db_name, symbol->sym_name); // this is the alias, not the path PAR_get_token(); if (!MSC_match(KW_DOT)) CPR_s_error(". (period)"); } - SQL_resolve_identifier("
", t_str); - if (gpreGlob.token_global.tok_length > NAME_SIZE) + SQL_resolve_identifier("
", NULL, NAME_SIZE + 1); + if (gpreGlob.token_global.tok_length >= NAME_SIZE) PAR_error("Table, owner, or database name too long"); strcpy(r_name, gpreGlob.token_global.tok_string); @@ -991,10 +992,10 @@ void SQL_relation_name(TEXT* r_name, if (MSC_match(KW_DOT)) { // the table name was really a owner specifier - if (gpreGlob.token_global.tok_length > NAME_SIZE) + if (gpreGlob.token_global.tok_length >= NAME_SIZE) PAR_error("TABLE name too long"); strcpy(owner_name, r_name); - SQL_resolve_identifier("
", t_str); + SQL_resolve_identifier("
", NULL, NAME_SIZE); strcpy(r_name, gpreGlob.token_global.tok_string); PAR_get_token(); } @@ -1273,8 +1274,8 @@ static act* act_alter_index(void) if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("Index name too long"); - SCHAR i_name[NAME_SIZE + 1]; - SQL_resolve_identifier("", i_name); + char i_name[NAME_SIZE]; + SQL_resolve_identifier("", i_name, NAME_SIZE); PAR_get_token(); @@ -1362,8 +1363,8 @@ static act* act_alter_table(void) cnstrt_str->cnstrt_flags |= CNSTRT_delete; cnstrt_str->cnstrt_name = (STR) MSC_alloc(NAME_SIZE + 1); SQL_resolve_identifier("", - cnstrt_str->cnstrt_name->str_string); - if (gpreGlob.token_global.tok_length > NAME_SIZE) + cnstrt_str->cnstrt_name->str_string, NAME_SIZE + 1); + if (gpreGlob.token_global.tok_length >= NAME_SIZE) PAR_error("Constraint name too long"); *cnstrt_ptr = cnstrt_str; cnstrt_ptr = &cnstrt_str->cnstrt_next; @@ -1804,7 +1805,7 @@ static act* act_create_domain(void) static act* act_create_generator(void) { TEXT* generator_name = (TEXT*) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", generator_name); + SQL_resolve_identifier("", generator_name, NAME_SIZE + 1); gpre_req* request = MSC_request(REQ_ddl); if (gpreGlob.isc_databases && !gpreGlob.isc_databases->dbb_next) @@ -1812,7 +1813,7 @@ static act* act_create_generator(void) else PAR_error("Can only CREATE GENERATOR in context of single database"); - if (gpreGlob.token_global.tok_length > NAME_SIZE) + if (gpreGlob.token_global.tok_length >= NAME_SIZE) PAR_error("Generator name too long"); @@ -1844,7 +1845,7 @@ static act* act_create_index(bool dups, PAR_error("Index name too long"); SCHAR i_name[NAME_SIZE + 1]; - SQL_resolve_identifier("", i_name); + SQL_resolve_identifier("", i_name, NAME_SIZE + 1); PAR_get_token(); @@ -2187,12 +2188,9 @@ static act* act_declare(void) } bool delimited = false; -#ifdef SCROLLABLE_CURSORS - bool scroll = false; -#endif - TEXT t_str[132]; // CVC: is it always enough? - SQL_resolve_identifier("", t_str); + TEXT t_str[MAX_CURSOR_SIZE]; + SQL_resolve_identifier("", t_str, MAX_CURSOR_SIZE); if (gpreGlob.token_global.tok_type == tok_dblquoted) delimited = true; else { @@ -2207,6 +2205,9 @@ static act* act_declare(void) } } +#ifdef SCROLLABLE_CURSORS + bool scroll = false; +#endif act* action = NULL; gpre_sym* symbol = PAR_symbol(SYM_cursor); @@ -2314,7 +2315,7 @@ static act* act_declare_filter(void) PAR_get_token(); FLTR filter = (FLTR) MSC_alloc(FLTR_LEN); filter->fltr_name = (TEXT*) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", filter->fltr_name); + SQL_resolve_identifier("", filter->fltr_name, NAME_SIZE + 1); if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("Filter name too long"); @@ -2462,7 +2463,7 @@ static act* act_declare_udf(void) decl_udf* udf_declaration = (decl_udf*) MSC_alloc(DECL_UDF_LEN); TEXT* udf_name = (TEXT*) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", udf_name); + SQL_resolve_identifier("", udf_name, NAME_SIZE + 1); udf_declaration->decl_udf_name = udf_name; if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("external function name too long"); @@ -2769,7 +2770,7 @@ static act* act_drop(void) PAR_error("Can only DROP DOMAIN in context of single database"); PAR_get_token(); identifier_name = (TEXT*) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", identifier_name); + SQL_resolve_identifier("", identifier_name, NAME_SIZE + 1); action = MSC_action(request, ACT_drop_domain); action->act_whenever = gen_whenever(); action->act_object = (REF) identifier_name; @@ -2784,7 +2785,7 @@ static act* act_drop(void) PAR_error("Can only DROP FILTER in context of single database"); PAR_get_token(); identifier_name = (TEXT*) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", identifier_name); + SQL_resolve_identifier("", identifier_name, NAME_SIZE + 1); action = MSC_action(request, ACT_drop_filter); action->act_whenever = gen_whenever(); action->act_object = (REF) identifier_name; @@ -2804,7 +2805,7 @@ static act* act_drop(void) ("Can only DROP EXTERNAL FUNCTION in context of a single database"); identifier_name = (TEXT*) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", identifier_name); + SQL_resolve_identifier("", identifier_name, NAME_SIZE + 1); action = MSC_action(request, ACT_drop_udf); action->act_whenever = gen_whenever(); action->act_object = (REF) identifier_name; @@ -2815,11 +2816,7 @@ static act* act_drop(void) { request = MSC_request(REQ_ddl); PAR_get_token(); - TEXT identifier_name_tmp[NAME_SIZE + 1]; // unused - SQL_resolve_identifier("", identifier_name_tmp); - // CVC: Why this line isn't like the commented one that matches other - // places before make_index()? - //IND index = make_index(request, identifier_name_tmp); + SQL_resolve_identifier("", NULL, NAME_SIZE + 1); IND index = make_index(request, gpreGlob.token_global.tok_string); action = MSC_action(request, ACT_drop_index); action->act_whenever = gen_whenever(); @@ -3171,7 +3168,7 @@ static act* act_grant_revoke( enum act_t type) if (MSC_match(KW_LEFT_PAREN)) { SCHAR col_name[NAME_SIZE + 1]; do { - SQL_resolve_identifier("", col_name); + SQL_resolve_identifier("", col_name, NAME_SIZE + 1); STR field_name = (STR) MSC_string(col_name); MSC_push((GPRE_NOD) field_name, fields); fields = &(*fields)->lls_next; @@ -3266,7 +3263,7 @@ static act* act_grant_revoke( enum act_t type) if (gpreGlob.token_global.tok_type != tok_ident) CPR_s_error(""); else - to_upcase(gpreGlob.token_global.tok_string, r_name); + to_upcase(gpreGlob.token_global.tok_string, r_name, sizeof(r_name)); user_dyn = isc_dyn_grant_user; CPR_token(); } @@ -3684,7 +3681,8 @@ static act* act_open_blob( ACT_T act_op, gpre_sym* symbol) TOK f_token = (TOK) MSC_alloc(TOK_LEN); f_token->tok_length = gpreGlob.token_global.tok_length; - SQL_resolve_identifier("", f_token->tok_string); + // Funny, as if we can have relation names up to MAX_SYM_SIZE. + SQL_resolve_identifier("", f_token->tok_string, f_token->tok_length + 1); CPR_token(); if (act_op == ACT_blob_open) { @@ -4096,8 +4094,8 @@ static act* act_set_generator(void) PAR_error("Generator name too long"); SGEN setgen = (SGEN) MSC_alloc(SGEN_LEN); - setgen->sgen_name = (TEXT*) MSC_alloc(gpreGlob.token_global.tok_length + 1); - SQL_resolve_identifier("", setgen->sgen_name); + setgen->sgen_name = (TEXT*) MSC_alloc(NAME_SIZE + 1); + SQL_resolve_identifier("", setgen->sgen_name, NAME_SIZE + 1); if (!MET_generator(setgen->sgen_name, request->req_database)) { SCHAR s[ERROR_LENGTH]; fb_utils::snprintf(s, sizeof(s), @@ -4218,7 +4216,7 @@ static act* act_set_statistics(void) if (MSC_match(KW_INDEX)) { stats->sts_flags = STS_index; stats->sts_name = (STR) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", stats->sts_name->str_string); + SQL_resolve_identifier("", stats->sts_name->str_string, NAME_SIZE + 1); if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("Index name too long"); PAR_get_token(); @@ -4733,11 +4731,11 @@ static void connect_opts( else if (MSC_match(KW_ROLE)) { if (gpreGlob.token_global.tok_type == tok_ident) { // reserve extra bytes for quotes and NULL - TEXT* s = (TEXT*) MSC_alloc(gpreGlob.token_global.tok_length + 3); + //TEXT* s = (TEXT*) MSC_alloc(gpreGlob.token_global.tok_length + 3); + TEXT* s = (TEXT*) MSC_alloc(NAME_SIZE + 2); - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", s + 1, NAME_SIZE); s[0] = '\"'; - strcpy(s + 1, gpreGlob.token_global.tok_string); strcat(s, "\""); *sql_role = s; } @@ -5037,9 +5035,9 @@ static void into( gpre_req* request, GPRE_NOD field_list, GPRE_NOD var_list) static gpre_fld* make_field( gpre_rel* relation) { - char s[ERROR_LENGTH]; + char s[NAME_SIZE]; - SQL_resolve_identifier("", s); + SQL_resolve_identifier("", s, NAME_SIZE); gpre_fld* field = MET_make_field(s, 0, 0, true); field->fld_relation = relation; field->fld_flags |= FLD_meta; @@ -5293,7 +5291,7 @@ static gpre_req* par_cursor( gpre_sym** symbol_ptr) // par_cursor() is called to use a previously declared cursor. // tok_symbol == NULL means one of the two things. // a) The name does not belong to a cursor. OR -// b) get_token() function in gpre.c was not able to find the cursor +// b) get_token() function in gpre.cpp was not able to find the cursor // in hash table. // // case a) is an error condition. @@ -5305,8 +5303,7 @@ static gpre_req* par_cursor( gpre_sym** symbol_ptr) // it still cannot be located, Its an error //* - TEXT t_cur[128]; - SQL_resolve_identifier("", t_cur); + SQL_resolve_identifier("", NULL, MAX_CURSOR_SIZE); gpre_sym* symbol = HSH_lookup(gpreGlob.token_global.tok_string); gpreGlob.token_global.tok_symbol = symbol; if (symbol && symbol->sym_type == SYM_keyword) @@ -5343,8 +5340,7 @@ static DYN par_dynamic_cursor(void) gpre_sym* symbol = NULL; if (gpreGlob.token_global.tok_symbol == NULL) { - TEXT t_cur[128]; - SQL_resolve_identifier("", t_cur); + SQL_resolve_identifier("", NULL, MAX_CURSOR_SIZE); gpreGlob.token_global.tok_symbol = symbol = HSH_lookup(gpreGlob.token_global.tok_string); if (symbol && symbol->sym_type == SYM_keyword) gpreGlob.token_global.tok_keyword = (KWWORDS) symbol->sym_keyword; @@ -5475,7 +5471,7 @@ static CNSTRT par_field_constraint( gpre_req* request, gpre_fld* for_field, PAR_get_token(); new_constraint->cnstrt_name = (STR) MSC_alloc(NAME_SIZE + 1); SQL_resolve_identifier("", - new_constraint->cnstrt_name->str_string); + new_constraint->cnstrt_name->str_string, NAME_SIZE + 1); if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("Constraint name too long"); PAR_get_token(); @@ -5518,7 +5514,8 @@ static CNSTRT par_field_constraint( gpre_req* request, gpre_fld* for_field, new_constraint->cnstrt_referred_rel = (STR) MSC_alloc(NAME_SIZE + 1); SQL_resolve_identifier("referred
", - new_constraint->cnstrt_referred_rel->str_string); + new_constraint->cnstrt_referred_rel->str_string, + NAME_SIZE + 1); if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("Referred table name too long"); PAR_get_token(); @@ -5527,7 +5524,7 @@ static CNSTRT par_field_constraint( gpre_req* request, gpre_fld* for_field, // Field specified for referred relation field_name = (STR) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", field_name->str_string); + SQL_resolve_identifier("", field_name->str_string, NAME_SIZE + 1); MSC_push((GPRE_NOD) field_name, &new_constraint->cnstrt_referred_fields); CPR_token(); EXP_match_paren(); @@ -5765,7 +5762,7 @@ static CNSTRT par_table_constraint( gpre_req* request, gpre_rel* relation) PAR_get_token(); constraint->cnstrt_name = (STR) MSC_alloc(NAME_SIZE + 1); SQL_resolve_identifier("", - constraint->cnstrt_name->str_string); + constraint->cnstrt_name->str_string, NAME_SIZE + 1); if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("Constraint name too long"); PAR_get_token(); @@ -5801,7 +5798,7 @@ static CNSTRT par_table_constraint( gpre_req* request, gpre_rel* relation) fields = &constraint->cnstrt_fields; do { STR field_name = (STR) MSC_alloc(NAME_SIZE + 1); - SQL_resolve_identifier("", field_name->str_string); + SQL_resolve_identifier("", field_name->str_string, NAME_SIZE + 1); MSC_push((GPRE_NOD) field_name, fields); fields = &(*fields)->lls_next; ++num_for_key_flds; @@ -5820,7 +5817,8 @@ static CNSTRT par_table_constraint( gpre_req* request, gpre_rel* relation) constraint->cnstrt_referred_rel = (STR) MSC_alloc(NAME_SIZE + 1); SQL_resolve_identifier("referred
", - constraint->cnstrt_referred_rel->str_string); + constraint->cnstrt_referred_rel->str_string, + NAME_SIZE + 1); if (gpreGlob.token_global.tok_length > NAME_SIZE) PAR_error("Referred table name too long"); PAR_get_token(); @@ -5834,7 +5832,7 @@ static CNSTRT par_table_constraint( gpre_req* request, gpre_rel* relation) do { STR field_name = (STR) MSC_alloc(NAME_SIZE + 1); SQL_resolve_identifier("", - field_name->str_string); + field_name->str_string, NAME_SIZE + 1); MSC_push((GPRE_NOD) field_name, fields); fields = &(*fields)->lls_next; ++num_prim_key_flds; @@ -6067,6 +6065,7 @@ static bool tail_database(enum act_t action_type, (TEXT*) MSC_alloc(gpreGlob.token_global.tok_length + 1); MSC_copy(gpreGlob.token_global.tok_string, gpreGlob.token_global.tok_length, string); + // - 2 here ??? string[gpreGlob.token_global.tok_length - 2] = '\0'; PAR_get_token(); } @@ -6234,12 +6233,12 @@ static bool tail_database(enum act_t action_type, // Upcase a string into another string. // -static void to_upcase(const TEXT * p, TEXT * q) +static void to_upcase(const TEXT* p, TEXT* q, int target_size) { UCHAR c; USHORT l = 0; - while ((c = *p++) && (++l <= NAME_SIZE)) { + while ((c = *p++) && (++l < target_size)) { *q++ = UPPER(c); } *q = 0; @@ -6249,11 +6248,34 @@ static void to_upcase(const TEXT * p, TEXT * q) //____________________________________________________________ // // To do: move these to the correct position in the file. +// Idea: if we don't need a result in a variable, we don't pass it, since the +// internal buffer will be used instead (in that case, bigger size cannot surpass +// the size of a cursor). We can provide a size smaller than MAX_CURSOR size +// with the internal buffer. We should provide the correct size if we provide +// the output variable to put the result in it. -void SQL_resolve_identifier( const TEXT* err_mesg, TEXT* str) +void SQL_resolve_identifier( const TEXT* err_mesg, TEXT* str_in, int in_size) { - // Ripe for B.O. - // Beware to_upcase() works only in the first 32 bytes. + static TEXT internal_buffer[MAX_CURSOR_SIZE]; + TEXT* str; + int len; + if (str_in) + { + str = str_in; + len = in_size - 1; + } + else + { + str = internal_buffer; + len = sizeof(internal_buffer) - 1; + if (in_size > 0 && in_size <= len) + len = in_size - 1; + else if (in_size > len + 1) + PAR_error("Provide your own buffer for sizes bigger than 64."); + } + + TEXT* const tk_string = gpreGlob.token_global.tok_string; + switch (gpreGlob.sw_sql_dialect) { case 2: if (gpreGlob.token_global.tok_type == tok_dblquoted) @@ -6262,21 +6284,24 @@ void SQL_resolve_identifier( const TEXT* err_mesg, TEXT* str) if (gpreGlob.token_global.tok_type != tok_ident) CPR_s_error(err_mesg); else - to_upcase(gpreGlob.token_global.tok_string, str); + to_upcase(tk_string, str, len + 1); break; case 3: if (gpreGlob.token_global.tok_type == tok_dblquoted) { - if (gpreGlob.token_global.tok_string[0] == '\"') + // strip_quotes is too dumb to handle C escape sequences + // or SQL escape sequences in quoted identifiers. + if (tk_string[0] == '\"') strip_quotes(gpreGlob.token_global); - strcpy(str, gpreGlob.token_global.tok_string); + strncpy(str, tk_string, len); + str[len] = 0; } else if (gpreGlob.token_global.tok_type == tok_ident) - to_upcase(gpreGlob.token_global.tok_string, str); + to_upcase(tk_string, str, len + 1); else CPR_s_error(err_mesg); break; } - strcpy(gpreGlob.token_global.tok_string, str); + strcpy(tk_string, str); } diff --git a/src/gpre/sql_proto.h b/src/gpre/sql_proto.h index 9b5c177747..a351de1c36 100644 --- a/src/gpre/sql_proto.h +++ b/src/gpre/sql_proto.h @@ -33,7 +33,7 @@ void SQL_par_field_dtype(gpre_req*, gpre_fld*, bool); gpre_prc* SQL_procedure(gpre_req*, const TEXT*, const TEXT*, const TEXT*, bool); gpre_rel* SQL_relation(gpre_req*, const TEXT*, const TEXT*, const TEXT*, bool); void SQL_relation_name(TEXT*, TEXT*, TEXT*); -void SQL_resolve_identifier(const TEXT*, TEXT*); +void SQL_resolve_identifier(const TEXT*, TEXT*, int in_size); TEXT* SQL_var_or_string(bool); #endif // GPRE_SQL_PROTO_H