@@ -14,18 +14,49 @@ static const char *const g_allowed_casts[] = {
1414 "ftod" , "dtof" ,
1515 "int4_numeric" , "float4_numeric" , "float8_numeric" ,
1616 "numeric_float4" , "numeric_float8" ,
17+ "date_timestamptz" ,
1718 /**/
1819};
1920
20- static const char * const g_allowed_builtins [] = {
21+ typedef struct FunctionByName
22+ {
23+ const char * name ;
24+ int primary_arg ;
25+ } FunctionByName ;
26+
27+ typedef struct FunctionByOid
28+ {
29+ Oid funcid ;
30+ int primary_arg ;
31+ } FunctionByOid ;
32+
33+ static const FunctionByName g_allowed_builtins [] = {
2134 /* rounding casts */
22- "ftoi2" , "ftoi4" , "ftoi8" , "dtoi2" , "dtoi4" , "dtoi8" , "numeric_int4" ,
35+ (FunctionByName ){.name = "ftoi2" , .primary_arg = 0 },
36+ (FunctionByName ){.name = "ftoi4" , .primary_arg = 0 },
37+ (FunctionByName ){.name = "ftoi8" , .primary_arg = 0 },
38+ (FunctionByName ){.name = "dtoi2" , .primary_arg = 0 },
39+ (FunctionByName ){.name = "dtoi4" , .primary_arg = 0 },
40+ (FunctionByName ){.name = "dtoi8" , .primary_arg = 0 },
41+ (FunctionByName ){.name = "numeric_int4" , .primary_arg = 0 },
2342 /* substring */
24- "text_substr" , "text_substr_no_len" , "bytea_substr" , "bytea_substr_no_len" ,
43+ (FunctionByName ){.name = "text_substr" , .primary_arg = 0 },
44+ (FunctionByName ){.name = "text_substr_no_len" , .primary_arg = 0 },
45+ (FunctionByName ){.name = "bytea_substr" , .primary_arg = 0 },
46+ (FunctionByName ){.name = "bytea_substr_no_len" , .primary_arg = 0 },
2547 /* numeric generalization */
26- "dround" , "numeric_round" , "dceil" , "numeric_ceil" , "dfloor" , "numeric_floor" ,
48+ (FunctionByName ){.name = "dround" , .primary_arg = 0 },
49+ (FunctionByName ){.name = "numeric_round" , .primary_arg = 0 },
50+ (FunctionByName ){.name = "dceil" , .primary_arg = 0 },
51+ (FunctionByName ){.name = "numeric_ceil" , .primary_arg = 0 },
52+ (FunctionByName ){.name = "dfloor" , .primary_arg = 0 },
53+ (FunctionByName ){.name = "numeric_floor" , .primary_arg = 0 },
2754 /* width_bucket */
28- "width_bucket_float8" , "width_bucket_numeric" ,
55+ (FunctionByName ){.name = "width_bucket_float8" , .primary_arg = 0 },
56+ (FunctionByName ){.name = "width_bucket_numeric" , .primary_arg = 0 },
57+ /* date_trunc */
58+ (FunctionByName ){.name = "timestamptz_trunc" , .primary_arg = 1 },
59+ (FunctionByName ){.name = "timestamp_trunc" , .primary_arg = 1 },
2960 /**/
3061};
3162
@@ -42,7 +73,7 @@ static const char *const g_implicit_range_builtins_untrusted[] = {
4273
4374/* Some allowed functions don't appear in the builtins catalog, so we must allow them manually by OID. */
4475#define F_NUMERIC_ROUND_INT 1708
45- static const Oid g_allowed_builtins_extra [] = {F_NUMERIC_ROUND_INT };
76+ static const FunctionByOid g_allowed_builtins_extra [] = {( FunctionByOid ){. funcid = F_NUMERIC_ROUND_INT , . primary_arg = 0 } };
4677
4778typedef struct AllowedCols
4879{
@@ -116,6 +147,21 @@ static const FmgrBuiltin *fmgr_isbuiltin(Oid id)
116147 return & fmgr_builtins [index ];
117148}
118149
150+ static bool is_func_member_of (Oid funcoid , const FunctionByName func_array [], int length )
151+ {
152+ const FmgrBuiltin * fmgr_builtin = fmgr_isbuiltin (funcoid );
153+ if (fmgr_builtin != NULL )
154+ {
155+ for (int i = 0 ; i < length ; i ++ )
156+ {
157+ if (strcmp (func_array [i ].name , fmgr_builtin -> funcName ) == 0 )
158+ return true;
159+ }
160+ }
161+
162+ return false;
163+ }
164+
119165static bool is_funcname_member_of (Oid funcoid , const char * const name_array [], int length )
120166{
121167 const FmgrBuiltin * fmgr_builtin = fmgr_isbuiltin (funcoid );
@@ -131,6 +177,33 @@ static bool is_funcname_member_of(Oid funcoid, const char *const name_array[], i
131177 return false;
132178}
133179
180+ int primary_arg_index (Oid funcoid )
181+ {
182+ for (int i = 0 ; i < ARRAY_LENGTH (g_implicit_range_udfs ); i ++ )
183+ {
184+ /* We ensured that our UDFs have the primary arg first. */
185+ if (* g_implicit_range_udfs [i ] == funcoid )
186+ return 0 ;
187+ }
188+
189+ const FmgrBuiltin * fmgr_builtin = fmgr_isbuiltin (funcoid );
190+ if (fmgr_builtin != NULL )
191+ {
192+ for (int i = 0 ; i < ARRAY_LENGTH (g_allowed_builtins ); i ++ )
193+ {
194+ if (strcmp (g_allowed_builtins [i ].name , fmgr_builtin -> funcName ) == 0 )
195+ return g_allowed_builtins [i ].primary_arg ;
196+ }
197+ }
198+
199+ for (int i = 0 ; i < ARRAY_LENGTH (g_allowed_builtins_extra ); i ++ )
200+ {
201+ if (g_allowed_builtins_extra [i ].funcid == funcoid )
202+ return g_allowed_builtins_extra [i ].primary_arg ;
203+ }
204+ FAILWITH ("Cannot identify the primary argument position for funcid %u." , funcoid );
205+ }
206+
134207bool is_allowed_cast (Oid funcoid )
135208{
136209 return is_funcname_member_of (funcoid , g_allowed_casts , ARRAY_LENGTH (g_allowed_casts ));
@@ -154,12 +227,12 @@ bool is_allowed_function(Oid funcoid)
154227 return true;
155228 }
156229
157- if (is_funcname_member_of (funcoid , g_allowed_builtins , ARRAY_LENGTH (g_allowed_builtins )))
230+ if (is_func_member_of (funcoid , g_allowed_builtins , ARRAY_LENGTH (g_allowed_builtins )))
158231 return true;
159232
160233 for (int i = 0 ; i < ARRAY_LENGTH (g_allowed_builtins_extra ); i ++ )
161234 {
162- if (g_allowed_builtins_extra [i ] == funcoid )
235+ if (g_allowed_builtins_extra [i ]. funcid == funcoid )
163236 return true;
164237 }
165238
0 commit comments