@@ -88,6 +88,7 @@ struct upload_pack_data {
88
88
enum allow_uor allow_uor ;
89
89
90
90
struct list_objects_filter_options filter_options ;
91
+ struct string_list allowed_filters ;
91
92
92
93
struct packet_writer writer ;
93
94
@@ -103,6 +104,8 @@ struct upload_pack_data {
103
104
unsigned no_progress : 1 ;
104
105
unsigned use_include_tag : 1 ;
105
106
unsigned allow_filter : 1 ;
107
+ unsigned allow_filter_fallback : 1 ;
108
+ unsigned long tree_filter_max_depth ;
106
109
107
110
unsigned done : 1 ; /* v2 only */
108
111
unsigned allow_ref_in_want : 1 ; /* v2 only */
@@ -120,6 +123,7 @@ static void upload_pack_data_init(struct upload_pack_data *data)
120
123
struct string_list deepen_not = STRING_LIST_INIT_DUP ;
121
124
struct string_list uri_protocols = STRING_LIST_INIT_DUP ;
122
125
struct object_array extra_edge_obj = OBJECT_ARRAY_INIT ;
126
+ struct string_list allowed_filters = STRING_LIST_INIT_DUP ;
123
127
124
128
memset (data , 0 , sizeof (* data ));
125
129
data -> symref = symref ;
@@ -131,6 +135,9 @@ static void upload_pack_data_init(struct upload_pack_data *data)
131
135
data -> deepen_not = deepen_not ;
132
136
data -> uri_protocols = uri_protocols ;
133
137
data -> extra_edge_obj = extra_edge_obj ;
138
+ data -> allowed_filters = allowed_filters ;
139
+ data -> allow_filter_fallback = 1 ;
140
+ data -> tree_filter_max_depth = ULONG_MAX ;
134
141
packet_writer_init (& data -> writer , 1 );
135
142
136
143
data -> keepalive = 5 ;
@@ -147,6 +154,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
147
154
string_list_clear (& data -> deepen_not , 0 );
148
155
object_array_clear (& data -> extra_edge_obj );
149
156
list_objects_filter_release (& data -> filter_options );
157
+ string_list_clear (& data -> allowed_filters , 1 );
150
158
151
159
free ((char * )data -> pack_objects_hook );
152
160
}
@@ -983,6 +991,63 @@ static int process_deepen_not(const char *line, struct string_list *deepen_not,
983
991
return 0 ;
984
992
}
985
993
994
+ NORETURN __attribute__((format (printf ,2 ,3 )))
995
+ static void send_err_and_die (struct upload_pack_data * data ,
996
+ const char * fmt , ...)
997
+ {
998
+ struct strbuf buf = STRBUF_INIT ;
999
+ va_list ap ;
1000
+
1001
+ va_start (ap , fmt );
1002
+ strbuf_vaddf (& buf , fmt , ap );
1003
+ va_end (ap );
1004
+
1005
+ packet_writer_error (& data -> writer , "%s" , buf .buf );
1006
+ die ("%s" , buf .buf );
1007
+ }
1008
+
1009
+ static void check_one_filter (struct upload_pack_data * data ,
1010
+ struct list_objects_filter_options * opts )
1011
+ {
1012
+ const char * key = list_object_filter_config_name (opts -> choice );
1013
+ struct string_list_item * item = string_list_lookup (& data -> allowed_filters ,
1014
+ key );
1015
+ int allowed ;
1016
+
1017
+ if (item )
1018
+ allowed = (intptr_t )item -> util ;
1019
+ else
1020
+ allowed = data -> allow_filter_fallback ;
1021
+
1022
+ if (!allowed )
1023
+ send_err_and_die (data , "filter '%s' not supported" , key );
1024
+
1025
+ if (opts -> choice == LOFC_TREE_DEPTH &&
1026
+ opts -> tree_exclude_depth > data -> tree_filter_max_depth )
1027
+ send_err_and_die (data ,
1028
+ "tree filter allows max depth %lu, but got %lu" ,
1029
+ data -> tree_filter_max_depth ,
1030
+ opts -> tree_exclude_depth );
1031
+ }
1032
+
1033
+ static void check_filter_recurse (struct upload_pack_data * data ,
1034
+ struct list_objects_filter_options * opts )
1035
+ {
1036
+ size_t i ;
1037
+
1038
+ check_one_filter (data , opts );
1039
+ if (opts -> choice != LOFC_COMBINE )
1040
+ return ;
1041
+
1042
+ for (i = 0 ; i < opts -> sub_nr ; i ++ )
1043
+ check_filter_recurse (data , & opts -> sub [i ]);
1044
+ }
1045
+
1046
+ static void die_if_using_banned_filter (struct upload_pack_data * data )
1047
+ {
1048
+ check_filter_recurse (data , & data -> filter_options );
1049
+ }
1050
+
986
1051
static void receive_needs (struct upload_pack_data * data ,
987
1052
struct packet_reader * reader )
988
1053
{
@@ -1013,6 +1078,7 @@ static void receive_needs(struct upload_pack_data *data,
1013
1078
die ("git upload-pack: filtering capability not negotiated" );
1014
1079
list_objects_filter_die_if_populated (& data -> filter_options );
1015
1080
parse_list_objects_filter (& data -> filter_options , arg );
1081
+ die_if_using_banned_filter (data );
1016
1082
continue ;
1017
1083
}
1018
1084
@@ -1170,6 +1236,41 @@ static int find_symref(const char *refname, const struct object_id *oid,
1170
1236
return 0 ;
1171
1237
}
1172
1238
1239
+ static int parse_object_filter_config (const char * var , const char * value ,
1240
+ struct upload_pack_data * data )
1241
+ {
1242
+ struct strbuf buf = STRBUF_INIT ;
1243
+ const char * sub , * key ;
1244
+ size_t sub_len ;
1245
+
1246
+ if (parse_config_key (var , "uploadpackfilter" , & sub , & sub_len , & key ))
1247
+ return 0 ;
1248
+
1249
+ if (!sub ) {
1250
+ if (!strcmp (key , "allow" ))
1251
+ data -> allow_filter_fallback = git_config_bool (var , value );
1252
+ return 0 ;
1253
+ }
1254
+
1255
+ strbuf_add (& buf , sub , sub_len );
1256
+
1257
+ if (!strcmp (key , "allow" ))
1258
+ string_list_insert (& data -> allowed_filters , buf .buf )-> util =
1259
+ (void * )(intptr_t )git_config_bool (var , value );
1260
+ else if (!strcmp (buf .buf , "tree" ) && !strcmp (key , "maxdepth" )) {
1261
+ if (!value ) {
1262
+ strbuf_release (& buf );
1263
+ return config_error_nonbool (var );
1264
+ }
1265
+ string_list_insert (& data -> allowed_filters , buf .buf )-> util =
1266
+ (void * )(intptr_t )1 ;
1267
+ data -> tree_filter_max_depth = git_config_ulong (var , value );
1268
+ }
1269
+
1270
+ strbuf_release (& buf );
1271
+ return 0 ;
1272
+ }
1273
+
1173
1274
static int upload_pack_config (const char * var , const char * value , void * cb_data )
1174
1275
{
1175
1276
struct upload_pack_data * data = cb_data ;
@@ -1209,6 +1310,8 @@ static int upload_pack_config(const char *var, const char *value, void *cb_data)
1209
1310
return git_config_string (& data -> pack_objects_hook , var , value );
1210
1311
}
1211
1312
1313
+ parse_object_filter_config (var , value , data );
1314
+
1212
1315
return parse_hide_refs_config (var , value , "uploadpack" );
1213
1316
}
1214
1317
@@ -1389,6 +1492,7 @@ static void process_args(struct packet_reader *request,
1389
1492
if (data -> allow_filter && skip_prefix (arg , "filter " , & p )) {
1390
1493
list_objects_filter_die_if_populated (& data -> filter_options );
1391
1494
parse_list_objects_filter (& data -> filter_options , p );
1495
+ die_if_using_banned_filter (data );
1392
1496
continue ;
1393
1497
}
1394
1498
0 commit comments