@@ -1092,6 +1092,75 @@ int git_config_set(const char *key, const char *value)
1092
1092
return git_config_set_multivar (key , value , NULL , 0 );
1093
1093
}
1094
1094
1095
+ /*
1096
+ * Auxiliary function to sanity-check and split the key into the section
1097
+ * identifier and variable name.
1098
+ *
1099
+ * Returns 0 on success, -1 when there is an invalid character in the key and
1100
+ * -2 if there is no section name in the key.
1101
+ *
1102
+ * store_key - pointer to char* which will hold a copy of the key with
1103
+ * lowercase section and variable name
1104
+ * baselen - pointer to int which will hold the length of the
1105
+ * section + subsection part, can be NULL
1106
+ */
1107
+ int git_config_parse_key (const char * key , char * * store_key , int * baselen_ )
1108
+ {
1109
+ int i , dot , baselen ;
1110
+ const char * last_dot = strrchr (key , '.' );
1111
+
1112
+ /*
1113
+ * Since "key" actually contains the section name and the real
1114
+ * key name separated by a dot, we have to know where the dot is.
1115
+ */
1116
+
1117
+ if (last_dot == NULL || last_dot == key ) {
1118
+ error ("key does not contain a section: %s" , key );
1119
+ return -2 ;
1120
+ }
1121
+
1122
+ if (!last_dot [1 ]) {
1123
+ error ("key does not contain variable name: %s" , key );
1124
+ return -2 ;
1125
+ }
1126
+
1127
+ baselen = last_dot - key ;
1128
+ if (baselen_ )
1129
+ * baselen_ = baselen ;
1130
+
1131
+ /*
1132
+ * Validate the key and while at it, lower case it for matching.
1133
+ */
1134
+ * store_key = xmalloc (strlen (key ) + 1 );
1135
+
1136
+ dot = 0 ;
1137
+ for (i = 0 ; key [i ]; i ++ ) {
1138
+ unsigned char c = key [i ];
1139
+ if (c == '.' )
1140
+ dot = 1 ;
1141
+ /* Leave the extended basename untouched.. */
1142
+ if (!dot || i > baselen ) {
1143
+ if (!iskeychar (c ) ||
1144
+ (i == baselen + 1 && !isalpha (c ))) {
1145
+ error ("invalid key: %s" , key );
1146
+ goto out_free_ret_1 ;
1147
+ }
1148
+ c = tolower (c );
1149
+ } else if (c == '\n' ) {
1150
+ error ("invalid key (newline): %s" , key );
1151
+ goto out_free_ret_1 ;
1152
+ }
1153
+ (* store_key )[i ] = c ;
1154
+ }
1155
+ (* store_key )[i ] = 0 ;
1156
+
1157
+ return 0 ;
1158
+
1159
+ out_free_ret_1 :
1160
+ free (* store_key );
1161
+ return -1 ;
1162
+ }
1163
+
1095
1164
/*
1096
1165
* If value==NULL, unset in (remove from) config,
1097
1166
* if value_regex!=NULL, disregard key/value pairs where value does not match.
@@ -1118,59 +1187,23 @@ int git_config_set(const char *key, const char *value)
1118
1187
int git_config_set_multivar (const char * key , const char * value ,
1119
1188
const char * value_regex , int multi_replace )
1120
1189
{
1121
- int i , dot ;
1122
1190
int fd = -1 , in_fd ;
1123
1191
int ret ;
1124
1192
char * config_filename ;
1125
1193
struct lock_file * lock = NULL ;
1126
- const char * last_dot = strrchr (key , '.' );
1127
1194
1128
1195
if (config_exclusive_filename )
1129
1196
config_filename = xstrdup (config_exclusive_filename );
1130
1197
else
1131
1198
config_filename = git_pathdup ("config" );
1132
1199
1133
- /*
1134
- * Since "key" actually contains the section name and the real
1135
- * key name separated by a dot, we have to know where the dot is.
1136
- */
1137
-
1138
- if (last_dot == NULL ) {
1139
- error ("key does not contain a section: %s" , key );
1140
- ret = 2 ;
1200
+ /* parse-key returns negative; flip the sign to feed exit(3) */
1201
+ ret = 0 - git_config_parse_key (key , & store .key , & store .baselen );
1202
+ if (ret )
1141
1203
goto out_free ;
1142
- }
1143
- store .baselen = last_dot - key ;
1144
1204
1145
1205
store .multi_replace = multi_replace ;
1146
1206
1147
- /*
1148
- * Validate the key and while at it, lower case it for matching.
1149
- */
1150
- store .key = xmalloc (strlen (key ) + 1 );
1151
- dot = 0 ;
1152
- for (i = 0 ; key [i ]; i ++ ) {
1153
- unsigned char c = key [i ];
1154
- if (c == '.' )
1155
- dot = 1 ;
1156
- /* Leave the extended basename untouched.. */
1157
- if (!dot || i > store .baselen ) {
1158
- if (!iskeychar (c ) || (i == store .baselen + 1 && !isalpha (c ))) {
1159
- error ("invalid key: %s" , key );
1160
- free (store .key );
1161
- ret = 1 ;
1162
- goto out_free ;
1163
- }
1164
- c = tolower (c );
1165
- } else if (c == '\n' ) {
1166
- error ("invalid key (newline): %s" , key );
1167
- free (store .key );
1168
- ret = 1 ;
1169
- goto out_free ;
1170
- }
1171
- store .key [i ] = c ;
1172
- }
1173
- store .key [i ] = 0 ;
1174
1207
1175
1208
/*
1176
1209
* The lock serves a purpose in addition to locking: the new
0 commit comments