Skip to content

Commit 92a83aa

Browse files
authored
Restrict identifier lengths to 128 characters and local temp tables to 116 characters (#4832)
Restrict identifier lengths to 128 characters and local temp tables to 116 characters Issues Resolved BABEL-6434 Authored-by: Anju Bharti <abanju@amazon.com>
1 parent 1786c44 commit 92a83aa

35 files changed

Lines changed: 1347 additions & 155 deletions

contrib/babelfishpg_tsql/src/backend_parser/gram-tsql-epilogue.y.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ construct_unique_index_name(char *index_name, char *relation_name)
6060
index_len = strlen(index_name);
6161
relation_len = strlen(relation_name);
6262

63+
/* Validate original index name against T-SQL 128-char limit */
64+
if (pg_mbstrlen_with_len(index_name, index_len) > 128)
65+
{
66+
int cliplen = pg_mbcliplen(index_name, index_len, 128);
67+
68+
ereport(ERROR,
69+
(errcode(ERRCODE_NAME_TOO_LONG),
70+
errmsg("The identifier that starts with '%.*s' is too long. Maximum length is 128.",
71+
cliplen, index_name)));
72+
}
73+
6374
success = pg_md5_hash(index_name, index_len, md5, &errstr);
6475
if (unlikely(!success))
6576
{ /* OOM */

contrib/babelfishpg_tsql/src/backend_parser/gram-tsql-prologue.y.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "access/htup_details.h"
88
#include "catalog/pg_type.h"
9+
#include "mb/pg_wchar.h"
910
#include "parser/parse_type.h"
1011
#include "parser/scansup.h"
1112
#include "utils/builtins.h"

contrib/babelfishpg_tsql/src/backend_parser/scan-tsql-prologue-top.l.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,16 @@
66
#include "common/string.h"
77
#include "nodes/parsenodes.h"
88
#include "src/backend_parser/gramparse.h"
9+
10+
#define CHECK_LOCAL_TEMP_TABLE_LENGTH(ident) \
11+
do { \
12+
if ((ident)[0] == '#' && (ident)[1] != '#' && \
13+
pg_mbstrlen(ident) > 116) \
14+
{ \
15+
int cliplen = pg_mbcliplen((ident), strlen(ident), 116); \
16+
ereport(ERROR, \
17+
(errcode(ERRCODE_NAME_TOO_LONG), \
18+
errmsg("The identifier that starts with '%.*s' is too long. Maximum length for local temporary table is 116.", \
19+
cliplen, (ident)))); \
20+
} \
21+
} while (0)

contrib/babelfishpg_tsql/src/backend_parser/scan-tsql-rule.l

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
if (yyextra->literallen == 0)
7777
yyerror("zero-length delimited identifier");
7878
ident = litbufdup(yyscanner);
79+
CHECK_LOCAL_TEMP_TABLE_LENGTH(ident);
7980
if (yyextra->literallen >= NAMEDATALEN)
8081
truncate_identifier(ident, yyextra->literallen, true);
8182
yylval->str = ident;
@@ -152,6 +153,7 @@
152153

153154
<tsql>{tsql_ttname} {
154155
SET_YYLLOC();
156+
CHECK_LOCAL_TEMP_TABLE_LENGTH(yytext);
155157
yylval->str = pstrdup(yytext);
156158
return IDENT;
157159
}

contrib/babelfishpg_tsql/src/cursor.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,18 @@ pltsql_declare_cursor(PLtsql_execstate *estate, PLtsql_var *var, PLtsql_expr *ex
194194
Portal portal;
195195
char mangled_name[NAMEDATALEN];
196196

197+
/* Enforce 128-character limit on cursor name */
198+
Assert(var->refname != NULL);
199+
if (pg_mbstrlen(var->refname) > 128)
200+
{
201+
int cliplen = pg_mbcliplen(var->refname, strlen(var->refname), 128);
202+
203+
ereport(ERROR,
204+
(errcode(ERRCODE_NAME_TOO_LONG),
205+
errmsg("The identifier that starts with '%.*s' is too long. Maximum length is 128.",
206+
cliplen, var->refname)));
207+
}
208+
197209
if (!var->isnull)
198210
{
199211
curname = TextDatumGetCString(var->value);
@@ -223,12 +235,6 @@ pltsql_declare_cursor(PLtsql_execstate *estate, PLtsql_var *var, PLtsql_expr *ex
223235
* cursor, its lifespan is longer so we have to use different memory
224236
* context.
225237
*/
226-
Assert(var->refname != NULL);
227-
if (strlen(var->refname) + strlen(LOCAL_CURSOR_INFIX) + 19 > NAMEDATALEN)
228-
ereport(ERROR,
229-
(errcode(ERRCODE_INTERNAL_ERROR),
230-
errmsg("internal cursor name is too long: %s", var->refname)));
231-
232238
snprintf(mangled_name, NAMEDATALEN, "%s%s%p", var->refname, LOCAL_CURSOR_INFIX, var);
233239

234240
assign_text_var(estate, var, mangled_name);

contrib/babelfishpg_tsql/src/multidb.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "postgres.h"
22

3+
#include "mb/pg_wchar.h"
34
#include "miscadmin.h"
45
#include "nodes/parsenodes.h"
56
#include "nodes/primnodes.h"
@@ -1195,6 +1196,17 @@ get_physical_schema_name_by_mode(char *db_name, const char *schema_name, Migrati
11951196
if (len == 0)
11961197
return NULL;
11971198

1199+
/* Validate original schema name against T-SQL 128-char limit */
1200+
if (pg_mbstrlen_with_len(schema_name, len) > 128)
1201+
{
1202+
int cliplen = pg_mbcliplen(schema_name, len, 128);
1203+
1204+
ereport(ERROR,
1205+
(errcode(ERRCODE_NAME_TOO_LONG),
1206+
errmsg("The identifier that starts with '%.*s' is too long. Maximum length is 128.",
1207+
cliplen, schema_name)));
1208+
}
1209+
11981210
/* always return a new copy */
11991211
len = len > MAX_BBF_NAMEDATALEND ? len : MAX_BBF_NAMEDATALEND;
12001212
name = palloc0(len + 1);

contrib/babelfishpg_tsql/src/pl_exec-2.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4388,11 +4388,14 @@ exec_stmt_partition_function(PLtsql_execstate *estate, PLtsql_stmt_partition_fun
43884388
*/
43894389

43904390
/* check if given name is exceeding the allowed limit */
4391-
if (strlen(partition_function_name) > 128)
4391+
if (pg_mbstrlen(partition_function_name) > 128)
43924392
{
4393-
ereport(ERROR,
4394-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4395-
errmsg("The identifier that starts with '%.128s' is too long. Maximum length is 128.", partition_function_name)));
4393+
int cliplen = pg_mbcliplen(partition_function_name, strlen(partition_function_name), 128);
4394+
4395+
ereport(ERROR,
4396+
(errcode(ERRCODE_NAME_TOO_LONG),
4397+
errmsg("The identifier that starts with '%.*s' is too long. Maximum length is 128.",
4398+
cliplen, partition_function_name)));
43964399
}
43974400

43984401
/*
@@ -4645,12 +4648,14 @@ exec_stmt_partition_scheme(PLtsql_execstate *estate, PLtsql_stmt_partition_schem
46454648
*/
46464649

46474650
/* check if given name is exceeding the allowed limit */
4648-
if (strlen(partition_scheme_name) > 128)
4651+
if (pg_mbstrlen(partition_scheme_name) > 128)
46494652
{
4650-
ereport(ERROR,
4651-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4652-
errmsg("The identifier that starts with '%.128s' is too long. Maximum length is 128.",
4653-
partition_scheme_name)));
4653+
int cliplen = pg_mbcliplen(partition_scheme_name, strlen(partition_scheme_name), 128);
4654+
4655+
ereport(ERROR,
4656+
(errcode(ERRCODE_NAME_TOO_LONG),
4657+
errmsg("The identifier that starts with '%.*s' is too long. Maximum length is 128.",
4658+
cliplen, partition_scheme_name)));
46544659
}
46554660

46564661
/* raise error if provided partition function doesn't exists in the current database */

contrib/babelfishpg_tsql/src/pl_handler.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6170,6 +6170,22 @@ pltsql_truncate_identifier(char *ident, int len, bool warn)
61706170

61716171
Assert(len >= NAMEDATALEN); /* should be already checked */
61726172

6173+
/*
6174+
* Restrict TSQL identifier length to 128 characters.
6175+
* Only enforce for user-supplied identifiers (warn=true from scanner).
6176+
* Internally constructed identifiers (warn=false) such as combined
6177+
* index+table names may exceed 128 chars and should just be truncated.
6178+
*/
6179+
if (warn && pg_mbstrlen_with_len(ident, len) > 128)
6180+
{
6181+
int cliplen = pg_mbcliplen(ident, len, 128);
6182+
6183+
ereport(ERROR,
6184+
(errcode(ERRCODE_NAME_TOO_LONG),
6185+
errmsg("The identifier that starts with '%.*s' is too long. Maximum length is 128.",
6186+
cliplen, ident)));
6187+
}
6188+
61736189
if (tsql_is_database_or_server_collation_CI())
61746190
{
61756191
/* md5 should be generated by case-insensitive way */
@@ -6216,6 +6232,9 @@ pltsql_cstr_to_name(char *s, int len)
62166232
bool success;
62176233
const char *errstr = NULL;
62186234

6235+
/* Identifier should already be validated at the entry point */
6236+
Assert(pg_mbstrlen_with_len(s, len) <= 128);
6237+
62196238
if (tsql_is_database_or_server_collation_CI())
62206239
{
62216240
/* md5 should be generated in a case-insensitive way */

contrib/babelfishpg_tsql/src/pltsql_partition.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ construct_unique_hash(char *relation_name)
379379
bool success;
380380
const char *errstr = NULL;
381381

382+
/* Identifier should already be validated at the entry point */
383+
Assert(pg_mbstrlen_with_len(relation_name, strlen(relation_name)) <= 128);
384+
382385
md5 = (char *) palloc(MD5_HASH_LEN + 1);
383386

384387
success = pg_md5_hash(relation_name, strlen(relation_name), md5, &errstr);

test/JDBC/expected/BABEL-3201-vu-verify.out

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -655,10 +655,10 @@ DBCC CHECKIDENT('[babel_DBCC_CHECK_schema .with .DOT_and_spaces]."babel_dbcc_CHE
655655
GO
656656

657657
-- db name longer then 63 and doing cross db call
658-
CREATE DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij
658+
CREATE DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8a
659659
GO
660660

661-
USE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij
661+
USE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8a
662662
GO
663663

664664
CREATE TABLE babel_3201_longer__name_db_table (a int identity, b int);
@@ -667,15 +667,15 @@ GO
667667
USE master;
668668
go
669669

670-
DBCC CHECKIDENT('babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij.dbo.babel_3201_longer__name_db_table', noreseed);
670+
DBCC CHECKIDENT('babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8a.dbo.babel_3201_longer__name_db_table', noreseed);
671671
GO
672672

673673
-- db name longer and mixed case as well.
674-
DBCC CHECKIDENT('bAbEl_dBcC_ChEcKiDeNt_dAtAbAsE_LoNgEr_tHaN_63_0AbCdEfGiJ1AbCdEfGiJ2AbCdEfGiJ3AbCdEfGiJ4AbCdEfGiJ5AbCdEfGiJ6AbCdEfGiJ7AbCdEfGiJ8AbCdEfGhIj9aBcDeFgHiJ.dbo.babel_3201_longer__name_db_table', noreseed);
674+
DBCC CHECKIDENT('babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8a.dbo.babel_3201_longer__name_db_table', noreseed);
675675
GO
676676

677677
-- drop this db because of single_db mode
678-
DROP DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8abcdefghij9abcdefghij
678+
DROP DATABASE babel_dbcc_checkident_database_longer_than_63_0abcdefgij1abcdefgij2abcdefgij3abcdefgij4abcdefgij5abcdefgij6abcdefgij7abcdefgij8a
679679
GO
680680

681681
-- create database to test cross db behavior.

0 commit comments

Comments
 (0)